diff --git a/.cursor/rules/feature-flag-rest.mdc b/.cursor/rules/feature-flag-rest.mdc new file mode 100644 index 00000000000..508c2f37f97 --- /dev/null +++ b/.cursor/rules/feature-flag-rest.mdc @@ -0,0 +1,584 @@ +--- +description: Feature flag store rest api +alwaysApply: false +--- +# Feature Flag REST API + +The Feature Flag REST API provides comprehensive CRUD operations for managing Atlas feature flags through HTTP endpoints. + +## Base URL +``` +/api/atlas/v2/featureflags +``` + +## Endpoints + +### 1. Get All Feature Flags +**GET** `/api/atlas/v2/featureflags` + +Returns all predefined feature flags with their current values and metadata. + +**Response:** +```json +{ + "featureFlags": [ + { + "key": "ENABLE_JANUS_OPTIMISATION", + "currentValue": "true", + "defaultValue": "false", + "hasCustomValue": true, + "timestamp": "2024-01-20T10:30:00.000Z" + }, + { + "key": "enable_persona_hierarchy_filter", + "currentValue": null, + "defaultValue": "false", + "hasCustomValue": false, + "timestamp": "2024-01-20T10:30:00.000Z" + } + ], + "totalCount": 2, + "timestamp": "2024-01-20T10:30:00.000Z" +} +``` + +**cURL Example:** +```bash +curl -X GET "http://localhost:21000/api/atlas/v2/featureflags" \ + -H "Content-Type: application/json" +``` + +### 2. Get Single Feature Flag +**GET** `/api/atlas/v2/featureflags/{key}` + +Returns details for a specific feature flag. + +**Parameters:** +- `key` (path parameter): Feature flag key name + +**Response:** +```json +{ + "key": "ENABLE_JANUS_OPTIMISATION", + "currentValue": "true", + "defaultValue": "false", + "hasCustomValue": true, + "timestamp": "2024-01-20T10:30:00.000Z" +} +``` + +**cURL Example:** +```bash +curl -X GET "http://localhost:21000/api/atlas/v2/featureflags/ENABLE_JANUS_OPTIMISATION" \ + -H "Content-Type: application/json" +``` + +**Error Response (Invalid Key):** +```json +{ + "errorCode": "ATLAS_400_00_001", + "errorMessage": "Invalid feature flag key: INVALID_KEY. Valid keys are: [ENABLE_JANUS_OPTIMISATION, enable_persona_hierarchy_filter, DISABLE_WRITE_FLAG]" +} +``` + +### 3. Update Feature Flag +**PUT** `/api/atlas/v2/featureflags/{key}` + +Updates or sets a feature flag value. + +**Parameters:** +- `key` (path parameter): Feature flag key name + +**Request Body:** +```json +{ + "value": "true" +} +``` + +**Response:** +```json +{ + "success": true, + "message": "Feature flag 'ENABLE_JANUS_OPTIMISATION' updated successfully to: true", + "key": "ENABLE_JANUS_OPTIMISATION", + "value": "true", + "timestamp": "2024-01-20T10:35:00.000Z" +} +``` + +**cURL Example:** +```bash +curl -X PUT "http://localhost:21000/api/atlas/v2/featureflags/ENABLE_JANUS_OPTIMISATION" \ + -H "Content-Type: application/json" \ + -d '{"value": "true"}' +``` + +### 4. Delete Feature Flag +**DELETE** `/api/atlas/v2/featureflags/{key}` + +Deletes a feature flag (resets to default value). + +**Parameters:** +- `key` (path parameter): Feature flag key name + +**Response:** +```json +{ + "success": true, + "message": "Feature flag 'ENABLE_JANUS_OPTIMISATION' deleted successfully (reset to default: false)", + "key": "ENABLE_JANUS_OPTIMISATION", + "value": "false", + "timestamp": "2024-01-20T10:40:00.000Z" +} +``` + +**cURL Example:** +```bash +curl -X DELETE "http://localhost:21000/api/atlas/v2/featureflags/ENABLE_JANUS_OPTIMISATION" \ + -H "Content-Type: application/json" +``` + +### 5. Health Check +**GET** `/api/atlas/v2/featureflags/health` + +Returns the health status of the Feature Flag service. + +**Response:** +```json +{ + "service": "FeatureFlagREST", + "status": "UP", + "timestamp": "2024-01-20T10:30:00.000Z", + "availableFlags": 3 +} +``` + +**cURL Example:** +```bash +curl -X GET "http://localhost:21000/api/atlas/v2/featureflags/health" \ + -H "Content-Type: application/json" +``` + +## Available Feature Flags + +The following feature flags are currently defined in the system: + +| Key | Default Value | Description | +|-----|---------------|-------------| +| `ENABLE_JANUS_OPTIMISATION` | `false` | Enables Janus graph optimizations | +| `enable_persona_hierarchy_filter` | `false` | Enables persona hierarchy filtering | +| `DISABLE_WRITE_FLAG` | `false` | Disables write operations | + +## Error Handling + +The API uses standard HTTP status codes and returns detailed error information: + +### Common Error Responses + +**400 Bad Request - Invalid Key:** +```json +{ + "errorCode": "ATLAS_400_00_001", + "errorMessage": "Invalid feature flag key: INVALID_KEY. Valid keys are: [ENABLE_JANUS_OPTIMISATION, enable_persona_hierarchy_filter, DISABLE_WRITE_FLAG]" +} +``` + +**400 Bad Request - Empty Value:** +```json +{ + "errorCode": "ATLAS_400_00_001", + "errorMessage": "Feature flag value cannot be empty" +} +``` + +**500 Internal Server Error:** +```json +{ + "errorCode": "ATLAS_500_00_001", + "errorMessage": "Internal server error occurred" +} +``` + +## Usage Examples + +### JavaScript/Fetch API +```javascript +// Get all feature flags +async function getAllFeatureFlags() { + const response = await fetch('/api/atlas/v2/featureflags'); + return await response.json(); +} + +// Update a feature flag +async function updateFeatureFlag(key, value) { + const response = await fetch(`/api/atlas/v2/featureflags/${key}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ value: value }) + }); + return await response.json(); +} + +// Delete a feature flag +async function deleteFeatureFlag(key) { + const response = await fetch(`/api/atlas/v2/featureflags/${key}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json' + } + }); + return await response.json(); +} +``` + +### Python/Requests +```python +import requests +import json + +base_url = "http://localhost:21000/api/atlas/v2/featureflags" + +# Get all feature flags +def get_all_feature_flags(): + response = requests.get(base_url) + return response.json() + +# Update a feature flag +def update_feature_flag(key, value): + url = f"{base_url}/{key}" + data = {"value": value} + response = requests.put(url, json=data) + return response.json() + +# Delete a feature flag +def delete_feature_flag(key): + url = f"{base_url}/{key}" + response = requests.delete(url) + return response.json() +``` + +## Security Considerations + +- The API inherits Atlas security configurations +- All operations are logged with user information when available +- Feature flag modifications are audited +- Only predefined feature flags can be modified (no dynamic flag creation) + +## Performance + +- All endpoints use performance tracing with AtlasPerfTracer +- Operations are optimized for quick response times +- Feature flag reads leverage the existing cache infrastructure +- Bulk operations are supported via the "get all" endpoint + +## Integration with Existing Code + +The REST API integrates seamlessly with the existing `FeatureFlagStore` service: + +```java +// Existing code continues to work +boolean isEnabled = FeatureFlagStore.evaluate("ENABLE_JANUS_OPTIMISATION", "true"); + +// REST API provides external access to the same underlying service +// PUT /api/atlas/v2/featureflags/ENABLE_JANUS_OPTIMISATION {"value": "true"} +``` + +## Monitoring and Observability + +- All operations are logged with appropriate levels (INFO for modifications, DEBUG for reads) +- Performance metrics are collected via @Timed annotations +- Health check endpoint provides service status +- Error cases are properly logged with context information +# Feature Flag REST API + +The Feature Flag REST API provides comprehensive CRUD operations for managing Atlas feature flags through HTTP endpoints. + +## Base URL +``` +/api/atlas/v2/featureflags +``` + +## Endpoints + +### 1. Get All Feature Flags +**GET** `/api/atlas/v2/featureflags` + +Returns all predefined feature flags with their current values and metadata. + +**Response:** +```json +{ + "featureFlags": [ + { + "key": "ENABLE_JANUS_OPTIMISATION", + "currentValue": "true", + "defaultValue": "false", + "hasCustomValue": true, + "timestamp": "2024-01-20T10:30:00.000Z" + }, + { + "key": "enable_persona_hierarchy_filter", + "currentValue": null, + "defaultValue": "false", + "hasCustomValue": false, + "timestamp": "2024-01-20T10:30:00.000Z" + } + ], + "totalCount": 2, + "timestamp": "2024-01-20T10:30:00.000Z" +} +``` + +**cURL Example:** +```bash +curl -X GET "http://localhost:21000/api/atlas/v2/featureflags" \ + -H "Content-Type: application/json" +``` + +### 2. Get Single Feature Flag +**GET** `/api/atlas/v2/featureflags/{key}` + +Returns details for a specific feature flag. + +**Parameters:** +- `key` (path parameter): Feature flag key name + +**Response:** +```json +{ + "key": "ENABLE_JANUS_OPTIMISATION", + "currentValue": "true", + "defaultValue": "false", + "hasCustomValue": true, + "timestamp": "2024-01-20T10:30:00.000Z" +} +``` + +**cURL Example:** +```bash +curl -X GET "http://localhost:21000/api/atlas/v2/featureflags/ENABLE_JANUS_OPTIMISATION" \ + -H "Content-Type: application/json" +``` + +**Error Response (Invalid Key):** +```json +{ + "errorCode": "ATLAS_400_00_001", + "errorMessage": "Invalid feature flag key: INVALID_KEY. Valid keys are: [ENABLE_JANUS_OPTIMISATION, enable_persona_hierarchy_filter, DISABLE_WRITE_FLAG]" +} +``` + +### 3. Update Feature Flag +**PUT** `/api/atlas/v2/featureflags/{key}` + +Updates or sets a feature flag value. + +**Parameters:** +- `key` (path parameter): Feature flag key name + +**Request Body:** +```json +{ + "value": "true" +} +``` + +**Response:** +```json +{ + "success": true, + "message": "Feature flag 'ENABLE_JANUS_OPTIMISATION' updated successfully to: true", + "key": "ENABLE_JANUS_OPTIMISATION", + "value": "true", + "timestamp": "2024-01-20T10:35:00.000Z" +} +``` + +**cURL Example:** +```bash +curl -X PUT "http://localhost:21000/api/atlas/v2/featureflags/ENABLE_JANUS_OPTIMISATION" \ + -H "Content-Type: application/json" \ + -d '{"value": "true"}' +``` + +### 4. Delete Feature Flag +**DELETE** `/api/atlas/v2/featureflags/{key}` + +Deletes a feature flag (resets to default value). + +**Parameters:** +- `key` (path parameter): Feature flag key name + +**Response:** +```json +{ + "success": true, + "message": "Feature flag 'ENABLE_JANUS_OPTIMISATION' deleted successfully (reset to default: false)", + "key": "ENABLE_JANUS_OPTIMISATION", + "value": "false", + "timestamp": "2024-01-20T10:40:00.000Z" +} +``` + +**cURL Example:** +```bash +curl -X DELETE "http://localhost:21000/api/atlas/v2/featureflags/ENABLE_JANUS_OPTIMISATION" \ + -H "Content-Type: application/json" +``` + +### 5. Health Check +**GET** `/api/atlas/v2/featureflags/health` + +Returns the health status of the Feature Flag service. + +**Response:** +```json +{ + "service": "FeatureFlagREST", + "status": "UP", + "timestamp": "2024-01-20T10:30:00.000Z", + "availableFlags": 3 +} +``` + +**cURL Example:** +```bash +curl -X GET "http://localhost:21000/api/atlas/v2/featureflags/health" \ + -H "Content-Type: application/json" +``` + +## Available Feature Flags + +The following feature flags are currently defined in the system: + +| Key | Default Value | Description | +|-----|---------------|-------------| +| `ENABLE_JANUS_OPTIMISATION` | `false` | Enables Janus graph optimizations | +| `enable_persona_hierarchy_filter` | `false` | Enables persona hierarchy filtering | +| `DISABLE_WRITE_FLAG` | `false` | Disables write operations | + +## Error Handling + +The API uses standard HTTP status codes and returns detailed error information: + +### Common Error Responses + +**400 Bad Request - Invalid Key:** +```json +{ + "errorCode": "ATLAS_400_00_001", + "errorMessage": "Invalid feature flag key: INVALID_KEY. Valid keys are: [ENABLE_JANUS_OPTIMISATION, enable_persona_hierarchy_filter, DISABLE_WRITE_FLAG]" +} +``` + +**400 Bad Request - Empty Value:** +```json +{ + "errorCode": "ATLAS_400_00_001", + "errorMessage": "Feature flag value cannot be empty" +} +``` + +**500 Internal Server Error:** +```json +{ + "errorCode": "ATLAS_500_00_001", + "errorMessage": "Internal server error occurred" +} +``` + +## Usage Examples + +### JavaScript/Fetch API +```javascript +// Get all feature flags +async function getAllFeatureFlags() { + const response = await fetch('/api/atlas/v2/featureflags'); + return await response.json(); +} + +// Update a feature flag +async function updateFeatureFlag(key, value) { + const response = await fetch(`/api/atlas/v2/featureflags/${key}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ value: value }) + }); + return await response.json(); +} + +// Delete a feature flag +async function deleteFeatureFlag(key) { + const response = await fetch(`/api/atlas/v2/featureflags/${key}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json' + } + }); + return await response.json(); +} +``` + +### Python/Requests +```python +import requests +import json + +base_url = "http://localhost:21000/api/atlas/v2/featureflags" + +# Get all feature flags +def get_all_feature_flags(): + response = requests.get(base_url) + return response.json() + +# Update a feature flag +def update_feature_flag(key, value): + url = f"{base_url}/{key}" + data = {"value": value} + response = requests.put(url, json=data) + return response.json() + +# Delete a feature flag +def delete_feature_flag(key): + url = f"{base_url}/{key}" + response = requests.delete(url) + return response.json() +``` + +## Security Considerations + +- The API inherits Atlas security configurations +- All operations are logged with user information when available +- Feature flag modifications are audited +- Only predefined feature flags can be modified (no dynamic flag creation) + +## Performance + +- All endpoints use performance tracing with AtlasPerfTracer +- Operations are optimized for quick response times +- Feature flag reads leverage the existing cache infrastructure +- Bulk operations are supported via the "get all" endpoint + +## Integration with Existing Code + +The REST API integrates seamlessly with the existing `FeatureFlagStore` service: + +```java +// Existing code continues to work +boolean isEnabled = FeatureFlagStore.evaluate("ENABLE_JANUS_OPTIMISATION", "true"); + +// REST API provides external access to the same underlying service +// PUT /api/atlas/v2/featureflags/ENABLE_JANUS_OPTIMISATION {"value": "true"} +``` + +## Monitoring and Observability + +- All operations are logged with appropriate levels (INFO for modifications, DEBUG for reads) +- Performance metrics are collected via @Timed annotations +- Health check endpoint provides service status +- Error cases are properly logged with context information diff --git a/.cursor/rules/feature-flag.mdc b/.cursor/rules/feature-flag.mdc new file mode 100644 index 00000000000..b279515500e --- /dev/null +++ b/.cursor/rules/feature-flag.mdc @@ -0,0 +1,211 @@ +--- +description: Cache based feature flag implementation based on redis +alwaysApply: false +--- +# Feature Flag Implementation Rules + +## Core Architecture Principles + +### Feature Flag Definition +- ALL feature flags MUST be defined in the FeatureFlag enum with explicit keys and default values +- Default values are ALWAYS false unless explicitly documented otherwise +- NO dynamic feature flag creation - only predefined flags allowed +- Feature flag keys should be descriptive and follow SCREAMING_SNAKE_CASE convention + +### Dual Cache Architecture +- Primary cache: Time-bound cache (configurable TTL with jitter, typically 30 minutes) +- Fallback cache: Permanent cache storing last known Redis values +- NEVER fallback to default values during runtime - use cached values instead +- Cache operations must be atomic to prevent dirty writes + +### Redis Integration +- RedisService MUST be initialized before FeatureFlagStore (@DependsOn annotation required) +- All Redis operations include retry logic with exponential backoff +- Redis connectivity MUST be validated during startup with actual read/write/delete test +- Startup MUST fail-fast if Redis is not operational + +## Code Patterns & Conventions + +### Thread Safety +- Use `synchronized` methods instead of manual lock management for write operations +- Read operations should be lock-free for performance +- Method names ending with `Internal` indicate synchronized operations +- Cache update operations must be synchronized: `updateBothCaches()`, `setFlagInternal()`, `deleteFlagInternal()` + +### Error Handling +- Constructor validation: Use `Objects.requireNonNull()` for critical dependencies +- Startup validation: Comprehensive dependency and connectivity testing +- Runtime validation: Null checks and state validation with clear error messages +- NO silent failures - log all errors with appropriate levels (WARN for retries, ERROR for failures) + +### Method Naming Conventions +```java +// Public static API methods (validation + delegation) +public static String getFlag(String key) +public static boolean evaluate(String key, String expectedValue) +public static void setFlag(String key, String value) + +// Private synchronized implementation methods +private synchronized void setFlagInternal(String key, String value) +private synchronized void deleteFlagInternal(String key) +private synchronized void updateBothCaches(String namespacedKey, String value) + +// Validation and utility methods +private static boolean isValidFlag(String key) +private void validateDependencies() +``` + +### Spring Integration Patterns +- Use `@DependsOn("redisService")` to ensure proper initialization order +- Use `@PostConstruct` for initialization with comprehensive validation +- Use `@Component` for Spring bean registration +- Use `@Inject` for constructor dependency injection +- ApplicationContextProvider pattern for static method access to Spring beans + +### Configuration Management +- All configuration values must have sensible defaults +- Configuration validation during startup (retry attempts > 0, timeouts > 0) +- Cache sizes and TTL values should be configurable via application properties +- Property names follow pattern: `atlas.feature.flag.{component}.{property}` + +### Validation Patterns +```java +// Flag validation - reject unknown flags immediately +if (!isValidFlag(key)) { + LOG.error("Invalid feature flag requested: '{}'", key); + return null; // or appropriate default +} + +// Null safety - fail fast with descriptive messages +Objects.requireNonNull(redisService, "RedisService cannot be null - critical dependency missing!"); + +// State validation - prevent operations on uninitialized objects +if (!initialized) { + throw new IllegalStateException("FeatureFlagStore not initialized"); +} +``` + +### Retry Logic Patterns +- Use simple for-loop: `for (int attempt = 1; attempt <= maxAttempts; attempt++)` +- Early return on success: `return redisService.getValue(key);` +- Last attempt handling: `boolean isLastAttempt = (attempt == maxAttempts);` +- Clear logging differentiation: WARN for retries, ERROR for final failures +- Thread interruption handling with proper cleanup + +### Logging Standards +- Startup: INFO level for successful initialization with timing +- Errors: ERROR level with full exception details and context +- Retries: WARN level with attempt numbers and total attempts +- Debug: DEBUG level for cache hits/misses and internal operations +- Health checks: DEBUG level to avoid log noise + +## API Design Principles + +### Public Static API +- Keep public methods simple and focused +- Always validate inputs before processing +- Return null for invalid requests (don't throw exceptions in getters) +- Provide convenience methods for common use cases + +### Internal Implementation +- Separate concerns: validation, caching, Redis operations +- Use meaningful method names that indicate thread safety +- Keep synchronized blocks minimal and focused +- Handle all exceptions gracefully with appropriate logging + +## Performance & Reliability + +### Caching Strategy +- Read path: Primary cache → Redis → Fallback cache → null +- Write path: Redis + Both caches (atomic) +- Cache invalidation: Remove from both caches simultaneously. Only current k8s pod updates both caches in real-time. Other pods will have wait for cache expiration +- No cache stampeding - single writer per flag per Atlas pod + +### Startup Reliability +- Fail-fast: Application won't start with broken feature flags store initialization. +- Comprehensive testing: Redis connectivity + configuration validation +- Clear error messages: Operators can quickly identify and fix issues +- Timeout protection: Prevent infinite startup hangs + +### Runtime Reliability +- Graceful degradation: Use cached values when Redis is unavailable +- Health monitoring: Provide methods for operational visibility +- Exception isolation: One bad flag doesn't break others +- Thread safety: Concurrent access without data corruption + +## Testing & Monitoring + +### Health Check Integration +```java +// Operational health checks +public static boolean isFeatureFlagStoreHealthy() +public boolean isRedisHealthy() +public boolean isInitialized() +``` + +### Debugging Support +- Comprehensive startup logging with timing information +- Clear error messages with actionable information +- Health check methods for operational monitoring +- Flag access logging for usage analysis + +## Anti-Patterns to Avoid + +❌ Manual lock management (`lock.lock(); try { ... } finally { lock.unlock(); }`) +❌ Default fallbacks during runtime (use cached values instead) +❌ Dynamic feature flag creation (only predefined flags) +❌ Silent failures (always log errors appropriately) +❌ Complex async initialization (keep startup simple and sequential) +❌ Missing dependency validation (always validate critical dependencies) +❌ Tight coupling between components (use clear interfaces) +❌ Runtime exceptions for normal operations (reserve for serious errors) + +## Example Implementation Template + +```java +@Component +@DependsOn("redisService") +public class FeatureService { + + private final RedisService redisService; + + @Inject + public FeatureService(RedisService redisService) { + this.redisService = Objects.requireNonNull(redisService, + "RedisService cannot be null - critical dependency missing!"); + } + + @PostConstruct + public void initialize() { + try { + validateDependencies(); + // ... initialization logic + initialized = true; + } catch (Exception e) { + throw new RuntimeException("Failed to initialize - cannot start application", e); + } + } + + public static ReturnType publicMethod(String key) { + if (!isValidInput(key)) { + LOG.warn("Invalid input: '{}'", key); + return appropriateDefault; + } + + Instance instance = getInstance(); + if (instance == null) { + LOG.warn("Service not initialized"); + return appropriateDefault; + } + + return instance.internalMethod(key); + } + + private synchronized void writeOperation(String key, String value) { + // Synchronized method for write operations + // Clean, focused implementation + } +} +``` + +Follow these rules to maintain consistency, reliability, and performance in the feature flag system. diff --git a/.cursor/rules/search-apis.mdc b/.cursor/rules/search-apis.mdc new file mode 100644 index 00000000000..05e0fa1d5ca --- /dev/null +++ b/.cursor/rules/search-apis.mdc @@ -0,0 +1,62 @@ +--- +alwaysApply: false +description: search-apis +--- +# Search APIs and ES Integration + +This rule documents the search API implementations and ES integration to help navigation and consistent usage across the repo. + +## Endpoints + +- POST `/search/indexsearch` → Atlas-shaped search using DSL. See [DiscoveryREST.java](mdc:webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java) +- POST `/search/es` → Raw ES search response passthrough, trimmed to the `hits` object if present. See [DiscoveryREST.java](mdc:webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java) +- POST `/search/count` → ES `_count` API; returns `{ "count": }`. See [DiscoveryREST.java](mdc:webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java) +- POST `/search/relationship/indexsearch` → Edge index search. See [DiscoveryREST.java](mdc:webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java) + +## Service Flow + +Service implementation: [EntityDiscoveryService.java](mdc:repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java) + +- `directIndexSearch(params, useVertexEdgeBulkFetching)` → standard Atlas result shaping +- `directEsIndexSearch(params)` → returns raw ES map from index query +- `directCountIndexSearch(params)` → returns `Long` count + +Common behavior (all three): +- Index selection via `getIndexName(IndexSearchParams)`; supports persona/purpose and access control exclusive DSL +- Optional pre-filtering when `enableFullRestriction` is true via `addPreFiltersToSearchQuery` +- Optional DSL optimization when feature flag is enabled and request originates from product client (see below) +- Error handling: propagate exceptions; upstream layers map network/ES errors to appropriate codes + +### DSL Optimization + +Reusable helper: `optimizeQueryIfApplicable(SearchParams, clientOrigin)` in [EntityDiscoveryService.java](mdc:repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java) + +- Controlled by feature flag key `discovery_use_dsl_optimisation` +- Only applied when `RequestContext.clientOrigin == product_webapp` +- Uses `ElasticsearchDslOptimizer.optimizeQueryWithValidation(...)` +- On validation failure: logs a warning and continues +- On optimizer error: logs and proceeds with original query + +## ES Layer + +Implementation: [AtlasElasticsearchQuery.java](mdc:graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasElasticsearchQuery.java) + +- `vertices(SearchParams)` → executes query via low-level client, returns `DirectIndexQueryResult` +- `directIndexQuery(String)` → returns parsed ES response with `total`, `data`, optional `aggregations` +- `directEsIndexQuery(String)` → returns raw ES response as `Map` (unmodified) +- `countIndexQuery(String)` → calls `/_count`, parses and returns `Long` +- Request isolation: selects ES client based on `RequestContext.clientOrigin`; `product_webapp` → UI cluster; others → Non-UI cluster; fallback to default client +- Network errors: mapped to `SERVICE_UNAVAILABLE` or gateway timeout codes + +Note: The Janus in-memory index implementation ([AtlasJanusIndexQuery.java](mdc:graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusIndexQuery.java)) does not implement `directEsIndexQuery`/`countIndexQuery` (throws `NotImplementedException`). + +## REST Response Shaping + +- `/search/es` returns only the `hits` object when present; otherwise returns the full ES response map +- `/search/count` wraps the `Long` in `{ "count": }` + +## Limits and Logging + +- Query size limits enforced when `ATLAS_INDEXSEARCH_ENABLE_API_LIMIT` is true; see `ATLAS_INDEXSEARCH_QUERY_SIZE_MAX_LIMIT` and `ATLAS_INDEXSEARCH_LIMIT_UTM_TAGS` +- Optional search logging; some utmTag patterns skip logging; see `shouldSkipSearchLog` in [DiscoveryREST.java](mdc:webapp/src/main/java/org/apache/atlas/web/rest/DiscoveryREST.java) + diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000000..e50cf0411f3 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,100 @@ +# Use `allow` to specify which dependencies to maintain + +version: 2 +updates: + - package-ecosystem: "npm" #npm + directory: "/" + schedule: + interval: "daily" + allow: + # Allow direct and indirect updates for all packages + - dependency-type: "all" + + - package-ecosystem: "composer" #composer + directory: "/" + schedule: + interval: "daily" + allow: + # Allow direct and indirect updates for all packages + - dependency-type: "all" + + - package-ecosystem: "pip" #python + directory: "/" + schedule: + interval: "daily" + allow: + # Allow direct and indirect updates for all packages + - dependency-type: "all" + + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" #github-actions + directory: "/" + schedule: + interval: "daily" + allow: + # Allow direct and indirect updates for all packages + - dependency-type: "all" + + - package-ecosystem: "bundler" + directory: "/" + schedule: + interval: "daily" + allow: + # Allow direct and indirect updates for all packages + - dependency-type: "all" + + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "daily" + allow: + # Allow direct and indirect updates for all packages + - dependency-type: "all" + + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "daily" + allow: + # Allow direct updates for all packages + - dependency-type: "all" + + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "daily" + allow: + # Allow direct and indirect updates for all packages + - dependency-type: "all" + + - package-ecosystem: "gradle" + directory: "/" + schedule: + interval: "daily" + allow: + # Allow direct and indirect updates for all packages + - dependency-type: "all" + + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "daily" + allow: + # Allow direct and indirect updates for all packages + - dependency-type: "all" + + - package-ecosystem: "pub" + directory: "/" + schedule: + interval: "daily" + allow: + # Allow direct and indirect updates for all packages + - dependency-type: "all" + + - package-ecosystem: "terraform" + directory: "/" + schedule: + interval: "daily" + allow: + # Allow direct and indirect updates for all packages + - dependency-type: "all" diff --git a/.github/workflows/chart-release-dispatcher.yaml b/.github/workflows/chart-release-dispatcher.yaml new file mode 100644 index 00000000000..040c5122a77 --- /dev/null +++ b/.github/workflows/chart-release-dispatcher.yaml @@ -0,0 +1,86 @@ +# Name of the Workflow +name: Charts Values Seed Trigger Dispatcher +on: + workflow_run: + workflows: + - "Java CI with Maven" + branches: + - master + - staging + - beta + - mlh41-integration-tests + - mlh41tests + - mlh40java17 + - dq651 + - poctagprophashedrebased + - idonlycanary + - idonlycanarybeta + types: + - completed + +jobs: + charts-release-dispatcher: + name: Dispatch + runs-on: ubuntu-latest + strategy: + matrix: + repo: ['atlanhq/atlan'] + if: ${{ github.event.workflow_run.conclusion == 'success' }} + steps: + # extract branch name + - name: Get branch name + id: extract_branch + run: | + echo "branch=${{ github.event.workflow_run.head_branch }}" >> $GITHUB_OUTPUT + + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + with: + token: ${{ secrets.ORG_PAT_GITHUB }} + ref: ${{ steps.extract_branch.outputs.branch }} + fetch-depth: 0 + + - name: Get SHA of the branch + id: get_sha + run: | + branch_name=${{ steps.extract_branch.outputs.branch }} + sha=$(git rev-parse "refs/heads/$branch_name") + echo "GIT_SHA: $sha" + echo "sha=${sha}" >> $GITHUB_OUTPUT + + - name: Extract Repository Name + id: extract_repo_name + run: | + repo_name=$(basename $GITHUB_REPOSITORY) + echo "repo_name=${repo_name}" >> $GITHUB_OUTPUT + + - name: Get PR url and PR User + id: get_pr_url_user + run: | + head_sha=$(curl -s -H "Authorization: Bearer ${{ secrets.ORG_PAT_GITHUB }}" -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}/jobs" | jq -r '.jobs[0].head_sha') + echo "Head SHA: $head_sha" + pr_url=$(curl -s -H "Authorization: Bearer ${{ secrets.ORG_PAT_GITHUB }}" -H "Accept: application/vnd.github.v3+json" "https://api.github.com/search/issues?q=sha:$head_sha+type:pr" | jq -r '.items[0].html_url') + pr_user=$(curl -s -H "Authorization: Bearer ${{ secrets.ORG_PAT_GITHUB }}" -H "Accept: application/vnd.github.v3+json" "https://api.github.com/search/issues?q=sha:$head_sha+type:pr" | jq -r '.items[0].user.login') + echo "pr_url=$pr_url" >> $GITHUB_OUTPUT + echo "pr_user=$pr_user" >> $GITHUB_OUTPUT + + - name: echo PR_URL and PR_USER + run: | + echo "${{ steps.get_pr_url_user.outputs.pr_url }}" + echo "${{ steps.get_pr_url_user.outputs.pr_user }}" + + - name: Repository Dispatch + uses: peter-evans/repository-dispatch@v2 + with: + token: ${{ secrets.ORG_PAT_GITHUB }} + repository: ${{ matrix.repo }} + event-type: dispatch_chart_release_workflow + client-payload: |- + { + "repo": { + "name": "${{ steps.extract_repo_name.outputs.repo_name }}", + "branch": "${{ steps.extract_branch.outputs.branch }}", + "pr_url": "${{ steps.get_pr_url_user.outputs.pr_url }}", + "pr_user": "${{ steps.get_pr_url_user.outputs.pr_user }}" + } + } diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000000..eb4c08900e9 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,75 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + pull_request: + schedule: + - cron: '0 1 * * *' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: ['java', 'python'] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + - name: Use Java version + uses: actions/setup-java@v3 + with: + distribution: 'adopt' # See 'Supported distributions' for available options + java-version: '8' + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + #- name: Autobuild + # uses: github/codeql-action/autobuild@v2 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + - name: Autobuild + run: | + echo "Run, Build Application using script" + chmod +x ./build.sh && ./build.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 00000000000..6c162f4a4dc --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,13 @@ +name: 'Dependency Review' +on: [pull_request] +permissions: + contents: read +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@v3 + - name: Dependency Review + uses: actions/dependency-review-action@v2 + diff --git a/.github/workflows/github-actions-pr-jira.yaml b/.github/workflows/github-actions-pr-jira.yaml new file mode 100644 index 00000000000..76cd01ab38a --- /dev/null +++ b/.github/workflows/github-actions-pr-jira.yaml @@ -0,0 +1,14 @@ +name: GitHub-Jira Link Action +run-name: ${{ github.actor }} is ensuring Jira ID is present in PR title +on: + pull_request: + types: [opened, edited, synchronize, reopened] + branches: [main, staging, master, beta, develop, prod, development] + +jobs: + Enforce-GitHub-Jira-Link-Action: + runs-on: ubuntu-latest + if: ${{ !contains(fromJson('["main", "staging", "master", "beta", "develop", "prod", "development"]'), github.event.pull_request.head.ref) }} + steps: + - name: Enforce Pull Request Title includes Jira Issue Key + uses: ryanvade/enforce-pr-title-style-action@v2.1.1 \ No newline at end of file diff --git a/.github/workflows/main-ecr.yml b/.github/workflows/main-ecr.yml new file mode 100644 index 00000000000..2a64a38c27a --- /dev/null +++ b/.github/workflows/main-ecr.yml @@ -0,0 +1,199 @@ +name: Build and Push Atlas Metastore docker image to ECR(deprecated as of Jan 11, 2023) + +on: + push: + branches: + - xoxo/deprecating-ecr/xoxo + +permissions: + id-token: write + contents: write + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Get branch name + run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})" + id: get_branch + + - name: Get repository name + run: echo "REPOSITORY_NAME=`echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}' | sed -e "s/:refs//"`" >> $GITHUB_ENV + shell: bash + + - name: Set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + + - name: Cache Maven packages + uses: actions/cache@v2 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/build.sh') }} + restore-keys: ${{ runner.os }}-m2 + + - name: Build with Maven + run: | + branch_name=${{ steps.get_branch.outputs.branch }} + if [[ $branch_name == 'main' || $branch_name == 'master' || $branch_name == 'lineageondemand' ]] + then + echo "build without dashboard" + chmod +x ./build.sh && ./build.sh build_without_dashboard + else + echo "build with dashboard" + chmod +x ./build.sh && ./build.sh + fi + + - name: Get IAM Role and Region to login into ECR + id: get_ecr-details + run: | + branch_name=${{ steps.get_branch.outputs.branch }} + if [[ $branch_name == 'main' || $branch_name == 'staging' || $branch_name == 'master' ]] + then + iamRole=${{ secrets.AWS_PROD_PLATFORM_ECR_ACCESS }} + region='us-east-1' + else + iamRole=${{ secrets.AWS_DEV_PLATFORM_ECR_ACCESS }} + region='ap-south-1' + fi + echo "##[set-output name=iamRole;]$(echo ${iamRole})" + echo "##[set-output name=region;]$(echo ${region})" + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + role-to-assume: ${{ steps.get_ecr-details.outputs.iamRole }} + aws-region: ${{ steps.get_ecr-details.outputs.region }} + + - name: Check and create ECR Repo if it does not exist + uses: nick-fields/retry@v2 + id: check_and_create_repo + with: + timeout_minutes: 10 + max_attempts: 5 + command: | + aws ecr describe-repositories --repository-names atlanhq/${{ github.event.repository.name }} || aws ecr create-repository --repository-name atlanhq/${{ github.event.repository.name }} --image-tag-mutability IMMUTABLE + while ! $(aws ecr get-repository-policy --repository-name atlanhq/${{ github.event.repository.name }}) + do + aws ecr set-repository-policy --repository-name atlanhq/${{ github.event.repository.name }} --policy-text file://ecrorgcrossaccountpolicy.json + registryIdfrompolicy=$(aws ecr get-repository-policy --repository-name atlanhq/${{ github.event.repository.name }} | jq -r '.registryId') + registryIdfromfromecrrepo=$(aws ecr describe-repositories --repository-names atlanhq/${{ github.event.repository.name }} | jq -r '.repositories[0].registryId') + echo "registryIdfrompolicy : $registryIdfrompolicy and registryIdfromfromecrrepo : $registryIdfromfromecrrepo" + if [ $registryIdfrompolicy == $registryIdfromfromecrrepo ] + then + break + fi + done + + - name: Get Semantic Version tag + id: semver_tag + run: | + branch_name=${{ steps.get_branch.outputs.branch }} + tag=$(git tag --sort=v:refname | grep -E "^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)-$branch_name$" | tail -1) + if [[ -z $tag ]] + then + echo "Creating a new tag series" + updated_full_tag="1.0.0-$branch_name" + new_tag=1.0.0 + else + # echo "Current tag is $tag" + patch_version=$(echo $tag | cut -d '.' -f 3 | cut -d '-' -f 1) + minor_version=$(echo $tag | cut -d '.' -f 2) + major_version=$(echo $tag | cut -d '.' -f 1) + if [[ $patch_version == '999' && $minor_version == '999' ]] + then + bump_type='M' + elif [[ $patch_version == '999' && $minor_version != '999' ]] + then + bump_type='m' + else + bump_type='p' + fi + plain_tag_value=$major_version.$minor_version.$patch_version + chmod +x ./sem-ver-bump.sh + new_tag=$(./sem-ver-bump.sh -$bump_type $plain_tag_value) + updated_full_tag=$new_tag-$branch_name + # echo "Last tag is $tag, Bumping up to $updated_full_tag" + fi + + commit_tag=$(git describe --tags --exact-match $GITHUB_SHA 2>/dev/null || echo "no_tag_found") + if [[ $commit_tag == "no_tag_found" ]] + then + echo "No associated tag found, tagging $GITHUB_SHA with $updated_full_tag" + git tag $updated_full_tag $GITHUB_SHA + git push --tags + echo "##[set-output name=build;]$(echo true)" + echo "##[set-output name=new_tag;]$(echo $new_tag)" + echo "Image will be tagged with $new_tag" + else + echo "$GITHUB_SHA is already tagged with $commit_tag" + IMAGE_META=$(aws ecr describe-images --repository-name=atlanhq/${{ github.event.repository.name }} --image-ids=imageTag=$commit_tag 2>/dev/null || echo "no_tag_found") + if [[ $IMAGE_META == "no_tag_found" ]]; then + echo "Image with specified tag does not exist, proceeding to build and push" + existing_tag=$(echo $commit_tag | cut -d '-' -f 1) + echo "##[set-output name=new_tag;]$(echo $existing_tag)" + echo "##[set-output name=build;]$(echo true)" + echo "Image will be tagged with $existing_tag" + else + IMAGE_TAGS="$( echo ${IMAGE_META} | jq '.imageDetails[0].imageTags[0]' -r )" + echo "Image with the specified tag exists, Skipping build" + existing_tag=$(echo $commit_tag | cut -d '-' -f 1) + echo "##[set-output name=new_tag;]$(echo $existing_tag)" + echo "##[set-output name=build;]$(echo false)" + fi + fi + + - name: Keep last 10 tags and delete rest of the old tags + id: cleanup-tags + run: | + branch_name=${{ steps.get_branch.outputs.branch }} + git tag --sort=v:refname | grep -E "^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)-$branch_name" > tagsfile + cat tagsfile + + vars=($(awk -F= '{print $1}' tagsfile)) + + Npars=${#vars[@]} + echo "Npars : $Npars" + numberOfTagsToKeep=10 + if [ $Npars -gt $numberOfTagsToKeep ] + + then + for ((i=0; i<$Npars - $numberOfTagsToKeep; i++)); do + echo "var $i : ${vars[$i]}" + git push --delete origin ${vars[$i]} + done + fi + + - name: Login to Amazon ECR + id: login-ecr + if: steps.semver_tag.outputs.build == 'true' + uses: aws-actions/amazon-ecr-login@v1 + + - name: Set up Buildx + id: buildx + if: steps.semver_tag.outputs.build == 'true' + uses: docker/setup-buildx-action@v2 + with: + driver-opts: image=moby/buildkit:master + + - name: Build and push docker image + id: docker_build + if: steps.semver_tag.outputs.build == 'true' + uses: docker/build-push-action@v3 + with: + context: . + file: ./Dockerfile + push: true + tags: | + ${{ steps.login-ecr.outputs.registry }}/atlanhq/${{ github.event.repository.name }}:${{ steps.semver_tag.outputs.new_tag }}-${{ steps.get_branch.outputs.branch }} + ${{ steps.login-ecr.outputs.registry }}/atlanhq/${{ github.event.repository.name }}:${{ steps.get_branch.outputs.branch }}-${{ steps.semver_tag.outputs.new_tag }} + build-args: | + ACCESS_TOKEN_USR=$GITHUB_ACTOR + ACCESS_TOKEN_PWD=${{ secrets.ORG_PAT_GITHUB }} \ No newline at end of file diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 00000000000..aa5b376ec52 --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,163 @@ + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +name: Java CI with Maven + +on: + push: + branches: + - alpha + - beta + - development + - master + - staging + - tagscanary + - tagscanarymerge + - fixlabels + - interceptapis + - mindbodylineage + - revert-custom-metadata-changes + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v1 + with: + java-version: 17 + + - name: Print JDK version + run: java -version + + - name: Cache Maven packages + uses: actions/cache@v3 + with: + path: ~/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/build.sh') }} + restore-keys: ${{ runner.os }}-m2 + + - name: Get branch name + run: | + echo "BRANCH_NAME=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV + echo BRANCH_NAME=${GITHUB_REF#refs/heads/} + + - name: Create Maven Settings + uses: s4u/maven-settings-action@v2.8.0 + with: + servers: | + [{ + "id": "github", + "username": "atlan-ci", + "password": "${{ secrets.ORG_PAT_GITHUB }}" + }] + + - name: Build with Maven + run: | + echo "build without dashboard" + chmod +x ./build.sh && ./build.sh + + - name: Get Repository Name + run: echo "REPOSITORY_NAME=`echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}' | sed -e "s/:refs//"`" >> $GITHUB_ENV + shell: bash + + - name: Get version tag + # run: echo "##[set-output name=version;]$(echo `git ls-remote https://${{ secrets.ORG_PAT_GITHUB }}@github.com/atlanhq/${REPOSITORY_NAME}.git ${{ env.BRANCH_NAME }} | awk '{ print $1}' | cut -c1-7`)abcd" + run: | + echo "VERSION=$(git ls-remote https://${{ secrets.ORG_PAT_GITHUB }}@github.com/atlanhq/${REPOSITORY_NAME}.git ${{ env.BRANCH_NAME }} | awk '{ print $1}' | cut -c1-7 | head -n 1)abcd" + echo "VERSION=$(git ls-remote https://${{ secrets.ORG_PAT_GITHUB }}@github.com/atlanhq/${REPOSITORY_NAME}.git ${{ env.BRANCH_NAME }} | awk '{ print $1}' | cut -c1-7 | tr -d '[:space:]')abcd" + echo "VERSION=$(git ls-remote https://${{ secrets.ORG_PAT_GITHUB }}@github.com/atlanhq/${REPOSITORY_NAME}.git ${{ env.BRANCH_NAME }} | awk '{ print $1}' | cut -c1-7 | tr -d '[:space:]')abcd" >> $GITHUB_ENV + + - name: Get commit ID + run: echo "COMMIT_ID=$(echo ${GITHUB_SHA} | cut -c1-7)abcd" >> $GITHUB_ENV + + # QEMU is required to build arm from a non-arm build machine + - name: Set up QEMU + id: qemu + uses: docker/setup-qemu-action@v3 + with: + image: tonistiigi/binfmt:qemu-v7.0.0-28 + platforms: arm64 + + - name: Set up Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to GitHub Registry + uses: docker/login-action@v1 + with: + registry: ghcr.io + username: $GITHUB_ACTOR + password: ${{ secrets.ORG_PAT_GITHUB }} + + - name: Build and push with retry + id: docker_build + run: | + # Build and push with retry logic + echo "Building and pushing Docker image with retry mechanism..." + retry_count=0 + max_retries=3 + retry_delay=5 + + while [ $retry_count -lt $max_retries ]; do + echo "Build and push attempt $((retry_count + 1)) of $max_retries" + + if docker buildx build \ + --platform linux/amd64,linux/arm64 \ + --file ./Dockerfile \ + --no-cache \ + --sbom=true \ + --provenance=true \ + --push \ + --tag ghcr.io/atlanhq/${{ github.event.repository.name }}-${{ env.BRANCH_NAME }}:latest \ + --tag ghcr.io/atlanhq/${{ github.event.repository.name }}-${{ env.BRANCH_NAME }}:${{ env.COMMIT_ID }} \ + .; then + echo "Build and push successful!" + break + else + retry_count=$((retry_count + 1)) + if [ $retry_count -lt $max_retries ]; then + echo "Build and push failed. Retrying in $retry_delay seconds..." + sleep $retry_delay + else + echo "Build and push failed after $max_retries attempts. Exiting." + exit 1 + fi + fi + done + + - name: Check Image Manifest + run: docker buildx imagetools inspect --raw ghcr.io/atlanhq/${{ github.event.repository.name }}-${{ env.BRANCH_NAME }}:${{ env.COMMIT_ID }} + + - name: Scan Image + uses: aquasecurity/trivy-action@master + with: + image-ref: 'ubuntu:18.04' + vuln-type: 'os,library' + format: 'sarif' + output: 'trivy-image-results.sarif' + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v2.1.33 + with: + sarif_file: 'trivy-image-results.sarif' \ No newline at end of file diff --git a/.github/workflows/trivy-docker-scan.yml b/.github/workflows/trivy-docker-scan.yml new file mode 100644 index 00000000000..f910348903b --- /dev/null +++ b/.github/workflows/trivy-docker-scan.yml @@ -0,0 +1,38 @@ +name: build +on: + push: + branches: + - alpha + - beta + - development + - master + - lineageondemand + + +jobs: + build: + name: Build + runs-on: ubuntu-20.04 + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Run Trivy vulnerability scanner in IaC mode + uses: aquasecurity/trivy-action@master + with: + scan-type: 'config' + scan-ref: './Dockerfile' + hide-progress: false + template: '@/contrib/gitlab.tpl' + format: 'sarif' + #output: '' + output: 'trivy-results-docker.sarif' + exit-code: '1' + #ignore-unfixed: true + severity: 'CRITICAL,HIGH' + + - name: Upload Trivy Docker Scan Results To GitHub Security tab + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: 'trivy-results-docker.sarif' + diff --git a/.gitignore b/.gitignore index a25f185f9a7..3c8ed375604 100755 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,9 @@ pom.xml.releaseBackup *.iws .idea +# gemini +gemini.md + # Eclipse .cache .classpath @@ -79,3 +82,8 @@ distro/solr/*.tgz # webapp /webapp/overlays/ + +# local models and configurations +/deploy +**.class +*/bin \ No newline at end of file diff --git a/3party-licenses/jnanoid-LICENSE b/3party-licenses/jnanoid-LICENSE new file mode 100644 index 00000000000..a7792c622e3 --- /dev/null +++ b/3party-licenses/jnanoid-LICENSE @@ -0,0 +1,23 @@ +MIT License + +Copyright (c) 2017 The JNanoID Authors +Copyright (c) 2017 Aventrix LLC +Copyright (c) 2017 Andrey Sitnik + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000000..fa7e04ab3ff --- /dev/null +++ b/Dockerfile @@ -0,0 +1,56 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +FROM scratch +FROM ubuntu:22.04 +LABEL maintainer="engineering@atlan.com" +ARG VERSION=3.0.0-SNAPSHOT + +COPY distro/target/apache-atlas-3.0.0-SNAPSHOT-server.tar.gz /apache-atlas-3.0.0-SNAPSHOT-server.tar.gz + +RUN apt-get update \ + && apt-get -y upgrade \ + && apt-get -y install apt-utils \ + && apt-get -y install \ + wget \ + python2 \ + openjdk-17-jdk-headless \ + patch \ + netcat \ + curl \ + && cd / \ + && export MAVEN_OPTS="-Xms2g -Xmx2g" \ + && export JAVA_HOME="/usr/lib/jvm/java-17-openjdk-amd64" \ + && tar -xzvf /apache-atlas-3.0.0-SNAPSHOT-server.tar.gz -C /opt \ + && mv /opt/apache-atlas-${VERSION} /opt/apache-atlas \ + && apt-get clean \ + && rm -rf /apache-atlas-3.0.0-SNAPSHOT-server.tar.gz + +RUN ln -s /usr/bin/python2 /usr/bin/python + +COPY atlas-hub/atlas_start.py.patch atlas-hub/atlas_config.py.patch /opt/apache-atlas/bin/ +COPY atlas-hub/pre-conf/atlas-logback.xml /opt/apache-atlas/conf/ +COPY atlas-hub/pre-conf/atlas-auth/ /opt/apache-atlas/conf/ + +RUN mkdir /opt/apache-atlas/libext +RUN curl https://repo1.maven.org/maven2/org/jolokia/jolokia-jvm/1.6.2/jolokia-jvm-1.6.2-agent.jar -o /opt/apache-atlas/libext/jolokia-jvm-agent.jar + +RUN cd /opt/apache-atlas/bin \ + && ./atlas_start.py -setup || true + +VOLUME ["/opt/apache-atlas/conf", "/opt/apache-atlas/logs"] diff --git a/README.txt b/README.txt index a6062b0d8e8..0c4dad9681b 100755 --- a/README.txt +++ b/README.txt @@ -6,7 +6,7 @@ # "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 +# 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, @@ -35,6 +35,11 @@ Security is both role based (RBAC) and attribute based (ABAC). Build Process ============= +0. Get keycloak dependency + $ mkdir -p ~/.m2/repository/org/keycloak + $ wget https://atlan-public.s3.eu-west-1.amazonaws.com/artifact/keycloak-15.0.2.1.zip + $ unzip -o keycloak-15.0.2.1.zip -d ~/.m2/repository/org + 1. Get Atlas sources to your local directory, for example with following commands $ cd @@ -50,13 +55,11 @@ Build Process $ git checkout tags/ 2. Execute the following commands to build Apache Atlas - $ export MAVEN_OPTS="-Xms2g -Xmx2g" $ mvn clean install $ mvn clean package -Pdist 3. After above build commands successfully complete, you should see the following files - distro/target/apache-atlas--bin.tar.gz distro/target/apache-atlas--hbase-hook.tar.gz distro/target/apache-atlas--hive-hook.tar.gz @@ -68,4 +71,4 @@ Build Process distro/target/apache-atlas--storm-hook.tar.gz distro/target/apache-atlas--falcon-hook.tar.gz -4. For more details on installing and running Apache Atlas, please refer to https://atlas.apache.org/#/Installation +4. For more details on installing and running Apache Atlas, please refer to https://atlas.apache.org/#/Installation. diff --git a/addons/elasticsearch/atlas-auth-es-schema.json b/addons/elasticsearch/atlas-auth-es-schema.json new file mode 100644 index 00000000000..58e7a9c0f64 --- /dev/null +++ b/addons/elasticsearch/atlas-auth-es-schema.json @@ -0,0 +1,128 @@ +{ + "mappings": { + "properties": { + "_expire_at_": { + "type": "date", + "store": true, + "doc_values": true + }, + "_ttl_": { + "type": "text", + "store": true + }, + "_version_": { + "type": "long", + "store": true, + "index": false + }, + "access": { + "type": "keyword" + }, + "action": { + "type": "keyword" + }, + "agent": { + "type": "keyword" + }, + "agentHost": { + "type": "keyword" + }, + "cliIP": { + "type": "keyword" + }, + "cliType": { + "type": "keyword" + }, + "cluster": { + "type": "keyword" + }, + "reqContext": { + "type": "keyword" + }, + "enforcer": { + "type": "keyword" + }, + "event_count": { + "type": "long", + "doc_values": true + }, + "event_dur_ms": { + "type": "long", + "doc_values": true + }, + "evtTime": { + "type": "date", + "doc_values": true + }, + "id": { + "type": "keyword", + "store": true + }, + "logType": { + "type": "keyword" + }, + "policy": { + "type": "keyword" + }, + "proxyUsers": { + "type": "keyword" + }, + "reason": { + "type": "text" + }, + "repo": { + "type": "keyword" + }, + "repoType": { + "type": "integer", + "doc_values": true + }, + "req_caller_id": { + "type": "keyword" + }, + "req_self_id": { + "type": "keyword" + }, + "reqData": { + "type": "text" + }, + "reqUser": { + "type": "keyword" + }, + "reqEntityGuid": { + "type": "keyword" + }, + "resType": { + "type": "keyword" + }, + "resource": { + "type": "keyword" + }, + "result": { + "type": "integer" + }, + "seq_num": { + "type": "long", + "doc_values": true + }, + "sess": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "tags_str": { + "type": "text" + }, + "text": { + "type": "text" + }, + "zoneName": { + "type": "keyword" + }, + "policyVersion": { + "type": "long" + } + } + } +} \ No newline at end of file diff --git a/addons/elasticsearch/es-audit-mappings.json b/addons/elasticsearch/es-audit-mappings.json new file mode 100644 index 00000000000..e514209ae2c --- /dev/null +++ b/addons/elasticsearch/es-audit-mappings.json @@ -0,0 +1,84 @@ +{ + "mappings": { + "properties": { + "entityQualifiedName": { + "type": "keyword" + }, + "entityId": { + "type": "keyword" + }, + "typeName": { + "type": "keyword" + }, + "created": { + "type": "date" + }, + "timestamp": { + "type": "date" + }, + "action": { + "type": "keyword" + }, + "detail": { + "type": "nested" + }, + "user": { + "type": "keyword" + }, + "eventKey": { + "type": "keyword" + } + }, + "dynamic_templates": [ + { + "ignore_random_id_objects": { + "path_match": "detail.attributes.*", + "match_pattern": "regex", + "match": "^[a-zA-Z](?=.*\\\\d)[a-zA-Z0-9]{21}$", + "mapping": { "enabled": false } + } + }, + { + "atlan_headers_as_keyword": { + "path_match": "headers.x-atlan-*", + "mapping": { "type": "keyword" } + } + }, + { + "suppress_attribute_hashes": { + "path_match": "detail.classifications.*", + "match_pattern": "regex", + "match": "^[a-zA-Z](?=.*\\\\d)[a-zA-Z0-9]{21}$", + "mapping": { "enabled": false } + } + }, + { + "bm_ids_in_businessAttributes_lvl1_obj": { + "path_match": "detail.businessAttributes.*", + "match": "^[A-Za-z](?=.*\\d)[A-Za-z0-9]{21}$", + "match_pattern": "regex", + "mapping": { + "enabled": false + } + } + }, + { + "bm_ids_in_businessAttributes_lvl2_obj": { + "path_match": "detail.businessAttributes.*.*", + "match": "^[A-Za-z](?=.*\\d)[A-Za-z0-9]{21}$", + "match_pattern": "regex", + "mapping": { + "enabled": false + } + } + }, + { "allow_strings": { "path_match":"detail.attributes.*", "match_mapping_type":"string", "mapping":{ "type":"keyword", "ignore_above":256 }}}, + { "allow_longs": { "path_match":"detail.attributes.*", "match_mapping_type":"long", "mapping":{ "type":"long" }}}, + { "allow_doubles": { "path_match":"detail.attributes.*", "match_mapping_type":"double", "mapping":{ "type":"double" }}}, + { "allow_booleans": { "path_match":"detail.attributes.*", "match_mapping_type":"boolean", "mapping":{ "type":"boolean" }}}, + { "allow_dates": { "path_match":"detail.attributes.*", "match_mapping_type":"date", "mapping":{ "type":"date", "format":"strict_date_optional_time||epoch_millis" }}} + ], + "date_detection": false, + "numeric_detection": false + } +} diff --git a/addons/elasticsearch/es-mappings.json b/addons/elasticsearch/es-mappings.json new file mode 100644 index 00000000000..56d12b2c0d4 --- /dev/null +++ b/addons/elasticsearch/es-mappings.json @@ -0,0 +1,54 @@ +{ + "properties": { + "relationshipList": { + "type": "nested", + "properties": { + "typeName": { + "type": "keyword" + }, + "guid": { + "type": "keyword" + }, + "provenanceType": { + "type": "integer" + }, + "endName": { + "type": "keyword" + }, + "endGuid": { + "type": "keyword" + }, + "endTypeName": { + "type": "keyword" + }, + "endQualifiedName": { + "type": "keyword" + }, + "label": { + "type": "keyword" + }, + "propagateTags": { + "type": "keyword" + }, + "status": { + "type": "keyword" + }, + "createdBy": { + "type": "keyword" + }, + "updatedBy": { + "type": "keyword" + }, + "createTime": { + "type": "long" + }, + "updateTime": { + "type": "long" + }, + "version": { + "type": "long" + } + } + } + } +} \ No newline at end of file diff --git a/addons/elasticsearch/es-search-logs-mappings.json b/addons/elasticsearch/es-search-logs-mappings.json new file mode 100644 index 00000000000..43b960eb5b0 --- /dev/null +++ b/addons/elasticsearch/es-search-logs-mappings.json @@ -0,0 +1,185 @@ +{ + "mappings": { + "properties": { + "request.attributes": { + "type": "keyword" + }, + "request.relationAttributes": { + "type": "keyword" + }, + "request.dsl": { + "type": "flattened" + }, + "request.dslText": { + "type": "text", + "analyzer": "atlan_json_analyzer" + }, + + + "persona": { + "type": "keyword", + "fields": { + "text": { + "type": "text", + "analyzer": "atlan_text_analyzer" + } + } + }, + "purpose": { + "type": "keyword", + "fields": { + "text": { + "type": "text", + "analyzer": "atlan_text_analyzer" + } + } + }, + + "searchInput": { + "type": "text", + "analyzer": "atlan_text_analyzer", + "fields": { + "keyword": { + "type": "keyword" + }, + "keyword_lowercase": { + "type": "keyword", + "normalizer": "atlan_normalizer" + } + } + }, + + "userAgent": { + "type": "keyword" + }, + "host": { + "type": "keyword" + }, + "ipAddress": { + "type": "keyword" + }, + "userName": { + "type": "keyword" + }, + "entityGuidsAll": { + "type": "keyword" + }, + "entityQFNamesAll": { + "type": "keyword" + }, + "entityGuidsAllowed": { + "type": "keyword" + }, + "entityQFNamesAllowed": { + "type": "keyword" + }, + "entityGuidsDenied": { + "type": "keyword" + }, + "entityQFNamesDenied": { + "type": "keyword" + }, + + "entityTypeNamesAll": { + "type": "keyword" + }, + "entityTypeNamesAllowed": { + "type": "keyword" + }, + "entityTypeNamesDenied": { + "type": "keyword" + }, + + "utmTags": { + "type": "keyword" + }, + "hasResult": { + "type": "boolean" + }, + "isFailed": { + "type": "boolean" + }, + "errorDetails": { + "type": "text" + }, + "errorCode": { + "type": "keyword" + }, + "resultsCount": { + "type": "long" + }, + "timestamp": { + "type": "long" + }, + "createdAt": { + "type": "long" + }, + "responseTime": { + "type": "long" + } + } + }, + "settings": { + "analysis": { + "analyzer": { + "atlan_text_analyzer": { + "type": "custom", + "tokenizer": "atlan_tokenizer", + "filter": [ + "apostrophe", + "lowercase" + ], + "char_filter": [ + "number_filter" + ] + }, + "atlan_json_analyzer": { + "type": "custom", + "tokenizer": "atlan_json_tokenizer" + }, + "atlan_text_stemmer": { + "type": "custom", + "tokenizer": "atlan_tokenizer", + "filter": [ + "snowball_english", + "lowercase" + ], + "char_filter": [ + "number_filter" + ] + } + }, + "normalizer": { + "atlan_normalizer": { + "type": "custom", + "filter": [ + "lowercase" + ] + } + }, + "filter": { + "snowball_english": { + "type": "snowball", + "language": "English" + } + }, + "tokenizer": { + "atlan_tokenizer": { + "type": "pattern", + "pattern": "( |_|-|'|/|@)" + }, + "atlan_json_tokenizer": { + "type": "pattern", + "pattern": "(\"|\\{|\\}|:|\\[|\\]|\\,)" + } + }, + "char_filter": { + "number_filter": { + "type": "pattern_replace", + "pattern": "\\d+", + "replacement": " $0" + } + } + } + } +} \ No newline at end of file diff --git a/addons/elasticsearch/es-settings.json b/addons/elasticsearch/es-settings.json new file mode 100644 index 00000000000..e67d2db8d9c --- /dev/null +++ b/addons/elasticsearch/es-settings.json @@ -0,0 +1,121 @@ +{ + "mapping" : { + "total_fields" : { + "limit" : "5000" + }, + "nested_objects" : { + "limit" : "100000" + } + }, + "similarity": { + "default": { + "type": "boolean" + } + }, + "analysis": { + "analyzer": { + "atlan_glossary_analyzer": { + "type": "custom", + "tokenizer": "atlan_glossary_tokenizer", + "filter": [ + "lowercase" + ], + "char_filter": [ + "letter_number_filter" + ] + }, + "atlan_text_analyzer": { + "type": "custom", + "tokenizer": "atlan_tokenizer", + "filter": [ + "apostrophe", "lowercase" + ], + "char_filter":[ + "number_filter" + ] + }, + "atlan_text_comma_analyzer": { + "type": "custom", + "tokenizer": "atlan_comma_tokenizer", + "filter": [ + "lowercase" + ] + }, + "atlan_text_stemmer": { + "type": "custom", + "tokenizer": "atlan_tokenizer", + "filter": [ + "snowball_english", "lowercase" + ], + "char_filter":[ + "number_filter" + ] + }, + "search_synonyms": { + "type": "custom", + "filter": [ + "graph_synonyms", "lowercase" + ], + "tokenizer": "atlan_tokenizer" + }, + "truncate_analyzer": { + "char_filter": [ + "truncate_filter" + ], + "tokenizer": "standard" + } + }, + "normalizer": { + "atlan_normalizer": { + "type": "custom", + "filter": ["lowercase"] + } + }, + "filter": { + "graph_synonyms": { + "type": "synonym_graph", + "synonyms_path": "synonym.txt" + }, + "snowball_english": { + "type": "snowball", + "language": "English" + } + }, + "tokenizer": { + "atlan_glossary_tokenizer": { + "type": "char_group", + "tokenize_on_chars": [ + "whitespace", + "punctuation", + "symbol" + ] + }, + "atlan_tokenizer": { + "type": "pattern", + "pattern": "( |_|-|'|/|@)" + }, + "atlan_comma_tokenizer": { + "type": "pattern", + "pattern": "," + } + }, + "char_filter":{ + "letter_number_filter": { + "type": "pattern_replace", + "pattern": "\\d+", + "replacement": " $0 " + }, + "number_filter":{ + "type":"pattern_replace", + "pattern":"\\d+", + "replacement":" $0" + }, + "truncate_filter": { + "pattern": "(.{0,100000}).*", + "type": "pattern_replace", + "replacement": "$1", + "flags": "DOTALL" + } + } + } +} diff --git a/addons/falcon-bridge-shim/pom.xml b/addons/falcon-bridge-shim/pom.xml deleted file mode 100755 index c554e890a71..00000000000 --- a/addons/falcon-bridge-shim/pom.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - falcon-bridge-shim - Apache Atlas Falcon Bridge Shim Module - Apache Atlas Falcon Bridge Shim - jar - - - - - org.apache.atlas - atlas-plugin-classloader - - - - org.apache.falcon - falcon-common - ${falcon.version} - provided - - - org.apache.spark - * - - - javax.servlet - servlet-api - - - org.mortbay.jetty - servlet-api - - - org.springframework - spring-beans - - - org.springframework - spring-jms - - - org.springframework - spring-tx - - - org.springframework - spring-context - - - - - diff --git a/addons/falcon-bridge-shim/src/main/java/org/apache/atlas/falcon/service/AtlasService.java b/addons/falcon-bridge-shim/src/main/java/org/apache/atlas/falcon/service/AtlasService.java deleted file mode 100755 index 2b756de0e29..00000000000 --- a/addons/falcon-bridge-shim/src/main/java/org/apache/atlas/falcon/service/AtlasService.java +++ /dev/null @@ -1,222 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.falcon.service; - - -import org.apache.atlas.plugin.classloader.AtlasPluginClassLoader; -import org.apache.falcon.FalconException; -import org.apache.falcon.entity.store.ConfigurationStore; -import org.apache.falcon.entity.v0.Entity; -import org.apache.falcon.service.ConfigurationChangeListener; -import org.apache.falcon.service.FalconService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Falcon hook used for atlas entity registration. - */ -public class AtlasService implements FalconService, ConfigurationChangeListener { - private static final Logger LOG = LoggerFactory.getLogger(AtlasService.class); - - private static final String ATLAS_PLUGIN_TYPE = "falcon"; - private static final String ATLAS_FALCON_HOOK_IMPL_CLASSNAME = "org.apache.atlas.falcon.service.AtlasService"; - - private AtlasPluginClassLoader atlasPluginClassLoader = null; - private FalconService falconServiceImpl = null; - private ConfigurationChangeListener configChangeListenerImpl = null; - - public AtlasService() { - this.initialize(); - } - - @Override - public String getName() { - if (LOG.isDebugEnabled()) { - LOG.debug("==> AtlasService.getName()"); - } - - String ret = null; - - try { - activatePluginClassLoader(); - ret = falconServiceImpl.getName(); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== AtlasService.getName()"); - } - - return ret; - } - - @Override - public void init() throws FalconException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> AtlasService.init()"); - } - - try { - activatePluginClassLoader(); - - ConfigurationStore.get().registerListener(this); - - falconServiceImpl.init(); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== AtlasService.init()"); - } - } - - @Override - public void destroy() throws FalconException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> AtlasService.destroy()"); - } - - try { - activatePluginClassLoader(); - - ConfigurationStore.get().unregisterListener(this); - - falconServiceImpl.destroy(); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== AtlasService.destroy()"); - } - } - - @Override - public void onAdd(Entity entity) throws FalconException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> AtlasService.onAdd({})", entity); - } - - try { - activatePluginClassLoader(); - configChangeListenerImpl.onAdd(entity); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== AtlasService.onAdd({})", entity); - } - } - - @Override - public void onRemove(Entity entity) throws FalconException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> AtlasService.onRemove({})", entity); - } - - try { - activatePluginClassLoader(); - configChangeListenerImpl.onRemove(entity); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== AtlasService.onRemove({})", entity); - } - } - - @Override - public void onChange(Entity entity, Entity entity1) throws FalconException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> AtlasService.onChange({}, {})", entity, entity1); - } - - try { - activatePluginClassLoader(); - configChangeListenerImpl.onChange(entity, entity1); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== AtlasService.onChange({}, {})", entity, entity1); - } - } - - @Override - public void onReload(Entity entity) throws FalconException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> AtlasService.onReload({})", entity); - } - - try { - activatePluginClassLoader(); - configChangeListenerImpl.onReload(entity); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== AtlasService.onReload({})", entity); - } - } - - private void initialize() { - if (LOG.isDebugEnabled()) { - LOG.debug("==> AtlasService.initialize()"); - } - - try { - atlasPluginClassLoader = AtlasPluginClassLoader.getInstance(ATLAS_PLUGIN_TYPE, this.getClass()); - - Class cls = Class.forName(ATLAS_FALCON_HOOK_IMPL_CLASSNAME, true, atlasPluginClassLoader); - - activatePluginClassLoader(); - - Object atlasService = cls.newInstance(); - - falconServiceImpl = (FalconService) atlasService; - configChangeListenerImpl = (ConfigurationChangeListener) atlasService; - } catch (Exception excp) { - LOG.error("Error instantiating Atlas hook implementation", excp); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== AtlasService.initialize()"); - } - } - - private void activatePluginClassLoader() { - if (atlasPluginClassLoader != null) { - atlasPluginClassLoader.activate(); - } - } - - private void deactivatePluginClassLoader() { - if (atlasPluginClassLoader != null) { - atlasPluginClassLoader.deactivate(); - } - } -} diff --git a/addons/falcon-bridge/pom.xml b/addons/falcon-bridge/pom.xml deleted file mode 100644 index 1e2ce7c81b4..00000000000 --- a/addons/falcon-bridge/pom.xml +++ /dev/null @@ -1,431 +0,0 @@ - - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - falcon-bridge - Apache Atlas Falcon Bridge Module - Apache Atlas Falcon Bridge - jar - - - - - org.slf4j - slf4j-api - - - - org.slf4j - slf4j-log4j12 - - - - org.apache.atlas - atlas-client-v1 - - - - org.apache.atlas - atlas-notification - - - - org.apache.falcon - falcon-common - ${falcon.version} - provided - - - org.apache.spark - * - - - javax.servlet - servlet-api - - - org.mortbay.jetty - servlet-api - - - org.springframework - spring-beans - - - org.springframework - spring-jms - - - org.springframework - spring-tx - - - - - - org.apache.atlas - hive-bridge - - - - org.testng - testng - - - - org.eclipse.jetty - jetty-server - test - - - - org.apache.atlas - atlas-graphdb-impls - pom - test - - - - - - dist - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-hook - package - - copy - - - ${project.build.directory}/dependency/hook/falcon/atlas-falcon-plugin-impl - false - false - true - - - ${project.groupId} - ${project.artifactId} - ${project.version} - - - ${project.groupId} - hive-bridge - ${project.version} - - - ${project.groupId} - atlas-client-common - ${project.version} - - - ${project.groupId} - atlas-client-v1 - ${project.version} - - - ${project.groupId} - atlas-client-v2 - ${project.version} - - - ${project.groupId} - atlas-intg - ${project.version} - - - ${project.groupId} - atlas-notification - ${project.version} - - - ${project.groupId} - atlas-common - ${project.version} - - - org.apache.kafka - kafka_${kafka.scala.binary.version} - ${kafka.version} - - - org.apache.kafka - kafka-clients - ${kafka.version} - - - com.sun.jersey - jersey-json - ${jersey.version} - - - javax.ws.rs - jsr311-api - ${jsr.version} - - - - - - copy-hook-shim - package - - copy - - - ${project.build.directory}/dependency/hook/falcon - false - false - true - - - ${project.groupId} - falcon-bridge-shim - ${project.version} - - - ${project.groupId} - atlas-plugin-classloader - ${project.version} - - - - - - - - - - - - - - org.eclipse.jetty - jetty-maven-plugin - ${jetty.version} - - ${skipTests} - - 31000 - 60000 - - ../../webapp/target/atlas-webapp-${project.version}.war - true - ../../webapp/src/main/webapp - - / - ${project.basedir}/../../webapp/src/main/webapp/WEB-INF/web.xml - - true - - true - - atlas.home - ${project.build.directory} - - - atlas.conf - ${project.build.directory}/test-classes - - - atlas.data - ${project.build.directory}/data - - - atlas.log.dir - ${project.build.directory}/logs - - - atlas.log.file - application.log - - - log4j.configuration - file:///${project.build.directory}/test-classes/atlas-log4j.xml - - - atlas.graphdb.backend - ${graphdb.backend.impl} - - - embedded.solr.directory - ${project.build.directory} - - - solr.log.dir - ${project.build.directory}/logs - - - org.eclipse.jetty.annotations.maxWait - 5000 - - - atlas-stop - 31001 - ${jetty-maven-plugin.stopWait} - jar - - - - org.apache.curator - curator-client - ${curator.version} - - - - org.apache.zookeeper - zookeeper - ${zookeeper.version} - - - - - start-jetty - pre-integration-test - - - stop - deploy-war - - - true - - - - stop-jetty - post-integration-test - - stop - - - - - - - org.apache.maven.plugins - maven-site-plugin - - - org.apache.maven.doxia - doxia-module-twiki - ${doxia.version} - - - org.apache.maven.doxia - doxia-core - ${doxia.version} - - - - - - site - - prepare-package - - - - false - false - - - - - org.codehaus.mojo - exec-maven-plugin - 1.2.1 - false - - - - - - org.apache.maven.plugins - maven-resources-plugin - - - copy-resources - validate - - copy-resources - - - ${basedir}/target/models - - - ${basedir}/../models - - 0000-Area0/0010-base_model.json - 1000-Hadoop/** - - - - - - - copy-solr-resources - validate - - copy-resources - - - ${project.build.directory}/solr - - - ${basedir}/../../test-tools/src/main/resources/solr - - - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - - - post-integration-test - - run - - - - - - - - - - - - - - diff --git a/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/Util/EventUtil.java b/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/Util/EventUtil.java deleted file mode 100644 index ef5634009d1..00000000000 --- a/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/Util/EventUtil.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.falcon.Util; - -import org.apache.commons.lang3.StringUtils; -import org.apache.falcon.FalconException; -import org.apache.falcon.security.CurrentUser; - -import java.util.HashMap; -import java.util.Map; - -/** - * Falcon event util - */ -public final class EventUtil { - - private EventUtil() {} - - - public static Map convertKeyValueStringToMap(final String keyValueString) { - if (StringUtils.isBlank(keyValueString)) { - return null; - } - - Map keyValueMap = new HashMap<>(); - - String[] tags = keyValueString.split(","); - for (String tag : tags) { - int index = tag.indexOf("="); - String tagKey = tag.substring(0, index).trim(); - String tagValue = tag.substring(index + 1, tag.length()).trim(); - keyValueMap.put(tagKey, tagValue); - } - return keyValueMap; - } - - public static String getUser() throws FalconException { - try { - return CurrentUser.getAuthenticatedUGI().getShortUserName(); - } catch (Exception ioe) { - //Ignore is failed to get user, uses login user - } - return null; - } -} diff --git a/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/bridge/FalconBridge.java b/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/bridge/FalconBridge.java deleted file mode 100644 index cbf002f4fa7..00000000000 --- a/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/bridge/FalconBridge.java +++ /dev/null @@ -1,416 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.falcon.bridge; - -import org.apache.atlas.AtlasClient; -import org.apache.atlas.AtlasConstants; -import org.apache.atlas.falcon.Util.EventUtil; -import org.apache.atlas.falcon.model.FalconDataTypes; -import org.apache.atlas.hive.bridge.HiveMetaStoreBridge; -import org.apache.atlas.hive.model.HiveDataTypes; -import org.apache.atlas.v1.model.instance.Referenceable; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.falcon.FalconException; -import org.apache.falcon.entity.CatalogStorage; -import org.apache.falcon.entity.FeedHelper; -import org.apache.falcon.entity.FileSystemStorage; -import org.apache.falcon.entity.ProcessHelper; -import org.apache.falcon.entity.store.ConfigurationStore; -import org.apache.falcon.entity.v0.EntityType; -import org.apache.falcon.entity.v0.feed.CatalogTable; -import org.apache.falcon.entity.v0.feed.ClusterType; -import org.apache.falcon.entity.v0.feed.Feed; -import org.apache.falcon.entity.v0.feed.Location; -import org.apache.falcon.entity.v0.feed.LocationType; -import org.apache.falcon.entity.v0.process.Cluster; -import org.apache.falcon.entity.v0.process.Input; -import org.apache.falcon.entity.v0.process.Output; -import org.apache.falcon.entity.v0.process.Workflow; -import org.apache.falcon.workflow.WorkflowExecutionArgs; -import org.apache.hadoop.fs.Path; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * A Bridge Utility to register Falcon entities metadata to Atlas. - */ -public class FalconBridge { - private static final Logger LOG = LoggerFactory.getLogger(FalconBridge.class); - - public static final String COLO = "colo"; - public static final String TAGS = "tags"; - public static final String GROUPS = "groups"; - public static final String PIPELINES = "pipelines"; - public static final String WFPROPERTIES = "workflow-properties"; - public static final String RUNSON = "runs-on"; - public static final String STOREDIN = "stored-in"; - public static final String FREQUENCY = "frequency"; - public static final String ATTRIBUTE_DB = "db"; - - /** - * Creates cluster entity - * - * @param cluster ClusterEntity - * @return cluster instance reference - */ - public static Referenceable createClusterEntity(final org.apache.falcon.entity.v0.cluster.Cluster cluster) { - LOG.info("Creating cluster Entity : {}", cluster.getName()); - - Referenceable clusterRef = new Referenceable(FalconDataTypes.FALCON_CLUSTER.getName()); - - clusterRef.set(AtlasClient.NAME, cluster.getName()); - clusterRef.set(AtlasClient.DESCRIPTION, cluster.getDescription()); - clusterRef.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, cluster.getName()); - - clusterRef.set(FalconBridge.COLO, cluster.getColo()); - - if (cluster.getACL() != null) { - clusterRef.set(AtlasClient.OWNER, cluster.getACL().getGroup()); - } - - if (StringUtils.isNotEmpty(cluster.getTags())) { - clusterRef.set(FalconBridge.TAGS, - EventUtil.convertKeyValueStringToMap(cluster.getTags())); - } - - return clusterRef; - } - - private static Referenceable createFeedEntity(Feed feed, Referenceable clusterReferenceable) { - LOG.info("Creating feed dataset: {}", feed.getName()); - - Referenceable feedEntity = new Referenceable(FalconDataTypes.FALCON_FEED.getName()); - feedEntity.set(AtlasClient.NAME, feed.getName()); - feedEntity.set(AtlasClient.DESCRIPTION, feed.getDescription()); - String feedQualifiedName = - getFeedQualifiedName(feed.getName(), (String) clusterReferenceable.get(AtlasClient.NAME)); - feedEntity.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, feedQualifiedName); - feedEntity.set(FalconBridge.FREQUENCY, feed.getFrequency().toString()); - feedEntity.set(FalconBridge.STOREDIN, clusterReferenceable); - if (feed.getACL() != null) { - feedEntity.set(AtlasClient.OWNER, feed.getACL().getOwner()); - } - - if (StringUtils.isNotEmpty(feed.getTags())) { - feedEntity.set(FalconBridge.TAGS, - EventUtil.convertKeyValueStringToMap(feed.getTags())); - } - - if (feed.getGroups() != null) { - feedEntity.set(FalconBridge.GROUPS, feed.getGroups()); - } - - return feedEntity; - } - - public static List createFeedCreationEntity(Feed feed, ConfigurationStore falconStore) throws FalconException, URISyntaxException { - LOG.info("Creating feed : {}", feed.getName()); - - List entities = new ArrayList<>(); - - if (feed.getClusters() != null) { - List replicationInputs = new ArrayList<>(); - List replicationOutputs = new ArrayList<>(); - - for (org.apache.falcon.entity.v0.feed.Cluster feedCluster : feed.getClusters().getClusters()) { - org.apache.falcon.entity.v0.cluster.Cluster cluster = falconStore.get(EntityType.CLUSTER, - feedCluster.getName()); - - // set cluster - Referenceable clusterReferenceable = getClusterEntityReference(cluster.getName(), cluster.getColo()); - entities.add(clusterReferenceable); - - // input as hive_table or hdfs_path, output as falcon_feed dataset - List inputs = new ArrayList<>(); - List inputReferenceables = getInputEntities(cluster, feed); - if (inputReferenceables != null) { - entities.addAll(inputReferenceables); - inputs.add(inputReferenceables.get(inputReferenceables.size() - 1)); - } - - List outputs = new ArrayList<>(); - Referenceable feedEntity = createFeedEntity(feed, clusterReferenceable); - if (feedEntity != null) { - entities.add(feedEntity); - outputs.add(feedEntity); - } - - if (!inputs.isEmpty() || !outputs.isEmpty()) { - Referenceable feedCreateEntity = new Referenceable(FalconDataTypes.FALCON_FEED_CREATION.getName()); - String feedQualifiedName = getFeedQualifiedName(feed.getName(), cluster.getName()); - - feedCreateEntity.set(AtlasClient.NAME, feed.getName()); - feedCreateEntity.set(AtlasClient.DESCRIPTION, "Feed creation - " + feed.getName()); - feedCreateEntity.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, feedQualifiedName); - - if (!inputs.isEmpty()) { - feedCreateEntity.set(AtlasClient.PROCESS_ATTRIBUTE_INPUTS, inputs); - } - if (!outputs.isEmpty()) { - feedCreateEntity.set(AtlasClient.PROCESS_ATTRIBUTE_OUTPUTS, outputs); - } - - feedCreateEntity.set(FalconBridge.STOREDIN, clusterReferenceable); - entities.add(feedCreateEntity); - } - - if (ClusterType.SOURCE == feedCluster.getType()) { - replicationInputs.add(feedEntity); - } else if (ClusterType.TARGET == feedCluster.getType()) { - replicationOutputs.add(feedEntity); - } - } - - if (!replicationInputs.isEmpty() && !replicationInputs.isEmpty()) { - Referenceable feedReplicationEntity = new Referenceable(FalconDataTypes - .FALCON_FEED_REPLICATION.getName()); - - feedReplicationEntity.set(AtlasClient.NAME, feed.getName()); - feedReplicationEntity.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, feed.getName()); - - feedReplicationEntity.set(AtlasClient.PROCESS_ATTRIBUTE_INPUTS, replicationInputs); - feedReplicationEntity.set(AtlasClient.PROCESS_ATTRIBUTE_OUTPUTS, replicationOutputs); - entities.add(feedReplicationEntity); - } - - } - return entities; - } - - /** - * Creates process entity - * - * @param process process entity - * @param falconStore config store - * @return process instance reference - * - * @throws FalconException if retrieving from the configuration store fail - */ - public static List createProcessEntity(org.apache.falcon.entity.v0.process.Process process, - ConfigurationStore falconStore) throws FalconException { - LOG.info("Creating process Entity : {}", process.getName()); - - // The requirement is for each cluster, create a process entity with name - // clustername.processname - List entities = new ArrayList<>(); - - if (process.getClusters() != null) { - - for (Cluster processCluster : process.getClusters().getClusters()) { - org.apache.falcon.entity.v0.cluster.Cluster cluster = - falconStore.get(EntityType.CLUSTER, processCluster.getName()); - Referenceable clusterReferenceable = getClusterEntityReference(cluster.getName(), cluster.getColo()); - entities.add(clusterReferenceable); - - List inputs = new ArrayList<>(); - if (process.getInputs() != null) { - for (Input input : process.getInputs().getInputs()) { - Feed feed = falconStore.get(EntityType.FEED, input.getFeed()); - Referenceable inputReferenceable = getFeedDataSetReference(feed, clusterReferenceable); - entities.add(inputReferenceable); - inputs.add(inputReferenceable); - } - } - - List outputs = new ArrayList<>(); - if (process.getOutputs() != null) { - for (Output output : process.getOutputs().getOutputs()) { - Feed feed = falconStore.get(EntityType.FEED, output.getFeed()); - Referenceable outputReferenceable = getFeedDataSetReference(feed, clusterReferenceable); - entities.add(outputReferenceable); - outputs.add(outputReferenceable); - } - } - - if (!inputs.isEmpty() || !outputs.isEmpty()) { - - Referenceable processEntity = new Referenceable(FalconDataTypes.FALCON_PROCESS.getName()); - processEntity.set(AtlasClient.NAME, process.getName()); - processEntity.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - getProcessQualifiedName(process.getName(), cluster.getName())); - processEntity.set(FalconBridge.FREQUENCY, process.getFrequency().toString()); - - if (!inputs.isEmpty()) { - processEntity.set(AtlasClient.PROCESS_ATTRIBUTE_INPUTS, inputs); - } - if (!outputs.isEmpty()) { - processEntity.set(AtlasClient.PROCESS_ATTRIBUTE_OUTPUTS, outputs); - } - - // set cluster - processEntity.set(FalconBridge.RUNSON, clusterReferenceable); - - // Set user - if (process.getACL() != null) { - processEntity.set(AtlasClient.OWNER, process.getACL().getOwner()); - } - - if (StringUtils.isNotEmpty(process.getTags())) { - processEntity.set(FalconBridge.TAGS, - EventUtil.convertKeyValueStringToMap(process.getTags())); - } - - if (process.getPipelines() != null) { - processEntity.set(FalconBridge.PIPELINES, process.getPipelines()); - } - - processEntity.set(FalconBridge.WFPROPERTIES, - getProcessEntityWFProperties(process.getWorkflow(), - process.getName())); - - entities.add(processEntity); - } - - } - } - return entities; - } - - private static List getInputEntities(org.apache.falcon.entity.v0.cluster.Cluster cluster, - Feed feed) throws URISyntaxException { - org.apache.falcon.entity.v0.feed.Cluster feedCluster = FeedHelper.getCluster(feed, cluster.getName()); - - if(feedCluster != null) { - final CatalogTable table = getTable(feedCluster, feed); - if (table != null) { - CatalogStorage storage = new CatalogStorage(cluster, table); - return createHiveTableInstance(cluster.getName(), storage.getDatabase().toLowerCase(), - storage.getTable().toLowerCase()); - } else { - List locations = FeedHelper.getLocations(feedCluster, feed); - if (CollectionUtils.isNotEmpty(locations)) { - Location dataLocation = FileSystemStorage.getLocation(locations, LocationType.DATA); - if (dataLocation != null) { - final String pathUri = normalize(dataLocation.getPath()); - LOG.info("Registering DFS Path {} ", pathUri); - return fillHDFSDataSet(pathUri, cluster.getName()); - } - } - } - } - - return null; - } - - private static CatalogTable getTable(org.apache.falcon.entity.v0.feed.Cluster cluster, Feed feed) { - // check if table is overridden in cluster - if (cluster.getTable() != null) { - return cluster.getTable(); - } - - return feed.getTable(); - } - - private static List fillHDFSDataSet(final String pathUri, final String clusterName) { - List entities = new ArrayList<>(); - Referenceable ref = new Referenceable(HiveMetaStoreBridge.HDFS_PATH); - ref.set("path", pathUri); - // Path path = new Path(pathUri); - // ref.set("name", path.getName()); - //TODO - Fix after ATLAS-542 to shorter Name - Path path = new Path(pathUri); - ref.set(AtlasClient.NAME, Path.getPathWithoutSchemeAndAuthority(path).toString().toLowerCase()); - ref.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, pathUri); - ref.set(AtlasConstants.CLUSTER_NAME_ATTRIBUTE, clusterName); - entities.add(ref); - return entities; - } - - private static Referenceable createHiveDatabaseInstance(String clusterName, String dbName) { - Referenceable dbRef = new Referenceable(HiveDataTypes.HIVE_DB.getName()); - dbRef.set(AtlasConstants.CLUSTER_NAME_ATTRIBUTE, clusterName); - dbRef.set(AtlasClient.NAME, dbName); - dbRef.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - HiveMetaStoreBridge.getDBQualifiedName(clusterName, dbName)); - return dbRef; - } - - private static List createHiveTableInstance(String clusterName, String dbName, - String tableName) { - List entities = new ArrayList<>(); - Referenceable dbRef = createHiveDatabaseInstance(clusterName, dbName); - entities.add(dbRef); - - Referenceable tableRef = new Referenceable(HiveDataTypes.HIVE_TABLE.getName()); - tableRef.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - HiveMetaStoreBridge.getTableQualifiedName(clusterName, dbName, tableName)); - tableRef.set(AtlasClient.NAME, tableName.toLowerCase()); - tableRef.set(ATTRIBUTE_DB, dbRef); - entities.add(tableRef); - - return entities; - } - - private static Referenceable getClusterEntityReference(final String clusterName, - final String colo) { - LOG.info("Getting reference for entity {}", clusterName); - Referenceable clusterRef = new Referenceable(FalconDataTypes.FALCON_CLUSTER.getName()); - clusterRef.set(AtlasClient.NAME, String.format("%s", clusterName)); - clusterRef.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, clusterName); - clusterRef.set(FalconBridge.COLO, colo); - return clusterRef; - } - - - private static Referenceable getFeedDataSetReference(Feed feed, Referenceable clusterReference) { - LOG.info("Getting reference for entity {}", feed.getName()); - Referenceable feedDatasetRef = new Referenceable(FalconDataTypes.FALCON_FEED.getName()); - feedDatasetRef.set(AtlasClient.NAME, feed.getName()); - feedDatasetRef.set(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, getFeedQualifiedName(feed.getName(), - (String) clusterReference.get(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME))); - feedDatasetRef.set(FalconBridge.STOREDIN, clusterReference); - feedDatasetRef.set(FalconBridge.FREQUENCY, feed.getFrequency()); - return feedDatasetRef; - } - - private static Map getProcessEntityWFProperties(final Workflow workflow, - final String processName) { - Map wfProperties = new HashMap<>(); - wfProperties.put(WorkflowExecutionArgs.USER_WORKFLOW_NAME.getName(), - ProcessHelper.getProcessWorkflowName(workflow.getName(), processName)); - wfProperties.put(WorkflowExecutionArgs.USER_WORKFLOW_VERSION.getName(), - workflow.getVersion()); - wfProperties.put(WorkflowExecutionArgs.USER_WORKFLOW_ENGINE.getName(), - workflow.getEngine().value()); - - return wfProperties; - } - - public static String getFeedQualifiedName(final String feedName, final String clusterName) { - return String.format("%s@%s", feedName, clusterName); - } - - public static String getProcessQualifiedName(final String processName, final String clusterName) { - return String.format("%s@%s", processName, clusterName); - } - - public static String normalize(final String str) { - if (StringUtils.isBlank(str)) { - return null; - } - return str.toLowerCase().trim(); - } -} diff --git a/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/event/FalconEvent.java b/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/event/FalconEvent.java deleted file mode 100644 index 51db894ab6f..00000000000 --- a/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/event/FalconEvent.java +++ /dev/null @@ -1,57 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.falcon.event; - -import org.apache.falcon.entity.v0.Entity; - -/** - * Falcon event to interface with Atlas Service. - */ -public class FalconEvent { - protected String user; - protected OPERATION operation; - protected Entity entity; - - public FalconEvent(String doAsUser, OPERATION falconOperation, Entity entity) { - this.user = doAsUser; - this.operation = falconOperation; - this.entity = entity; - } - - public enum OPERATION { - ADD_CLUSTER, - UPDATE_CLUSTER, - ADD_FEED, - UPDATE_FEED, - ADD_PROCESS, - UPDATE_PROCESS, - } - - public String getUser() { - return user; - } - - public OPERATION getOperation() { - return operation; - } - - public Entity getEntity() { - return entity; - } -} diff --git a/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/hook/FalconHook.java b/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/hook/FalconHook.java deleted file mode 100644 index b8a73cbe63e..00000000000 --- a/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/hook/FalconHook.java +++ /dev/null @@ -1,138 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.falcon.hook; - -import org.apache.atlas.falcon.bridge.FalconBridge; -import org.apache.atlas.falcon.event.FalconEvent; -import org.apache.atlas.falcon.publisher.FalconEventPublisher; -import org.apache.atlas.hook.AtlasHook; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.v1.model.instance.Referenceable; -import org.apache.atlas.v1.model.notification.HookNotificationV1.EntityCreateRequest; -import org.apache.falcon.FalconException; -import org.apache.falcon.entity.store.ConfigurationStore; -import org.apache.falcon.entity.v0.feed.Feed; -import org.apache.falcon.entity.v0.process.Process; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.List; -import static org.apache.atlas.repository.Constants.FALCON_SOURCE; - -/** - * Falcon hook sends lineage information to the Atlas Service. - */ -public class FalconHook extends AtlasHook implements FalconEventPublisher { - private static final Logger LOG = LoggerFactory.getLogger(FalconHook.class); - - private static ConfigurationStore STORE; - - @Override - public String getMessageSource() { - return FALCON_SOURCE; - } - - private enum Operation { - ADD, - UPDATE - } - - static { - try { - STORE = ConfigurationStore.get(); - } catch (Exception e) { - LOG.error("Caught exception initializing the falcon hook.", e); - } - - LOG.info("Created Atlas Hook for Falcon"); - } - - @Override - public void publish(final Data data) { - final FalconEvent event = data.getEvent(); - try { - fireAndForget(event); - } catch (Throwable t) { - LOG.warn("Error in processing data {}", data, t); - } - } - - private void fireAndForget(FalconEvent event) throws FalconException, URISyntaxException { - LOG.info("Entered Atlas hook for Falcon hook operation {}", event.getOperation()); - List messages = new ArrayList<>(); - - Operation op = getOperation(event.getOperation()); - String user = getUser(event.getUser()); - LOG.info("fireAndForget user:{}", user); - switch (op) { - case ADD: - messages.add(new EntityCreateRequest(user, createEntities(event, user))); - break; - - } - notifyEntities(messages, null); - } - - private List createEntities(FalconEvent event, String user) throws FalconException, URISyntaxException { - List entities = new ArrayList<>(); - - switch (event.getOperation()) { - case ADD_CLUSTER: - entities.add(FalconBridge - .createClusterEntity((org.apache.falcon.entity.v0.cluster.Cluster) event.getEntity())); - break; - - case ADD_PROCESS: - entities.addAll(FalconBridge.createProcessEntity((Process) event.getEntity(), STORE)); - break; - - case ADD_FEED: - entities.addAll(FalconBridge.createFeedCreationEntity((Feed) event.getEntity(), STORE)); - break; - - case UPDATE_CLUSTER: - case UPDATE_FEED: - case UPDATE_PROCESS: - default: - LOG.info("Falcon operation {} is not valid or supported", event.getOperation()); - } - - return entities; - } - - private static Operation getOperation(final FalconEvent.OPERATION op) throws FalconException { - switch (op) { - case ADD_CLUSTER: - case ADD_FEED: - case ADD_PROCESS: - return Operation.ADD; - - case UPDATE_CLUSTER: - case UPDATE_FEED: - case UPDATE_PROCESS: - return Operation.UPDATE; - - default: - throw new FalconException("Falcon operation " + op + " is not valid or supported"); - } - } -} - diff --git a/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/model/FalconDataTypes.java b/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/model/FalconDataTypes.java deleted file mode 100644 index e36ff23affd..00000000000 --- a/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/model/FalconDataTypes.java +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.falcon.model; - -/** - * Falcon Data Types for model and bridge. - */ -public enum FalconDataTypes { - // Classes - FALCON_CLUSTER, - FALCON_FEED_CREATION, - FALCON_FEED, - FALCON_FEED_REPLICATION, - FALCON_PROCESS; - - public String getName() { - return name().toLowerCase(); - } - -} diff --git a/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/publisher/FalconEventPublisher.java b/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/publisher/FalconEventPublisher.java deleted file mode 100644 index a01ec14beb3..00000000000 --- a/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/publisher/FalconEventPublisher.java +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.falcon.publisher; - - -import org.apache.atlas.falcon.event.FalconEvent; - -/** - * Falcon publisher for Atlas - */ -public interface FalconEventPublisher { - class Data { - private FalconEvent event; - - public Data(FalconEvent event) { - this.event = event; - } - - public FalconEvent getEvent() { - return event; - } - } - - void publish(final Data data); -} diff --git a/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/service/AtlasService.java b/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/service/AtlasService.java deleted file mode 100644 index 7482ba7b823..00000000000 --- a/addons/falcon-bridge/src/main/java/org/apache/atlas/falcon/service/AtlasService.java +++ /dev/null @@ -1,135 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.falcon.service; - -import org.apache.atlas.falcon.Util.EventUtil; -import org.apache.atlas.falcon.event.FalconEvent; -import org.apache.atlas.falcon.hook.FalconHook; -import org.apache.atlas.falcon.publisher.FalconEventPublisher; -import org.apache.falcon.FalconException; -import org.apache.falcon.entity.v0.Entity; -import org.apache.falcon.entity.v0.EntityType; -import org.apache.falcon.service.ConfigurationChangeListener; -import org.apache.falcon.service.FalconService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -/** - * Atlas service to publish Falcon events - */ -public class AtlasService implements FalconService, ConfigurationChangeListener { - - private static final Logger LOG = LoggerFactory.getLogger(AtlasService.class); - private FalconEventPublisher publisher; - - /** - * Constant for the service name. - */ - public static final String SERVICE_NAME = AtlasService.class.getSimpleName(); - - @Override - public String getName() { - return SERVICE_NAME; - } - - @Override - public void init() throws FalconException { - publisher = new FalconHook(); - } - - @Override - public void destroy() throws FalconException { - } - - @Override - public void onAdd(Entity entity) throws FalconException { - try { - EntityType entityType = entity.getEntityType(); - switch (entityType) { - case CLUSTER: - addEntity(entity, FalconEvent.OPERATION.ADD_CLUSTER); - break; - - case PROCESS: - addEntity(entity, FalconEvent.OPERATION.ADD_PROCESS); - break; - - case FEED: - addEntity(entity, FalconEvent.OPERATION.ADD_FEED); - break; - - default: - LOG.debug("Entity type not processed {}", entityType); - } - } catch(Throwable t) { - LOG.warn("Error handling entity {}", entity, t); - } - } - - @Override - public void onRemove(Entity entity) throws FalconException { - } - - @Override - public void onChange(Entity oldEntity, Entity newEntity) throws FalconException { - /** - * Skipping update for now - update uses full update currently and this might result in all attributes wiped for hive entities - EntityType entityType = newEntity.getEntityType(); - switch (entityType) { - case CLUSTER: - addEntity(newEntity, FalconEvent.OPERATION.UPDATE_CLUSTER); - break; - - case PROCESS: - addEntity(newEntity, FalconEvent.OPERATION.UPDATE_PROCESS); - break; - - case FEED: - FalconEvent.OPERATION operation = isReplicationFeed((Feed) newEntity) ? - FalconEvent.OPERATION.UPDATE_REPLICATION_FEED : - FalconEvent.OPERATION.UPDATE_FEED; - addEntity(newEntity, operation); - break; - - default: - LOG.debug("Entity type not processed {}", entityType); - } - **/ - } - - @Override - public void onReload(Entity entity) throws FalconException { - //Since there is no import script that can import existing falcon entities to atlas, adding on falcon service start - onAdd(entity); - } - - private void addEntity(Entity entity, FalconEvent.OPERATION operation) throws FalconException { - LOG.info("Adding {} entity to Atlas: {}", entity.getEntityType().name(), entity.getName()); - - try { - FalconEvent event = - new FalconEvent(EventUtil.getUser(), operation, entity); - FalconEventPublisher.Data data = new FalconEventPublisher.Data(event); - publisher.publish(data); - } catch (Exception ex) { - throw new FalconException("Unable to publish data to publisher " + ex.getMessage(), ex); - } - } -} diff --git a/addons/falcon-bridge/src/test/java/org/apache/atlas/falcon/hook/FalconHookIT.java b/addons/falcon-bridge/src/test/java/org/apache/atlas/falcon/hook/FalconHookIT.java deleted file mode 100644 index 24f36168c9e..00000000000 --- a/addons/falcon-bridge/src/test/java/org/apache/atlas/falcon/hook/FalconHookIT.java +++ /dev/null @@ -1,351 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.falcon.hook; - -import com.sun.jersey.api.client.ClientResponse; -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasClient; -import org.apache.atlas.AtlasServiceException; -import org.apache.atlas.falcon.bridge.FalconBridge; -import org.apache.atlas.falcon.model.FalconDataTypes; -import org.apache.atlas.hive.bridge.HiveMetaStoreBridge; -import org.apache.atlas.hive.model.HiveDataTypes; -import org.apache.atlas.v1.model.instance.Id; -import org.apache.atlas.v1.model.instance.Referenceable; -import org.apache.atlas.v1.typesystem.types.utils.TypesUtil; -import org.apache.atlas.utils.AuthenticationUtil; -import org.apache.atlas.utils.ParamChecker; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.lang.RandomStringUtils; -import org.apache.atlas.falcon.service.AtlasService; -import org.apache.falcon.entity.FeedHelper; -import org.apache.falcon.entity.FileSystemStorage; -import org.apache.falcon.entity.store.ConfigurationStore; -import org.apache.falcon.entity.v0.Entity; -import org.apache.falcon.entity.v0.EntityType; -import org.apache.falcon.entity.v0.cluster.Cluster; -import org.apache.falcon.entity.v0.feed.Feed; -import org.apache.falcon.entity.v0.feed.Location; -import org.apache.falcon.entity.v0.feed.LocationType; -import org.apache.falcon.entity.v0.process.Process; -import org.apache.falcon.security.CurrentUser; -import org.slf4j.Logger; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import javax.xml.bind.JAXBException; -import java.util.List; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.fail; - -public class FalconHookIT { - public static final Logger LOG = org.slf4j.LoggerFactory.getLogger(FalconHookIT.class); - - public static final String CLUSTER_RESOURCE = "/cluster.xml"; - public static final String FEED_RESOURCE = "/feed.xml"; - public static final String FEED_HDFS_RESOURCE = "/feed-hdfs.xml"; - public static final String FEED_REPLICATION_RESOURCE = "/feed-replication.xml"; - public static final String PROCESS_RESOURCE = "/process.xml"; - - private AtlasClient atlasClient; - - private static final ConfigurationStore STORE = ConfigurationStore.get(); - - @BeforeClass - public void setUp() throws Exception { - Configuration atlasProperties = ApplicationProperties.get(); - if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { - atlasClient = new AtlasClient(atlasProperties.getStringArray(HiveMetaStoreBridge.ATLAS_ENDPOINT), new String[]{"admin", "admin"}); - } else { - atlasClient = new AtlasClient(atlasProperties.getStringArray(HiveMetaStoreBridge.ATLAS_ENDPOINT)); - } - - AtlasService service = new AtlasService(); - service.init(); - STORE.registerListener(service); - CurrentUser.authenticate(System.getProperty("user.name")); - } - - private boolean isDataModelAlreadyRegistered() throws Exception { - try { - atlasClient.getType(FalconDataTypes.FALCON_PROCESS.getName()); - LOG.info("Hive data model is already registered!"); - return true; - } catch(AtlasServiceException ase) { - if (ase.getStatus() == ClientResponse.Status.NOT_FOUND) { - return false; - } - throw ase; - } - } - - private T loadEntity(EntityType type, String resource, String name) throws JAXBException { - Entity entity = (Entity) type.getUnmarshaller().unmarshal(this.getClass().getResourceAsStream(resource)); - switch (entity.getEntityType()) { - case CLUSTER: - ((Cluster) entity).setName(name); - break; - - case FEED: - ((Feed) entity).setName(name); - break; - - case PROCESS: - ((Process) entity).setName(name); - break; - } - return (T)entity; - } - - private String random() { - return RandomStringUtils.randomAlphanumeric(10); - } - - private String getTableUri(String dbName, String tableName) { - return String.format("catalog:%s:%s#ds=${YEAR}-${MONTH}-${DAY}-${HOUR}", dbName, tableName); - } - - @Test - public void testCreateProcess() throws Exception { - Cluster cluster = loadEntity(EntityType.CLUSTER, CLUSTER_RESOURCE, "cluster" + random()); - STORE.publish(EntityType.CLUSTER, cluster); - assertClusterIsRegistered(cluster); - - Feed infeed = getTableFeed(FEED_RESOURCE, cluster.getName(), null); - String infeedId = atlasClient.getEntity(FalconDataTypes.FALCON_FEED.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - FalconBridge.getFeedQualifiedName(infeed.getName(), cluster.getName())).getId()._getId(); - - Feed outfeed = getTableFeed(FEED_RESOURCE, cluster.getName()); - String outFeedId = atlasClient.getEntity(FalconDataTypes.FALCON_FEED.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - FalconBridge.getFeedQualifiedName(outfeed.getName(), cluster.getName())).getId()._getId(); - - Process process = loadEntity(EntityType.PROCESS, PROCESS_RESOURCE, "process" + random()); - process.getClusters().getClusters().get(0).setName(cluster.getName()); - process.getInputs().getInputs().get(0).setFeed(infeed.getName()); - process.getOutputs().getOutputs().get(0).setFeed(outfeed.getName()); - STORE.publish(EntityType.PROCESS, process); - - String pid = assertProcessIsRegistered(process, cluster.getName()); - Referenceable processEntity = atlasClient.getEntity(pid); - assertNotNull(processEntity); - assertEquals(processEntity.get(AtlasClient.NAME), process.getName()); - assertEquals(((List)processEntity.get("inputs")).get(0)._getId(), infeedId); - assertEquals(((List)processEntity.get("outputs")).get(0)._getId(), outFeedId); - } - - private String assertProcessIsRegistered(Process process, String clusterName) throws Exception { - return assertEntityIsRegistered(FalconDataTypes.FALCON_PROCESS.getName(), - AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - FalconBridge.getProcessQualifiedName(process.getName(), clusterName)); - } - - private String assertClusterIsRegistered(Cluster cluster) throws Exception { - return assertEntityIsRegistered(FalconDataTypes.FALCON_CLUSTER.getName(), - AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, cluster.getName()); - } - - private TypesUtil.Pair getHDFSFeed(String feedResource, String clusterName) throws Exception { - Feed feed = loadEntity(EntityType.FEED, feedResource, "feed" + random()); - org.apache.falcon.entity.v0.feed.Cluster feedCluster = feed.getClusters().getClusters().get(0); - feedCluster.setName(clusterName); - STORE.publish(EntityType.FEED, feed); - String feedId = assertFeedIsRegistered(feed, clusterName); - assertFeedAttributes(feedId); - - String processId = assertEntityIsRegistered(FalconDataTypes.FALCON_FEED_CREATION.getName(), - AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - FalconBridge.getFeedQualifiedName(feed.getName(), clusterName)); - Referenceable processEntity = atlasClient.getEntity(processId); - assertEquals(((List)processEntity.get("outputs")).get(0).getId(), feedId); - - String inputId = ((List) processEntity.get("inputs")).get(0).getId(); - Referenceable pathEntity = atlasClient.getEntity(inputId); - assertEquals(pathEntity.getTypeName(), HiveMetaStoreBridge.HDFS_PATH); - - List locations = FeedHelper.getLocations(feedCluster, feed); - Location dataLocation = FileSystemStorage.getLocation(locations, LocationType.DATA); - assertEquals(pathEntity.get(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME), - FalconBridge.normalize(dataLocation.getPath())); - - return TypesUtil.Pair.of(feedId, feed); - } - - private Feed getTableFeed(String feedResource, String clusterName) throws Exception { - return getTableFeed(feedResource, clusterName, null); - } - - private Feed getTableFeed(String feedResource, String clusterName, String secondClusterName) throws Exception { - Feed feed = loadEntity(EntityType.FEED, feedResource, "feed" + random()); - org.apache.falcon.entity.v0.feed.Cluster feedCluster = feed.getClusters().getClusters().get(0); - feedCluster.setName(clusterName); - String dbName = "db" + random(); - String tableName = "table" + random(); - feedCluster.getTable().setUri(getTableUri(dbName, tableName)); - - String dbName2 = "db" + random(); - String tableName2 = "table" + random(); - - if (secondClusterName != null) { - org.apache.falcon.entity.v0.feed.Cluster feedCluster2 = feed.getClusters().getClusters().get(1); - feedCluster2.setName(secondClusterName); - feedCluster2.getTable().setUri(getTableUri(dbName2, tableName2)); - } - - STORE.publish(EntityType.FEED, feed); - String feedId = assertFeedIsRegistered(feed, clusterName); - assertFeedAttributes(feedId); - verifyFeedLineage(feed.getName(), clusterName, feedId, dbName, tableName); - - if (secondClusterName != null) { - String feedId2 = assertFeedIsRegistered(feed, secondClusterName); - assertFeedAttributes(feedId2); - verifyFeedLineage(feed.getName(), secondClusterName, feedId2, dbName2, tableName2); - } - return feed; - } - - private void assertFeedAttributes(String feedId) throws Exception { - Referenceable feedEntity = atlasClient.getEntity(feedId); - assertEquals(feedEntity.get(AtlasClient.OWNER), "testuser"); - assertEquals(feedEntity.get(FalconBridge.FREQUENCY), "hours(1)"); - assertEquals(feedEntity.get(AtlasClient.DESCRIPTION), "test input"); - } - - private void verifyFeedLineage(String feedName, String clusterName, String feedId, String dbName, String tableName) - throws Exception{ - //verify that lineage from hive table to falcon feed is created - String processId = assertEntityIsRegistered(FalconDataTypes.FALCON_FEED_CREATION.getName(), - AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - FalconBridge.getFeedQualifiedName(feedName, clusterName)); - Referenceable processEntity = atlasClient.getEntity(processId); - assertEquals(((List)processEntity.get("outputs")).get(0).getId(), feedId); - - String inputId = ((List) processEntity.get("inputs")).get(0).getId(); - Referenceable tableEntity = atlasClient.getEntity(inputId); - assertEquals(tableEntity.getTypeName(), HiveDataTypes.HIVE_TABLE.getName()); - assertEquals(tableEntity.get(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME), - HiveMetaStoreBridge.getTableQualifiedName(clusterName, dbName, tableName)); - - } - - private String assertFeedIsRegistered(Feed feed, String clusterName) throws Exception { - return assertEntityIsRegistered(FalconDataTypes.FALCON_FEED.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - FalconBridge.getFeedQualifiedName(feed.getName(), clusterName)); - } - - @Test - public void testReplicationFeed() throws Exception { - Cluster srcCluster = loadEntity(EntityType.CLUSTER, CLUSTER_RESOURCE, "cluster" + random()); - STORE.publish(EntityType.CLUSTER, srcCluster); - assertClusterIsRegistered(srcCluster); - - Cluster targetCluster = loadEntity(EntityType.CLUSTER, CLUSTER_RESOURCE, "cluster" + random()); - STORE.publish(EntityType.CLUSTER, targetCluster); - assertClusterIsRegistered(targetCluster); - - Feed feed = getTableFeed(FEED_REPLICATION_RESOURCE, srcCluster.getName(), targetCluster.getName()); - String inId = atlasClient.getEntity(FalconDataTypes.FALCON_FEED.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - FalconBridge.getFeedQualifiedName(feed.getName(), srcCluster.getName())).getId()._getId(); - String outId = atlasClient.getEntity(FalconDataTypes.FALCON_FEED.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - FalconBridge.getFeedQualifiedName(feed.getName(), targetCluster.getName())).getId()._getId(); - - - String processId = assertEntityIsRegistered(FalconDataTypes.FALCON_FEED_REPLICATION.getName(), - AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, feed.getName()); - Referenceable process = atlasClient.getEntity(processId); - assertEquals(((List)process.get("inputs")).get(0)._getId(), inId); - assertEquals(((List)process.get("outputs")).get(0)._getId(), outId); - } - - @Test - public void testCreateProcessWithHDFSFeed() throws Exception { - Cluster cluster = loadEntity(EntityType.CLUSTER, CLUSTER_RESOURCE, "cluster" + random()); - STORE.publish(EntityType.CLUSTER, cluster); - - TypesUtil.Pair result = getHDFSFeed(FEED_HDFS_RESOURCE, cluster.getName()); - Feed infeed = result.right; - String infeedId = result.left; - - Feed outfeed = getTableFeed(FEED_RESOURCE, cluster.getName()); - String outfeedId = atlasClient.getEntity(FalconDataTypes.FALCON_FEED.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - FalconBridge.getFeedQualifiedName(outfeed.getName(), cluster.getName())).getId()._getId(); - - Process process = loadEntity(EntityType.PROCESS, PROCESS_RESOURCE, "process" + random()); - process.getClusters().getClusters().get(0).setName(cluster.getName()); - process.getInputs().getInputs().get(0).setFeed(infeed.getName()); - process.getOutputs().getOutputs().get(0).setFeed(outfeed.getName()); - STORE.publish(EntityType.PROCESS, process); - - String pid = assertProcessIsRegistered(process, cluster.getName()); - Referenceable processEntity = atlasClient.getEntity(pid); - assertEquals(processEntity.get(AtlasClient.NAME), process.getName()); - assertEquals(processEntity.get(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME), - FalconBridge.getProcessQualifiedName(process.getName(), cluster.getName())); - assertEquals(((List)processEntity.get("inputs")).get(0)._getId(), infeedId); - assertEquals(((List)processEntity.get("outputs")).get(0)._getId(), outfeedId); - } - - private String assertEntityIsRegistered(final String typeName, final String property, final String value) throws Exception { - waitFor(80000, new Predicate() { - @Override - public void evaluate() throws Exception { - Referenceable entity = atlasClient.getEntity(typeName, property, value); - assertNotNull(entity); - } - }); - Referenceable entity = atlasClient.getEntity(typeName, property, value); - return entity.getId()._getId(); - } - - public interface Predicate { - /** - * Perform a predicate evaluation. - * - * @return the boolean result of the evaluation. - * @throws Exception thrown if the predicate evaluation could not evaluate. - */ - void evaluate() throws Exception; - } - - /** - * Wait for a condition, expressed via a {@link Predicate} to become true. - * - * @param timeout maximum time in milliseconds to wait for the predicate to become true. - * @param predicate predicate waiting on. - */ - protected void waitFor(int timeout, Predicate predicate) throws Exception { - ParamChecker.notNull(predicate, "predicate"); - long mustEnd = System.currentTimeMillis() + timeout; - - while (true) { - try { - predicate.evaluate(); - return; - } catch(Error | Exception e) { - if (System.currentTimeMillis() >= mustEnd) { - fail("Assertions failed. Failing after waiting for timeout " + timeout + " msecs", e); - } - LOG.debug("Waiting up to {} msec as assertion failed", mustEnd - System.currentTimeMillis(), e); - Thread.sleep(400); - } - } - } -} diff --git a/addons/falcon-bridge/src/test/resources/atlas-application.properties b/addons/falcon-bridge/src/test/resources/atlas-application.properties deleted file mode 100644 index 3b12e5fb333..00000000000 --- a/addons/falcon-bridge/src/test/resources/atlas-application.properties +++ /dev/null @@ -1,125 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# - -######### Atlas Server Configs ######### -atlas.rest.address=http://localhost:31000 - -######### Graph Database Configs ######### - - -# Graph database implementation. Value inserted by maven. -atlas.graphdb.backend=org.apache.atlas.repository.graphdb.janus.AtlasJanusGraphDatabase -atlas.graph.index.search.solr.wait-searcher=true - -# Graph Storage -atlas.graph.storage.backend=berkeleyje - -# Entity repository implementation -atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.InMemoryEntityAuditRepository - -# Graph Search Index Backend -atlas.graph.index.search.backend=solr - -#Berkeley storage directory -atlas.graph.storage.directory=${sys:atlas.data}/berkley - -#hbase -#For standalone mode , specify localhost -#for distributed mode, specify zookeeper quorum here - -atlas.graph.storage.hostname=${graph.storage.hostname} -atlas.graph.storage.hbase.regions-per-server=1 -atlas.graph.storage.lock.wait-time=10000 - -#ElasticSearch -atlas.graph.index.search.directory=${sys:atlas.data}/es -atlas.graph.index.search.elasticsearch.client-only=false -atlas.graph.index.search.elasticsearch.local-mode=true -atlas.graph.index.search.elasticsearch.create.sleep=2000 - -# Solr cloud mode properties -atlas.graph.index.search.solr.mode=cloud -atlas.graph.index.search.solr.zookeeper-url=${solr.zk.address} -atlas.graph.index.search.solr.embedded=true -atlas.graph.index.search.max-result-set-size=150 - - -######### Notification Configs ######### -atlas.notification.embedded=true - -atlas.kafka.zookeeper.connect=localhost:19026 -atlas.kafka.bootstrap.servers=localhost:19027 -atlas.kafka.data=${sys:atlas.data}/kafka -atlas.kafka.zookeeper.session.timeout.ms=4000 -atlas.kafka.zookeeper.sync.time.ms=20 -atlas.kafka.consumer.timeout.ms=4000 -atlas.kafka.auto.commit.interval.ms=100 -atlas.kafka.hook.group.id=atlas -atlas.kafka.entities.group.id=atlas_entities -#atlas.kafka.auto.commit.enable=false - -atlas.kafka.enable.auto.commit=false -atlas.kafka.auto.offset.reset=earliest -atlas.kafka.session.timeout.ms=30000 -atlas.kafka.offsets.topic.replication.factor=1 - - - -######### Entity Audit Configs ######### -atlas.audit.hbase.tablename=ATLAS_ENTITY_AUDIT_EVENTS -atlas.audit.zookeeper.session.timeout.ms=1000 -atlas.audit.hbase.zookeeper.quorum=localhost -atlas.audit.hbase.zookeeper.property.clientPort=19026 - -######### Security Properties ######### - -# SSL config -atlas.enableTLS=false -atlas.server.https.port=31443 - -######### Security Properties ######### - -hbase.security.authentication=simple - -atlas.hook.falcon.synchronous=true - -######### JAAS Configuration ######## - -atlas.jaas.KafkaClient.loginModuleName = com.sun.security.auth.module.Krb5LoginModule -atlas.jaas.KafkaClient.loginModuleControlFlag = required -atlas.jaas.KafkaClient.option.useKeyTab = true -atlas.jaas.KafkaClient.option.storeKey = true -atlas.jaas.KafkaClient.option.serviceName = kafka -atlas.jaas.KafkaClient.option.keyTab = /etc/security/keytabs/atlas.service.keytab -atlas.jaas.KafkaClient.option.principal = atlas/_HOST@EXAMPLE.COM - -######### High Availability Configuration ######## -atlas.server.ha.enabled=false -#atlas.server.ids=id1 -#atlas.server.address.id1=localhost:21000 - -######### Atlas Authorization ######### -atlas.authorizer.impl=none -# atlas.authorizer.impl=simple -# atlas.authorizer.simple.authz.policy.file=atlas-simple-authz-policy.json - -######### Atlas Authentication ######### -atlas.authentication.method.file=true -atlas.authentication.method.ldap.type=none -atlas.authentication.method.kerberos=false -# atlas.authentication.method.file.filename=users-credentials.properties diff --git a/addons/falcon-bridge/src/test/resources/atlas-log4j.xml b/addons/falcon-bridge/src/test/resources/atlas-log4j.xml deleted file mode 100755 index 262a710f7aa..00000000000 --- a/addons/falcon-bridge/src/test/resources/atlas-log4j.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/falcon-bridge/src/test/resources/cluster.xml b/addons/falcon-bridge/src/test/resources/cluster.xml deleted file mode 100644 index b183847db38..00000000000 --- a/addons/falcon-bridge/src/test/resources/cluster.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/falcon-bridge/src/test/resources/feed-hdfs.xml b/addons/falcon-bridge/src/test/resources/feed-hdfs.xml deleted file mode 100644 index 435db074518..00000000000 --- a/addons/falcon-bridge/src/test/resources/feed-hdfs.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - online,bi - - hours(1) - UTC - - - - - - - - - - - - - - - - diff --git a/addons/falcon-bridge/src/test/resources/feed-replication.xml b/addons/falcon-bridge/src/test/resources/feed-replication.xml deleted file mode 100644 index dcd427b1800..00000000000 --- a/addons/falcon-bridge/src/test/resources/feed-replication.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - online,bi - - hours(1) - UTC - - - - - - - - - - - -
- - - -
- - - - diff --git a/addons/falcon-bridge/src/test/resources/feed.xml b/addons/falcon-bridge/src/test/resources/feed.xml deleted file mode 100644 index 473c745ce89..00000000000 --- a/addons/falcon-bridge/src/test/resources/feed.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - online,bi - - hours(1) - UTC - - - - - - -
- - - -
- - - - diff --git a/addons/falcon-bridge/src/test/resources/hive-site.xml b/addons/falcon-bridge/src/test/resources/hive-site.xml deleted file mode 100644 index f058c2edc20..00000000000 --- a/addons/falcon-bridge/src/test/resources/hive-site.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - hive.exec.post.hooks - org.apache.atlas.hive.hook.HiveHook - - - - hive.support.concurrency - false - - - - hive.metastore.warehouse.dir - ${user.dir}/target/metastore - - - - javax.jdo.option.ConnectionURL - jdbc:derby:${user.dir}/target/metastore_db;create=true - - - - atlas.hook.hive.synchronous - true - - - - fs.pfile.impl - org.apache.hadoop.fs.ProxyLocalFileSystem - - \ No newline at end of file diff --git a/addons/falcon-bridge/src/test/resources/process.xml b/addons/falcon-bridge/src/test/resources/process.xml deleted file mode 100644 index b94d0a8470a..00000000000 --- a/addons/falcon-bridge/src/test/resources/process.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - consumer=consumer@xyz.com, owner=producer@xyz.com, department=forecasting - - - - - - - - 1 - FIFO - days(1) - UTC - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/falcon-bridge/src/test/resources/startup.properties b/addons/falcon-bridge/src/test/resources/startup.properties deleted file mode 100644 index 96234703965..00000000000 --- a/addons/falcon-bridge/src/test/resources/startup.properties +++ /dev/null @@ -1,21 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# - -*.domain=debug -*.config.store.persist=false -*.config.store.uri=target/config_store \ No newline at end of file diff --git a/addons/falcon-bridge/src/test/resources/users-credentials.properties b/addons/falcon-bridge/src/test/resources/users-credentials.properties deleted file mode 100644 index da69923502e..00000000000 --- a/addons/falcon-bridge/src/test/resources/users-credentials.properties +++ /dev/null @@ -1,3 +0,0 @@ -#username=group::sha256+salt-password -admin=ADMIN::a4a88c0872bf652bb9ed803ece5fd6e82354838a9bf59ab4babb1dab322154e1 -rangertagsync=RANGER_TAG_SYNC::0afe7a1968b07d4c3ff4ed8c2d809a32ffea706c66cd795ead9048e81cfaf034 diff --git a/addons/hbase-bridge-shim/pom.xml b/addons/hbase-bridge-shim/pom.xml deleted file mode 100644 index eb1b2e9493d..00000000000 --- a/addons/hbase-bridge-shim/pom.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - hbase-bridge-shim - Apache Atlas Hbase Bridge Shim Module - Apache Atlas Hbase Bridge Shim - jar - - - - - org.apache.atlas - atlas-plugin-classloader - - - org.apache.hbase - hbase-server - ${hbase.version} - provided - - - javax.servlet - servlet-api - - - com.github.stephenc.findbugs - findbugs-annotations - - - javax.ws.rs - * - - - - - diff --git a/addons/hbase-bridge-shim/src/main/java/org/apache/atlas/hbase/hook/HBaseAtlasCoprocessor.java b/addons/hbase-bridge-shim/src/main/java/org/apache/atlas/hbase/hook/HBaseAtlasCoprocessor.java deleted file mode 100755 index 0b69104b17d..00000000000 --- a/addons/hbase-bridge-shim/src/main/java/org/apache/atlas/hbase/hook/HBaseAtlasCoprocessor.java +++ /dev/null @@ -1,277 +0,0 @@ -/** - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hbase.hook; - - -import org.apache.atlas.plugin.classloader.AtlasPluginClassLoader; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.hbase.NamespaceDescriptor; -import org.apache.hadoop.hbase.TableName; -import org.apache.hadoop.hbase.client.RegionInfo; -import org.apache.hadoop.hbase.CoprocessorEnvironment; -import org.apache.hadoop.hbase.client.SnapshotDescription; -import org.apache.hadoop.hbase.client.TableDescriptor; -import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor; -import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment; -import org.apache.hadoop.hbase.coprocessor.MasterObserver; -import org.apache.hadoop.hbase.coprocessor.ObserverContext; -import org.apache.hadoop.hbase.coprocessor.RegionObserver; -import org.apache.hadoop.hbase.coprocessor.RegionServerObserver; - -import java.io.IOException; -import java.util.Optional; - - -public class HBaseAtlasCoprocessor implements MasterCoprocessor, MasterObserver, RegionObserver, RegionServerObserver { - public static final Log LOG = LogFactory.getLog(HBaseAtlasCoprocessor.class); - - private static final String ATLAS_PLUGIN_TYPE = "hbase"; - private static final String ATLAS_HBASE_HOOK_IMPL_CLASSNAME = "org.apache.atlas.hbase.hook.HBaseAtlasCoprocessor"; - - private AtlasPluginClassLoader atlasPluginClassLoader = null; - private Object impl = null; - private MasterObserver implMasterObserver = null; - private RegionObserver implRegionObserver = null; - private RegionServerObserver implRegionServerObserver = null; - private MasterCoprocessor implMasterCoprocessor = null; - - public HBaseAtlasCoprocessor() { - if(LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasCoprocessor.HBaseAtlasCoprocessor()"); - } - - this.init(); - - if(LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.HBaseAtlasCoprocessor()"); - } - } - - private void init(){ - if(LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasCoprocessor.init()"); - } - - try { - atlasPluginClassLoader = AtlasPluginClassLoader.getInstance(ATLAS_PLUGIN_TYPE, this.getClass()); - - @SuppressWarnings("unchecked") - Class cls = Class.forName(ATLAS_HBASE_HOOK_IMPL_CLASSNAME, true, atlasPluginClassLoader); - - activatePluginClassLoader(); - - impl = cls.newInstance(); - implMasterObserver = (MasterObserver)impl; - implRegionObserver = (RegionObserver)impl; - implRegionServerObserver = (RegionServerObserver)impl; - implMasterCoprocessor = (MasterCoprocessor)impl; - - } catch (Exception e) { - // check what need to be done - LOG.error("Error Enabling RangerHbasePlugin", e); - } finally { - deactivatePluginClassLoader(); - } - - if(LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.init()"); - } - } - - @Override - public Optional getMasterObserver() { - return Optional.of(this); - } - - @Override - public void start(CoprocessorEnvironment env) throws IOException { - if(LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasCoprocessor.start()"); - } - - try { - activatePluginClassLoader(); - if (env instanceof MasterCoprocessorEnvironment) { - implMasterCoprocessor.start(env); - } - } finally { - deactivatePluginClassLoader(); - } - if(LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.start()"); - } - } - - @Override - public void postCreateTable(ObserverContext ctx, TableDescriptor desc, RegionInfo[] regions) throws IOException { - if(LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasCoprocessor.postCreateTable()"); - } - - try { - activatePluginClassLoader(); - implMasterObserver.postCreateTable(ctx, desc, regions); - } finally { - deactivatePluginClassLoader(); - } - - if(LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.postCreateTable()"); - } - } - - @Override - public void postModifyTable(ObserverContext ctx, TableName tableName, TableDescriptor htd) throws IOException { - if(LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasCoprocessor.postModifyTable()"); - } - - try { - activatePluginClassLoader(); - implMasterObserver.postModifyTable(ctx, tableName, htd); - } finally { - deactivatePluginClassLoader(); - } - - if(LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.postModifyTable()"); - } - } - - @Override - public void postDeleteTable(ObserverContext ctx, TableName tableName) throws IOException { - if(LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasCoprocessor.postDeleteTable()"); - } - - try { - activatePluginClassLoader(); - implMasterObserver.postDeleteTable(ctx, tableName); - } finally { - deactivatePluginClassLoader(); - } - - if(LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.postDeleteTable()"); - } - } - - @Override - public void postCreateNamespace(ObserverContext ctx, NamespaceDescriptor ns) throws IOException { - if(LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasCoprocessor.preCreateNamespace()"); - } - - try { - activatePluginClassLoader(); - implMasterObserver.postCreateNamespace(ctx, ns); - } finally { - deactivatePluginClassLoader(); - } - - if(LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.preCreateNamespace()"); - } - } - - @Override - public void postDeleteNamespace(ObserverContext ctx, String ns) throws IOException { - if(LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasCoprocessor.preDeleteNamespace()"); - } - - try { - activatePluginClassLoader(); - implMasterObserver.postDeleteNamespace(ctx, ns); - } finally { - deactivatePluginClassLoader(); - } - - if(LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.preDeleteNamespace()"); - } - } - @Override - public void postModifyNamespace(ObserverContext ctx, NamespaceDescriptor ns) throws IOException { - if(LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasCoprocessor.preModifyNamespace()"); - } - - try { - activatePluginClassLoader(); - implMasterObserver.preModifyNamespace(ctx, ns); - } finally { - deactivatePluginClassLoader(); - } - - if(LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.preModifyNamespace()"); - } - } - - @Override - public void postCloneSnapshot(ObserverContext observerContext, SnapshotDescription snapshot, TableDescriptor tableDescriptor) throws IOException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasCoprocessor.postCloneSnapshot()"); - } - - try { - activatePluginClassLoader(); - implMasterObserver.postCloneSnapshot(observerContext,snapshot,tableDescriptor); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.postCloneSnapshot()"); - } - } - - @Override - public void postRestoreSnapshot(ObserverContext observerContext, SnapshotDescription snapshot, TableDescriptor tableDescriptor) throws IOException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasCoprocessor.postRestoreSnapshot()"); - } - - try { - activatePluginClassLoader(); - implMasterObserver.postRestoreSnapshot(observerContext,snapshot,tableDescriptor); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.postRestoreSnapshot()"); - } - } - - private void activatePluginClassLoader() { - if(atlasPluginClassLoader != null) { - atlasPluginClassLoader.activate(); - } - } - - private void deactivatePluginClassLoader() { - if(atlasPluginClassLoader != null) { - atlasPluginClassLoader.deactivate(); - } - } - -} diff --git a/addons/hbase-bridge/pom.xml b/addons/hbase-bridge/pom.xml deleted file mode 100644 index a6ed51421fb..00000000000 --- a/addons/hbase-bridge/pom.xml +++ /dev/null @@ -1,568 +0,0 @@ - - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - hbase-bridge - Apache Atlas Hbase Bridge Module - Apache Atlas Hbase Bridge - jar - - - 3.0.3 - 9.3.14.v20161028 - - - - - - org.apache.hbase - hbase-server - ${hbase.version} - provided - - - javax.servlet - servlet-api - - - org.mortbay.jetty - servlet-api-2.5 - - - - - - org.apache.atlas - atlas-notification - - - - - com.sun.jersey - jersey-bundle - 1.19 - test - - - - org.apache.atlas - atlas-webapp - war - test - - - - org.apache.hadoop - hadoop-client - ${hadoop.version} - - - - org.apache.hadoop - hadoop-hdfs - ${hadoop.version} - - - javax.servlet - servlet-api - - - - - org.apache.hadoop - hadoop-hdfs-client - ${hadoop.version} - - - - org.apache.hadoop - hadoop-annotations - - - - org.apache.hadoop - hadoop-minicluster - ${hadoop.version} - - - javax.servlet - servlet-api - - - - - - org.testng - testng - - - - org.mockito - mockito-all - - - - org.apache.httpcomponents - httpcore - ${httpcomponents-httpcore.version} - - - - org.eclipse.jetty - jetty-webapp - ${jetty.version} - compile - - - - org.eclipse.jetty - jetty-server - test - - - - org.apache.hbase - hbase-server - ${hbase.version} - test-jar - test - - - org.mortbay.jetty - servlet-api-2.5 - - - org.eclipse.jetty - jetty-server - - - - - - junit - junit - test - 4.12 - - - - org.apache.hbase - hbase-client - ${hbase.version} - - - org.apache.hbase - hbase-common - ${hbase.version} - - - com.github.stephenc.findbugs - findbugs-annotations - - - - - org.apache.hbase - hbase-hadoop2-compat - ${hbase.version} - test-jar - test - - - org.apache.hbase - hbase-hadoop-compat - ${hbase.version} - test-jar - test - - - com.google.guava - guava - - - org.apache.hadoop - hadoop-common - ${hadoop.version} - compile - - - javax.servlet - servlet-api - - - - - org.apache.hadoop - hadoop-auth - ${hadoop.version} - compile - - - org.apache.atlas - atlas-client-v2 - ${project.version} - - - org.apache.hbase - hbase-zookeeper - test-jar - test - ${hbase.version} - - - org.apache.hbase - hbase-common - test-jar - ${hbase.version} - test - - - - - org.apache.hbase - hbase-testing-util - ${hbase.version} - - - - - - - dist - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-hook - package - - copy - - - ${project.build.directory}/dependency/hook/hbase/atlas-hbase-plugin-impl - false - false - true - - - ${project.groupId} - ${project.artifactId} - ${project.version} - - - ${project.groupId} - atlas-client-common - ${project.version} - - - ${project.groupId} - atlas-client-v2 - ${project.version} - - - ${project.groupId} - atlas-intg - ${project.version} - - - ${project.groupId} - atlas-notification - ${project.version} - - - ${project.groupId} - atlas-common - ${project.version} - - - org.apache.kafka - kafka_${kafka.scala.binary.version} - ${kafka.version} - - - org.apache.kafka - kafka-clients - ${kafka.version} - - - com.sun.jersey.contribs - jersey-multipart - ${jersey.version} - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.databind.version} - - - com.fasterxml.jackson.core - jackson-core - ${jackson.version} - - - com.fasterxml.jackson.core - jackson-annotations - ${jackson.version} - - - commons-configuration - commons-configuration - ${commons-conf.version} - - - com.sun.jersey - jersey-json - ${jersey.version} - - - javax.ws.rs - jsr311-api - ${jsr.version} - - - - - - copy-hook-shim - package - - copy - - - ${project.build.directory}/dependency/hook/hbase - false - false - true - - - ${project.groupId} - hbase-bridge-shim - ${project.version} - - - ${project.groupId} - atlas-plugin-classloader - ${project.version} - - - - - - - - - - - - - - org.eclipse.jetty - jetty-maven-plugin - ${jetty.version} - - ${skipTests} - - - 31000 - 60000 - - ../../webapp/target/atlas-webapp-${project.version}.war - true - ../../webapp/src/main/webapp - - / - ${project.basedir}/../../webapp/src/main/webapp/WEB-INF/web.xml - - true - - true - - atlas.home - ${project.build.directory} - - - atlas.conf - ${project.build.directory}/test-classes - - - atlas.data - ${project.build.directory}/data - - - atlas.log.dir - ${project.build.directory}/logs - - - atlas.log.file - application.log - - - log4j.configuration - file:///${project.build.directory}/test-classes/atlas-log4j.xml - - - atlas.graphdb.backend - ${graphdb.backend.impl} - - - embedded.solr.directory - ${project.build.directory} - - - solr.log.dir - ${project.build.directory}/logs - - - org.eclipse.jetty.annotations.maxWait - 5000 - - - atlas-stop - 31001 - ${jetty-maven-plugin.stopWait} - jar - - - - org.apache.curator - curator-client - ${curator.version} - - - - org.apache.zookeeper - zookeeper - ${zookeeper.version} - - - - - start-jetty - pre-integration-test - - - stop - deploy-war - - - true - - - - stop-jetty - post-integration-test - - stop - - - - - - - org.apache.maven.plugins - maven-site-plugin - - - org.apache.maven.doxia - doxia-module-twiki - ${doxia.version} - - - org.apache.maven.doxia - doxia-core - ${doxia.version} - - - - - - site - - prepare-package - - - - false - false - - - - - org.codehaus.mojo - exec-maven-plugin - 1.2.1 - false - - - - - - org.apache.maven.plugins - maven-resources-plugin - - - copy-resources - validate - - copy-resources - - - ${basedir}/target/models - - - ${basedir}/../models - - 0000-Area0/** - 1000-Hadoop/** - - - - - - - copy-solr-resources - validate - - copy-resources - - - ${project.build.directory}/solr - - - ${basedir}/../../test-tools/src/main/resources/solr - - - - - - - - - - diff --git a/addons/hbase-bridge/src/bin/import-hbase.sh b/addons/hbase-bridge/src/bin/import-hbase.sh deleted file mode 100644 index a343036fafd..00000000000 --- a/addons/hbase-bridge/src/bin/import-hbase.sh +++ /dev/null @@ -1,162 +0,0 @@ -#!/bin/bash -# -# 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. See accompanying LICENSE file. -# - -# resolve links - $0 may be a softlink -PRG="${0}" - -[[ `uname -s` == *"CYGWIN"* ]] && CYGWIN=true - -while [ -h "${PRG}" ]; do - ls=`ls -ld "${PRG}"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "${PRG}"`/"$link" - fi -done - -echo ">>>>> $PRG" - -BASEDIR=`dirname ${PRG}` -BASEDIR=`cd ${BASEDIR}/..;pwd` - -echo ">>>>> $BASEDIR" - -if test -z "${JAVA_HOME}" -then - JAVA_BIN=`which java` - JAR_BIN=`which jar` -else - JAVA_BIN="${JAVA_HOME}/bin/java" - JAR_BIN="${JAVA_HOME}/bin/jar" -fi -export JAVA_BIN - -if [ ! -e "${JAVA_BIN}" ] || [ ! -e "${JAR_BIN}" ]; then - echo "$JAVA_BIN and/or $JAR_BIN not found on the system. Please make sure java and jar commands are available." - exit 1 -fi - -# Construct Atlas classpath using jars from hook/hbase/atlas-hbase-plugin-impl/ directory. -for i in "${BASEDIR}/hook/hbase/atlas-hbase-plugin-impl/"*.jar; do - ATLASCPPATH="${ATLASCPPATH}:$i" -done - -if [ -z "${ATLAS_CONF_DIR}" ] && [ -e /etc/atlas/conf ];then - ATLAS_CONF_DIR=/etc/atlas/conf -fi -ATLASCPPATH=${ATLASCPPATH}:${ATLAS_CONF_DIR} - -# log dir for applications -ATLAS_LOG_DIR="${ATLAS_LOG_DIR:-/var/log/atlas}" -export ATLAS_LOG_DIR -LOGFILE="$ATLAS_LOG_DIR/import-hbase.log" - -TIME=`date +%Y%m%d%H%M%s` - -#Add HBase conf in classpath -if [ ! -z "$HBASE_CONF_DIR" ]; then - HBASE_CONF=$HBASE_CONF_DIR -elif [ ! -z "$HBASE_HOME" ]; then - HBASE_CONF="$HBASE_HOME/conf" -elif [ -e /etc/hbase/conf ]; then - HBASE_CONF="/etc/hbase/conf" -else - echo "Could not find a valid HBASE configuration" - exit 1 -fi - -echo Using HBase configuration directory "[$HBASE_CONF]" - - -if [ -f "${HBASE_CONF}/hbase-env.sh" ]; then - . "${HBASE_CONF}/hbase-env.sh" -fi - -if [ -z "$HBASE_HOME" ]; then - if [ -d "${BASEDIR}/../hbase" ]; then - HBASE_HOME=${BASEDIR}/../hbase - else - echo "Please set HBASE_HOME to the root of HBase installation" - exit 1 - fi -fi - -HBASE_CP="${HBASE_CONF}" - -for i in "${HBASE_HOME}/lib/"*.jar; do - HBASE_CP="${HBASE_CP}:$i" -done - -#Add hadoop conf in classpath -if [ ! -z "$HADOOP_CLASSPATH" ]; then - HADOOP_CP=$HADOOP_CLASSPATH -elif [ ! -z "$HADOOP_HOME" ]; then - HADOOP_CP=`$HADOOP_HOME/bin/hadoop classpath` -elif [ $(command -v hadoop) ]; then - HADOOP_CP=`hadoop classpath` - echo $HADOOP_CP -else - echo "Environment variable HADOOP_CLASSPATH or HADOOP_HOME need to be set" - exit 1 -fi - -CP="${HBASE_CP}:${HADOOP_CP}:${ATLASCPPATH}" - -# If running in cygwin, convert pathnames and classpath to Windows format. -if [ "${CYGWIN}" == "true" ] -then - ATLAS_LOG_DIR=`cygpath -w ${ATLAS_LOG_DIR}` - LOGFILE=`cygpath -w ${LOGFILE}` - HBASE_CP=`cygpath -w ${HBASE_CP}` - HADOOP_CP=`cygpath -w ${HADOOP_CP}` - CP=`cygpath -w -p ${CP}` -fi - -JAVA_PROPERTIES="$ATLAS_OPTS -Datlas.log.dir=$ATLAS_LOG_DIR -Datlas.log.file=import-hbase.log --Dlog4j.configuration=atlas-hbase-import-log4j.xml" - -IMPORT_ARGS= -JVM_ARGS= - -while true -do - option=$1 - shift - - case "$option" in - -n) IMPORT_ARGS="$IMPORT_ARGS -n $1"; shift;; - -t) IMPORT_ARGS="$IMPORT_ARGS -t $1"; shift;; - -f) IMPORT_ARGS="$IMPORT_ARGS -f $1"; shift;; - --namespace) IMPORT_ARGS="$IMPORT_ARGS --namespace $1"; shift;; - --table) IMPORT_ARGS="$IMPORT_ARGS --table $1"; shift;; - --filename) IMPORT_ARGS="$IMPORT_ARGS --filename $1"; shift;; - "") break;; - *) JVM_ARGS="$JVM_ARGS $option" - esac -done - -JAVA_PROPERTIES="${JAVA_PROPERTIES} ${JVM_ARGS}" - -echo "Log file for import is $LOGFILE" - -"${JAVA_BIN}" ${JAVA_PROPERTIES} -cp "${CP}" org.apache.atlas.hbase.bridge.HBaseBridge $IMPORT_ARGS - -RETVAL=$? -[ $RETVAL -eq 0 ] && echo HBase Data Model imported successfully!!! -[ $RETVAL -ne 0 ] && echo Failed to import HBase Data Model!!! - -exit $RETVAL diff --git a/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/bridge/HBaseAtlasHook.java b/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/bridge/HBaseAtlasHook.java deleted file mode 100644 index 8e6c57dba37..00000000000 --- a/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/bridge/HBaseAtlasHook.java +++ /dev/null @@ -1,678 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hbase.bridge; - -import org.apache.atlas.AtlasConstants; -import org.apache.atlas.hbase.model.HBaseOperationContext; -import org.apache.atlas.hbase.model.HBaseDataTypes; -import org.apache.atlas.hook.AtlasHook; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.model.notification.HookNotification.EntityCreateRequestV2; -import org.apache.atlas.model.notification.HookNotification.EntityDeleteRequestV2; -import org.apache.atlas.model.notification.HookNotification.EntityUpdateRequestV2; -import org.apache.atlas.type.AtlasTypeUtil; -import org.apache.commons.collections.CollectionUtils; -import org.apache.hadoop.hbase.TableName; -import org.apache.hadoop.hbase.NamespaceDescriptor; -import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; -import org.apache.hadoop.hbase.client.TableDescriptor; -import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment; -import org.apache.hadoop.hbase.coprocessor.ObserverContext; -import org.apache.hadoop.hbase.security.User; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.apache.atlas.repository.Constants.HBASE_SOURCE; - -// This will register Hbase entities into Atlas -public class HBaseAtlasHook extends AtlasHook { - private static final Logger LOG = LoggerFactory.getLogger(HBaseAtlasHook.class); - - - public static final String ATTR_DESCRIPTION = "description"; - public static final String ATTR_ATLAS_ENDPOINT = "atlas.rest.address"; - public static final String ATTR_PARAMETERS = "parameters"; - public static final String ATTR_URI = "uri"; - public static final String ATTR_NAMESPACE = "namespace"; - public static final String ATTR_TABLE = "table"; - public static final String ATTR_COLUMNFAMILIES = "column_families"; - public static final String ATTR_CREATE_TIME = "createTime"; - public static final String ATTR_MODIFIED_TIME = "modifiedTime"; - public static final String ATTR_OWNER = "owner"; - public static final String ATTR_NAME = "name"; - - // column addition metadata - public static final String ATTR_TABLE_MAX_FILESIZE = "maxFileSize"; - public static final String ATTR_TABLE_ISREADONLY = "isReadOnly"; - public static final String ATTR_TABLE_ISCOMPACTION_ENABLED = "isCompactionEnabled"; - public static final String ATTR_TABLE_ISNORMALIZATION_ENABLED = "isNormalizationEnabled"; - public static final String ATTR_TABLE_REPLICATION_PER_REGION = "replicasPerRegion"; - public static final String ATTR_TABLE_DURABLILITY = "durability"; - public static final String ATTR_TABLE_NORMALIZATION_ENABLED = "isNormalizationEnabled"; - - // column family additional metadata - public static final String ATTR_CF_BLOOMFILTER_TYPE = "bloomFilterType"; - public static final String ATTR_CF_COMPRESSION_TYPE = "compressionType"; - public static final String ATTR_CF_COMPACTION_COMPRESSION_TYPE = "compactionCompressionType"; - public static final String ATTR_CF_ENCRYPTION_TYPE = "encryptionType"; - public static final String ATTR_CF_INMEMORY_COMPACTION_POLICY = "inMemoryCompactionPolicy"; - public static final String ATTR_CF_KEEP_DELETE_CELLS = "keepDeletedCells"; - public static final String ATTR_CF_MAX_VERSIONS = "maxVersions"; - public static final String ATTR_CF_MIN_VERSIONS = "minVersions"; - public static final String ATTR_CF_DATA_BLOCK_ENCODING = "dataBlockEncoding"; - public static final String ATTR_CF_STORAGE_POLICY = "StoragePolicy"; - public static final String ATTR_CF_TTL = "ttl"; - public static final String ATTR_CF_BLOCK_CACHE_ENABLED = "blockCacheEnabled"; - public static final String ATTR_CF_CACHED_BLOOM_ON_WRITE = "cacheBloomsOnWrite"; - public static final String ATTR_CF_CACHED_DATA_ON_WRITE = "cacheDataOnWrite"; - public static final String ATTR_CF_CACHED_INDEXES_ON_WRITE = "cacheIndexesOnWrite"; - public static final String ATTR_CF_EVICT_BLOCK_ONCLOSE = "evictBlocksOnClose"; - public static final String ATTR_CF_PREFETCH_BLOCK_ONOPEN = "prefetchBlocksOnOpen"; - public static final String ATTR_CF_NEW_VERSION_BEHAVIOR = "newVersionBehavior"; - public static final String ATTR_CF_MOB_ENABLED = "isMobEnabled"; - public static final String ATTR_CF_MOB_COMPATCTPARTITION_POLICY = "mobCompactPartitionPolicy"; - - public static final String HBASE_NAMESPACE_QUALIFIED_NAME = "%s@%s"; - public static final String HBASE_TABLE_QUALIFIED_NAME_FORMAT = "%s:%s@%s"; - public static final String HBASE_COLUMN_FAMILY_QUALIFIED_NAME_FORMAT = "%s:%s.%s@%s"; - - private static final String REFERENCEABLE_ATTRIBUTE_NAME = "qualifiedName"; - - public static final String RELATIONSHIP_HBASE_TABLE_COLUMN_FAMILIES = "hbase_table_column_families"; - public static final String RELATIONSHIP_HBASE_TABLE_NAMESPACE = "hbase_table_namespace"; - - private static volatile HBaseAtlasHook me; - - public enum OPERATION { - CREATE_NAMESPACE("create_namespace"), - ALTER_NAMESPACE("alter_namespace"), - DELETE_NAMESPACE("delete_namespace"), - CREATE_TABLE("create_table"), - ALTER_TABLE("alter_table"), - DELETE_TABLE("delete_table"), - CREATE_COLUMN_FAMILY("create_column_Family"), - ALTER_COLUMN_FAMILY("alter_column_Family"), - DELETE_COLUMN_FAMILY("delete_column_Family"); - - private final String name; - - OPERATION(String s) { - name = s; - } - - public String getName() { - return name; - } - } - - public static HBaseAtlasHook getInstance() { - HBaseAtlasHook ret = me; - - if (ret == null) { - try { - synchronized (HBaseAtlasHook.class) { - ret = me; - - if (ret == null) { - me = ret = new HBaseAtlasHook(); - } - } - } catch (Exception e) { - LOG.error("Caught exception instantiating the Atlas HBase hook.", e); - } - } - - return ret; - } - - public HBaseAtlasHook() { - } - - public void createAtlasInstances(HBaseOperationContext hbaseOperationContext) { - OPERATION operation = hbaseOperationContext.getOperation(); - - LOG.info("HBaseAtlasHook(operation={})", operation); - - switch (operation) { - case CREATE_NAMESPACE: - case ALTER_NAMESPACE: - createOrUpdateNamespaceInstance(hbaseOperationContext); - break; - case DELETE_NAMESPACE: - deleteNameSpaceInstance(hbaseOperationContext); - break; - case CREATE_TABLE: - case ALTER_TABLE: - createOrUpdateTableInstance(hbaseOperationContext); - break; - case DELETE_TABLE: - deleteTableInstance(hbaseOperationContext); - break; - case CREATE_COLUMN_FAMILY: - case ALTER_COLUMN_FAMILY: - createOrUpdateColumnFamilyInstance(hbaseOperationContext); - break; - case DELETE_COLUMN_FAMILY: - deleteColumnFamilyInstance(hbaseOperationContext); - break; - } - } - - private void createOrUpdateNamespaceInstance(HBaseOperationContext hbaseOperationContext) { - AtlasEntity nameSpace = buildNameSpace(hbaseOperationContext); - - switch (hbaseOperationContext.getOperation()) { - case CREATE_NAMESPACE: - LOG.info("Create NameSpace {}", nameSpace.getAttribute(REFERENCEABLE_ATTRIBUTE_NAME)); - - hbaseOperationContext.addMessage(new EntityCreateRequestV2(hbaseOperationContext.getUser(), new AtlasEntitiesWithExtInfo(nameSpace))); - break; - - case ALTER_NAMESPACE: - LOG.info("Modify NameSpace {}", nameSpace.getAttribute(REFERENCEABLE_ATTRIBUTE_NAME)); - - hbaseOperationContext.addMessage(new EntityUpdateRequestV2(hbaseOperationContext.getUser(), new AtlasEntitiesWithExtInfo(nameSpace))); - break; - } - } - - private void deleteNameSpaceInstance(HBaseOperationContext hbaseOperationContext) { - String nameSpaceQName = getNameSpaceQualifiedName(getMetadataNamespace(), hbaseOperationContext.getNameSpace()); - AtlasObjectId nameSpaceId = new AtlasObjectId(HBaseDataTypes.HBASE_NAMESPACE.getName(), REFERENCEABLE_ATTRIBUTE_NAME, nameSpaceQName); - - LOG.info("Delete NameSpace {}", nameSpaceQName); - - hbaseOperationContext.addMessage(new EntityDeleteRequestV2(hbaseOperationContext.getUser(), Collections.singletonList(nameSpaceId))); - } - - private void createOrUpdateTableInstance(HBaseOperationContext hbaseOperationContext) { - AtlasEntity nameSpace = buildNameSpace(hbaseOperationContext); - AtlasEntity table = buildTable(hbaseOperationContext, nameSpace); - List columnFamilies = buildColumnFamilies(hbaseOperationContext, nameSpace, table); - - table.setRelationshipAttribute(ATTR_COLUMNFAMILIES, AtlasTypeUtil.getAtlasRelatedObjectIds(columnFamilies, RELATIONSHIP_HBASE_TABLE_COLUMN_FAMILIES)); - - AtlasEntitiesWithExtInfo entities = new AtlasEntitiesWithExtInfo(table); - - entities.addReferredEntity(nameSpace); - - if (CollectionUtils.isNotEmpty(columnFamilies)) { - for (AtlasEntity columnFamily : columnFamilies) { - entities.addReferredEntity(columnFamily); - } - } - - switch (hbaseOperationContext.getOperation()) { - case CREATE_TABLE: - LOG.info("Create Table {}", table.getAttribute(REFERENCEABLE_ATTRIBUTE_NAME)); - - hbaseOperationContext.addMessage(new EntityCreateRequestV2(hbaseOperationContext.getUser(), entities)); - break; - - case ALTER_TABLE: - LOG.info("Modify Table {}", table.getAttribute(REFERENCEABLE_ATTRIBUTE_NAME)); - - hbaseOperationContext.addMessage(new EntityUpdateRequestV2(hbaseOperationContext.getUser(), entities)); - break; - } - } - - private void deleteTableInstance(HBaseOperationContext hbaseOperationContext) { - TableName tableName = hbaseOperationContext.getTableName(); - String nameSpaceName = tableName.getNamespaceAsString(); - - if (nameSpaceName == null) { - nameSpaceName = tableName.getNameWithNamespaceInclAsString(); - } - - String tableNameStr = tableName.getNameAsString(); - String tableQName = getTableQualifiedName(getMetadataNamespace(), nameSpaceName, tableNameStr); - AtlasObjectId tableId = new AtlasObjectId(HBaseDataTypes.HBASE_TABLE.getName(), REFERENCEABLE_ATTRIBUTE_NAME, tableQName); - - LOG.info("Delete Table {}", tableQName); - - hbaseOperationContext.addMessage(new EntityDeleteRequestV2(hbaseOperationContext.getUser(), Collections.singletonList(tableId))); - } - - private void createOrUpdateColumnFamilyInstance(HBaseOperationContext hbaseOperationContext) { - AtlasEntity nameSpace = buildNameSpace(hbaseOperationContext); - AtlasEntity table = buildTable(hbaseOperationContext, nameSpace); - AtlasEntity columnFamily = buildColumnFamily(hbaseOperationContext, hbaseOperationContext.gethColumnDescriptor(), nameSpace, table); - - AtlasEntitiesWithExtInfo entities = new AtlasEntitiesWithExtInfo(columnFamily); - - entities.addReferredEntity(nameSpace); - entities.addReferredEntity(table); - - switch (hbaseOperationContext.getOperation()) { - case CREATE_COLUMN_FAMILY: - LOG.info("Create ColumnFamily {}", columnFamily.getAttribute(REFERENCEABLE_ATTRIBUTE_NAME)); - - hbaseOperationContext.addMessage(new EntityCreateRequestV2(hbaseOperationContext.getUser(), entities)); - break; - - case ALTER_COLUMN_FAMILY: - LOG.info("Alter ColumnFamily {}", columnFamily.getAttribute(REFERENCEABLE_ATTRIBUTE_NAME)); - - hbaseOperationContext.addMessage(new EntityUpdateRequestV2(hbaseOperationContext.getUser(), entities)); - break; - } - } - - private void deleteColumnFamilyInstance(HBaseOperationContext hbaseOperationContext) { - TableName tableName = hbaseOperationContext.getTableName(); - String nameSpaceName = tableName.getNamespaceAsString(); - - if (nameSpaceName == null) { - nameSpaceName = tableName.getNameWithNamespaceInclAsString(); - } - - String tableNameStr = tableName.getNameAsString(); - String columnFamilyName = hbaseOperationContext.getColummFamily(); - String columnFamilyQName = getColumnFamilyQualifiedName(getMetadataNamespace(), nameSpaceName, tableNameStr, columnFamilyName); - AtlasObjectId columnFamilyId = new AtlasObjectId(HBaseDataTypes.HBASE_COLUMN_FAMILY.getName(), REFERENCEABLE_ATTRIBUTE_NAME, columnFamilyQName); - - LOG.info("Delete ColumnFamily {}", columnFamilyQName); - - hbaseOperationContext.addMessage(new EntityDeleteRequestV2(hbaseOperationContext.getUser(), Collections.singletonList(columnFamilyId))); - } - - - /** - * Construct the qualified name used to uniquely identify a ColumnFamily instance in Atlas. - * - * @param metadataNamespace Metadata namespace of the cluster to which the HBase component belongs - * @param nameSpace Name of the HBase database to which the Table belongs - * @param tableName Name of the HBase table - * @param columnFamily Name of the ColumnFamily - * @return Unique qualified name to identify the Table instance in Atlas. - */ - public static String getColumnFamilyQualifiedName(String metadataNamespace, String nameSpace, String tableName, String columnFamily) { - if (metadataNamespace == null || nameSpace == null || tableName == null || columnFamily == null) { - return null; - } else { - return String.format(HBASE_COLUMN_FAMILY_QUALIFIED_NAME_FORMAT, nameSpace, stripNameSpace(tableName), columnFamily, metadataNamespace); - } - } - - /** - * Construct the qualified name used to uniquely identify a Table instance in Atlas. - * - * @param metadataNamespace Metadata namespace of the cluster to which the HBase component belongs - * @param nameSpace Name of the HBase database to which the Table belongs - * @param tableName Name of the HBase table - * @return Unique qualified name to identify the Table instance in Atlas. - */ - public static String getTableQualifiedName(String metadataNamespace, String nameSpace, String tableName) { - if (metadataNamespace == null || nameSpace == null || tableName == null) { - return null; - } else { - return String.format(HBASE_TABLE_QUALIFIED_NAME_FORMAT, nameSpace, stripNameSpace(tableName), metadataNamespace); - } - } - - /** - * Construct the qualified name used to uniquely identify a HBase NameSpace instance in Atlas. - * - * @param metadataNamespace Metadata namespace of the cluster to which the HBase component belongs - * @param nameSpace - * @return Unique qualified name to identify the HBase NameSpace instance in Atlas. - */ - public static String getNameSpaceQualifiedName(String metadataNamespace, String nameSpace) { - if (metadataNamespace == null || nameSpace == null) { - return null; - } else { - return String.format(HBASE_NAMESPACE_QUALIFIED_NAME, nameSpace, metadataNamespace); - } - } - - private static String stripNameSpace(String tableName) { - return tableName.substring(tableName.indexOf(":") + 1); - } - - private AtlasEntity buildNameSpace(HBaseOperationContext hbaseOperationContext) { - AtlasEntity nameSpace = new AtlasEntity(HBaseDataTypes.HBASE_NAMESPACE.getName()); - NamespaceDescriptor nameSpaceDesc = hbaseOperationContext.getNamespaceDescriptor(); - String nameSpaceName = nameSpaceDesc == null ? null : hbaseOperationContext.getNamespaceDescriptor().getName(); - - if (nameSpaceName == null) { - nameSpaceName = hbaseOperationContext.getNameSpace(); - } - - Date now = new Date(System.currentTimeMillis()); - - nameSpace.setAttribute(ATTR_NAME, nameSpaceName); - nameSpace.setAttribute(REFERENCEABLE_ATTRIBUTE_NAME, getNameSpaceQualifiedName(getMetadataNamespace(), nameSpaceName)); - nameSpace.setAttribute(AtlasConstants.CLUSTER_NAME_ATTRIBUTE, getMetadataNamespace()); - nameSpace.setAttribute(ATTR_DESCRIPTION, nameSpaceName); - nameSpace.setAttribute(ATTR_PARAMETERS, hbaseOperationContext.getHbaseConf()); - nameSpace.setAttribute(ATTR_OWNER, hbaseOperationContext.getOwner()); - nameSpace.setAttribute(ATTR_MODIFIED_TIME, now); - - if (OPERATION.CREATE_NAMESPACE.equals(hbaseOperationContext.getOperation())) { - nameSpace.setAttribute(ATTR_CREATE_TIME, now); - } - - return nameSpace; - } - - private AtlasEntity buildTable(HBaseOperationContext hbaseOperationContext, AtlasEntity nameSpace) { - AtlasEntity table = new AtlasEntity(HBaseDataTypes.HBASE_TABLE.getName()); - String tableName = getTableName(hbaseOperationContext); - String nameSpaceName = (String) nameSpace.getAttribute(ATTR_NAME); - String tableQName = getTableQualifiedName(getMetadataNamespace(), nameSpaceName, tableName); - OPERATION operation = hbaseOperationContext.getOperation(); - Date now = new Date(System.currentTimeMillis()); - - table.setAttribute(REFERENCEABLE_ATTRIBUTE_NAME, tableQName); - table.setAttribute(ATTR_NAME, tableName); - table.setAttribute(ATTR_URI, tableName); - table.setAttribute(ATTR_OWNER, hbaseOperationContext.getOwner()); - table.setAttribute(ATTR_DESCRIPTION, tableName); - table.setAttribute(ATTR_PARAMETERS, hbaseOperationContext.getHbaseConf()); - table.setRelationshipAttribute(ATTR_NAMESPACE, AtlasTypeUtil.getAtlasRelatedObjectId(nameSpace, RELATIONSHIP_HBASE_TABLE_NAMESPACE)); - - TableDescriptor tableDescriptor = hbaseOperationContext.gethTableDescriptor(); - if (tableDescriptor != null) { - table.setAttribute(ATTR_TABLE_MAX_FILESIZE, tableDescriptor.getMaxFileSize()); - table.setAttribute(ATTR_TABLE_REPLICATION_PER_REGION, tableDescriptor.getRegionReplication()); - table.setAttribute(ATTR_TABLE_ISREADONLY, tableDescriptor.isReadOnly()); - table.setAttribute(ATTR_TABLE_ISNORMALIZATION_ENABLED, tableDescriptor.isNormalizationEnabled()); - table.setAttribute(ATTR_TABLE_ISCOMPACTION_ENABLED, tableDescriptor.isCompactionEnabled()); - table.setAttribute(ATTR_TABLE_DURABLILITY, (tableDescriptor.getDurability() != null ? tableDescriptor.getDurability().name() : null)); - table.setAttribute(ATTR_TABLE_NORMALIZATION_ENABLED, tableDescriptor.isNormalizationEnabled()); - } - - switch (operation) { - case CREATE_TABLE: - table.setAttribute(ATTR_CREATE_TIME, now); - table.setAttribute(ATTR_MODIFIED_TIME, now); - break; - case CREATE_COLUMN_FAMILY: - table.setAttribute(ATTR_MODIFIED_TIME, now); - break; - case ALTER_TABLE: - case ALTER_COLUMN_FAMILY: - table.setAttribute(ATTR_MODIFIED_TIME, now); - break; - default: - break; - } - - return table; - } - - private List buildColumnFamilies(HBaseOperationContext hbaseOperationContext, AtlasEntity nameSpace, AtlasEntity table) { - List columnFamilies = new ArrayList<>(); - ColumnFamilyDescriptor[] columnFamilyDescriptors = hbaseOperationContext.gethColumnDescriptors(); - - if (columnFamilyDescriptors != null) { - for (ColumnFamilyDescriptor columnFamilyDescriptor : columnFamilyDescriptors) { - AtlasEntity columnFamily = buildColumnFamily(hbaseOperationContext, columnFamilyDescriptor, nameSpace, table); - - columnFamilies.add(columnFamily); - } - } - - return columnFamilies; - } - - private AtlasEntity buildColumnFamily(HBaseOperationContext hbaseOperationContext, ColumnFamilyDescriptor columnFamilyDescriptor, AtlasEntity nameSpace, AtlasEntity table) { - AtlasEntity columnFamily = new AtlasEntity(HBaseDataTypes.HBASE_COLUMN_FAMILY.getName()); - String columnFamilyName = columnFamilyDescriptor.getNameAsString(); - String tableName = (String) table.getAttribute(ATTR_NAME); - String nameSpaceName = (String) nameSpace.getAttribute(ATTR_NAME); - String columnFamilyQName = getColumnFamilyQualifiedName(getMetadataNamespace(), nameSpaceName, tableName, columnFamilyName); - Date now = new Date(System.currentTimeMillis()); - - columnFamily.setAttribute(ATTR_NAME, columnFamilyName); - columnFamily.setAttribute(ATTR_DESCRIPTION, columnFamilyName); - columnFamily.setAttribute(REFERENCEABLE_ATTRIBUTE_NAME, columnFamilyQName); - columnFamily.setAttribute(ATTR_OWNER, hbaseOperationContext.getOwner()); - columnFamily.setRelationshipAttribute(ATTR_TABLE, AtlasTypeUtil.getAtlasRelatedObjectId(table, RELATIONSHIP_HBASE_TABLE_COLUMN_FAMILIES)); - - if (columnFamilyDescriptor!= null) { - columnFamily.setAttribute(ATTR_CF_BLOCK_CACHE_ENABLED, columnFamilyDescriptor.isBlockCacheEnabled()); - columnFamily.setAttribute(ATTR_CF_BLOOMFILTER_TYPE, (columnFamilyDescriptor.getBloomFilterType() != null ? columnFamilyDescriptor.getBloomFilterType().name():null)); - columnFamily.setAttribute(ATTR_CF_CACHED_BLOOM_ON_WRITE, columnFamilyDescriptor.isCacheBloomsOnWrite()); - columnFamily.setAttribute(ATTR_CF_CACHED_DATA_ON_WRITE, columnFamilyDescriptor.isCacheDataOnWrite()); - columnFamily.setAttribute(ATTR_CF_CACHED_INDEXES_ON_WRITE, columnFamilyDescriptor.isCacheIndexesOnWrite()); - columnFamily.setAttribute(ATTR_CF_COMPACTION_COMPRESSION_TYPE, (columnFamilyDescriptor.getCompactionCompressionType() != null ? columnFamilyDescriptor.getCompactionCompressionType().name():null)); - columnFamily.setAttribute(ATTR_CF_COMPRESSION_TYPE, (columnFamilyDescriptor.getCompressionType() != null ? columnFamilyDescriptor.getCompressionType().name():null)); - columnFamily.setAttribute(ATTR_CF_DATA_BLOCK_ENCODING, (columnFamilyDescriptor.getDataBlockEncoding() != null ? columnFamilyDescriptor.getDataBlockEncoding().name():null)); - columnFamily.setAttribute(ATTR_CF_ENCRYPTION_TYPE, columnFamilyDescriptor.getEncryptionType()); - columnFamily.setAttribute(ATTR_CF_EVICT_BLOCK_ONCLOSE, columnFamilyDescriptor.isEvictBlocksOnClose()); - columnFamily.setAttribute(ATTR_CF_INMEMORY_COMPACTION_POLICY, (columnFamilyDescriptor.getInMemoryCompaction() != null ? columnFamilyDescriptor.getInMemoryCompaction().name():null)); - columnFamily.setAttribute(ATTR_CF_KEEP_DELETE_CELLS, ( columnFamilyDescriptor.getKeepDeletedCells() != null ? columnFamilyDescriptor.getKeepDeletedCells().name():null)); - columnFamily.setAttribute(ATTR_CF_MAX_VERSIONS, columnFamilyDescriptor.getMaxVersions()); - columnFamily.setAttribute(ATTR_CF_MIN_VERSIONS, columnFamilyDescriptor.getMinVersions()); - columnFamily.setAttribute(ATTR_CF_NEW_VERSION_BEHAVIOR, columnFamilyDescriptor.isNewVersionBehavior()); - columnFamily.setAttribute(ATTR_CF_MOB_ENABLED, columnFamilyDescriptor.isMobEnabled()); - columnFamily.setAttribute(ATTR_CF_MOB_COMPATCTPARTITION_POLICY, ( columnFamilyDescriptor.getMobCompactPartitionPolicy() != null ? columnFamilyDescriptor.getMobCompactPartitionPolicy().name():null)); - columnFamily.setAttribute(ATTR_CF_PREFETCH_BLOCK_ONOPEN, columnFamilyDescriptor.isPrefetchBlocksOnOpen()); - columnFamily.setAttribute(ATTR_CF_STORAGE_POLICY, columnFamilyDescriptor.getStoragePolicy()); - columnFamily.setAttribute(ATTR_CF_TTL, columnFamilyDescriptor.getTimeToLive()); - } - - switch (hbaseOperationContext.getOperation()) { - case CREATE_COLUMN_FAMILY: - case CREATE_TABLE: - columnFamily.setAttribute(ATTR_CREATE_TIME, now); - columnFamily.setAttribute(ATTR_MODIFIED_TIME, now); - break; - - case ALTER_COLUMN_FAMILY: - columnFamily.setAttribute(ATTR_MODIFIED_TIME, now); - break; - - default: - break; - } - - return columnFamily; - } - - public String getMessageSource() { - return HBASE_SOURCE; - } - - private String getTableName(HBaseOperationContext hbaseOperationContext) { - final String ret; - - TableName tableName = hbaseOperationContext.getTableName(); - - if (tableName != null) { - ret = tableName.getNameAsString(); - } else { - TableDescriptor tableDescriptor = hbaseOperationContext.gethTableDescriptor(); - - ret = (tableDescriptor != null) ? tableDescriptor.getTableName().getNameAsString() : null; - } - - return ret; - } - - public void sendHBaseNameSpaceOperation(final NamespaceDescriptor namespaceDescriptor, final String nameSpace, final OPERATION operation, ObserverContext ctx) { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasHook.sendHBaseNameSpaceOperation()"); - } - - try { - final UserGroupInformation ugi = getUGI(ctx); - final User user = getActiveUser(ctx); - final String userName = (user != null) ? user.getShortName() : null; - HBaseOperationContext hbaseOperationContext = handleHBaseNameSpaceOperation(namespaceDescriptor, nameSpace, operation, ugi, userName); - - sendNotification(hbaseOperationContext); - } catch (Throwable t) { - LOG.error("HBaseAtlasHook.sendHBaseNameSpaceOperation(): failed to send notification", t); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasHook.sendHBaseNameSpaceOperation()"); - } - } - - public void sendHBaseTableOperation(TableDescriptor tableDescriptor, final TableName tableName, final OPERATION operation, ObserverContext ctx) { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasHook.sendHBaseTableOperation()"); - } - - try { - final UserGroupInformation ugi = getUGI(ctx); - final User user = getActiveUser(ctx); - final String userName = (user != null) ? user.getShortName() : null; - HBaseOperationContext hbaseOperationContext = handleHBaseTableOperation(tableDescriptor, tableName, operation, ugi, userName); - - sendNotification(hbaseOperationContext); - } catch (Throwable t) { - LOG.error("<== HBaseAtlasHook.sendHBaseTableOperation(): failed to send notification", t); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasHook.sendHBaseTableOperation()"); - } - } - - private void sendNotification(HBaseOperationContext hbaseOperationContext) { - UserGroupInformation ugi = hbaseOperationContext.getUgi(); - - if (ugi != null && ugi.getRealUser() != null) { - ugi = ugi.getRealUser(); - } - - notifyEntities(hbaseOperationContext.getMessages(), ugi); - } - - private HBaseOperationContext handleHBaseNameSpaceOperation(NamespaceDescriptor namespaceDescriptor, String nameSpace, OPERATION operation, UserGroupInformation ugi, String userName) { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasHook.handleHBaseNameSpaceOperation()"); - } - - HBaseOperationContext hbaseOperationContext = new HBaseOperationContext(namespaceDescriptor, nameSpace, operation, ugi, userName, userName); - createAtlasInstances(hbaseOperationContext); - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasHook.handleHBaseNameSpaceOperation(): {}", hbaseOperationContext); - } - - return hbaseOperationContext; - } - - private HBaseOperationContext handleHBaseTableOperation(TableDescriptor tableDescriptor, TableName tableName, OPERATION operation, UserGroupInformation ugi, String userName) { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasHook.handleHBaseTableOperation()"); - } - - Map hbaseConf = null; - String owner = null; - String tableNameSpace = null; - TableName hbaseTableName = null; - ColumnFamilyDescriptor[] columnFamilyDescriptors = null; - - if (tableDescriptor != null) { - owner = tableDescriptor.getOwnerString(); - hbaseConf = null; - hbaseTableName = tableDescriptor.getTableName(); - if (hbaseTableName != null) { - tableNameSpace = hbaseTableName.getNamespaceAsString(); - if (tableNameSpace == null) { - tableNameSpace = hbaseTableName.getNameWithNamespaceInclAsString(); - } - } - } - - if (owner == null) { - owner = userName; - } - - if (tableDescriptor != null) { - columnFamilyDescriptors = tableDescriptor.getColumnFamilies(); - } - - HBaseOperationContext hbaseOperationContext = new HBaseOperationContext(tableNameSpace, tableDescriptor, tableName, columnFamilyDescriptors, operation, ugi, userName, owner, hbaseConf); - createAtlasInstances(hbaseOperationContext); - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasHook.handleHBaseTableOperation(): {}", hbaseOperationContext); - } - return hbaseOperationContext; - } - - private HBaseOperationContext handleHBaseColumnFamilyOperation(ColumnFamilyDescriptor columnFamilyDescriptor, TableName tableName, String columnFamily, OPERATION operation, UserGroupInformation ugi, String userName) { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasHook.handleHBaseColumnFamilyOperation()"); - } - - String owner = userName; - Map hbaseConf = new HashMap<>(); - - String tableNameSpace = tableName.getNamespaceAsString(); - if (tableNameSpace == null) { - tableNameSpace = tableName.getNameWithNamespaceInclAsString(); - } - - if (columnFamilyDescriptor != null) { - hbaseConf = columnFamilyDescriptor.getConfiguration(); - } - - HBaseOperationContext hbaseOperationContext = new HBaseOperationContext(tableNameSpace, tableName, columnFamilyDescriptor, columnFamily, operation, ugi, userName, owner, hbaseConf); - createAtlasInstances(hbaseOperationContext); - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasHook.handleHBaseColumnFamilyOperation(): {}", hbaseOperationContext); - } - return hbaseOperationContext; - } - - private UserGroupInformation getUGI(ObserverContext ctx) { - UserGroupInformation ugi = null; - User user = null; - try { - user = getActiveUser(ctx); - ugi = UserGroupInformation.getLoginUser(); - } catch (Exception e) { - // not setting the UGI here - } - - if (ugi == null) { - if (user != null) { - ugi = user.getUGI(); - } - } - - LOG.info("HBaseAtlasHook: UGI: {}", ugi); - return ugi; - } - - private User getActiveUser(ObserverContext ctx) throws IOException { - return (User)ctx.getCaller().orElse(User.getCurrent()); - } -} diff --git a/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/bridge/HBaseBridge.java b/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/bridge/HBaseBridge.java deleted file mode 100644 index f5a1d2ad51c..00000000000 --- a/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/bridge/HBaseBridge.java +++ /dev/null @@ -1,720 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hbase.bridge; - -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.hbase.model.HBaseDataTypes; -import org.apache.atlas.hook.AtlasHookException; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; -import org.apache.atlas.model.instance.AtlasEntityHeader; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.model.instance.EntityMutationResponse; -import org.apache.atlas.type.AtlasTypeUtil; -import org.apache.atlas.utils.AtlasConfigurationUtil; -import org.apache.atlas.utils.AuthenticationUtil; -import org.apache.commons.cli.BasicParser; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.CommandLineParser; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.hadoop.hbase.HBaseConfiguration; -import org.apache.hadoop.hbase.NamespaceDescriptor; -import org.apache.hadoop.hbase.client.Admin; -import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; -import org.apache.hadoop.hbase.client.Connection; -import org.apache.hadoop.hbase.client.ConnectionFactory; -import org.apache.hadoop.hbase.client.HBaseAdmin; -import org.apache.hadoop.hbase.client.TableDescriptor; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class HBaseBridge { - private static final Logger LOG = LoggerFactory.getLogger(HBaseBridge.class); - - private static final int EXIT_CODE_SUCCESS = 0; - private static final int EXIT_CODE_FAILED = 1; - private static final String ATLAS_ENDPOINT = "atlas.rest.address"; - private static final String DEFAULT_ATLAS_URL = "http://localhost:21000/"; - private static final String CLUSTER_NAME_KEY = "atlas.cluster.name"; - private static final String DEFAULT_CLUSTER_NAME = "primary"; - private static final String HBASE_METADATA_NAMESPACE = "atlas.metadata.namespace"; - private static final String QUALIFIED_NAME = "qualifiedName"; - private static final String NAME = "name"; - private static final String URI = "uri"; - private static final String OWNER = "owner"; - private static final String DESCRIPTION_ATTR = "description"; - private static final String CLUSTERNAME = "clusterName"; - private static final String NAMESPACE = "namespace"; - private static final String TABLE = "table"; - private static final String COLUMN_FAMILIES = "column_families"; - - // table metadata - private static final String ATTR_TABLE_MAX_FILESIZE = "maxFileSize"; - private static final String ATTR_TABLE_ISREADONLY = "isReadOnly"; - private static final String ATTR_TABLE_ISCOMPACTION_ENABLED = "isCompactionEnabled"; - private static final String ATTR_TABLE_REPLICATION_PER_REGION = "replicasPerRegion"; - private static final String ATTR_TABLE_DURABLILITY = "durability"; - private static final String ATTR_TABLE_NORMALIZATION_ENABLED = "isNormalizationEnabled"; - - // column family metadata - private static final String ATTR_CF_BLOOMFILTER_TYPE = "bloomFilterType"; - private static final String ATTR_CF_COMPRESSION_TYPE = "compressionType"; - private static final String ATTR_CF_COMPACTION_COMPRESSION_TYPE = "compactionCompressionType"; - private static final String ATTR_CF_ENCRYPTION_TYPE = "encryptionType"; - private static final String ATTR_CF_KEEP_DELETE_CELLS = "keepDeletedCells"; - private static final String ATTR_CF_MAX_VERSIONS = "maxVersions"; - private static final String ATTR_CF_MIN_VERSIONS = "minVersions"; - private static final String ATTR_CF_DATA_BLOCK_ENCODING = "dataBlockEncoding"; - private static final String ATTR_CF_TTL = "ttl"; - private static final String ATTR_CF_BLOCK_CACHE_ENABLED = "blockCacheEnabled"; - private static final String ATTR_CF_CACHED_BLOOM_ON_WRITE = "cacheBloomsOnWrite"; - private static final String ATTR_CF_CACHED_DATA_ON_WRITE = "cacheDataOnWrite"; - private static final String ATTR_CF_CACHED_INDEXES_ON_WRITE = "cacheIndexesOnWrite"; - private static final String ATTR_CF_EVICT_BLOCK_ONCLOSE = "evictBlocksOnClose"; - private static final String ATTR_CF_PREFETCH_BLOCK_ONOPEN = "prefetchBlocksOnOpen"; - private static final String ATTRIBUTE_QUALIFIED_NAME = "qualifiedName"; - private static final String ATTR_CF_INMEMORY_COMPACTION_POLICY = "inMemoryCompactionPolicy"; - private static final String ATTR_CF_MOB_COMPATCTPARTITION_POLICY = "mobCompactPartitionPolicy"; - private static final String ATTR_CF_MOB_ENABLED = "isMobEnabled"; - private static final String ATTR_CF_NEW_VERSION_BEHAVIOR = "newVersionBehavior"; - - private static final String HBASE_NAMESPACE_QUALIFIED_NAME = "%s@%s"; - private static final String HBASE_TABLE_QUALIFIED_NAME_FORMAT = "%s:%s@%s"; - private static final String HBASE_COLUMN_FAMILY_QUALIFIED_NAME_FORMAT = "%s:%s.%s@%s"; - - private final String metadataNamespace; - private final AtlasClientV2 atlasClientV2; - private final Admin hbaseAdmin; - - - public static void main(String[] args) { - int exitCode = EXIT_CODE_FAILED; - AtlasClientV2 atlasClientV2 =null; - - try { - Options options = new Options(); - options.addOption("n","namespace", true, "namespace"); - options.addOption("t", "table", true, "tablename"); - options.addOption("f", "filename", true, "filename"); - - CommandLineParser parser = new BasicParser(); - CommandLine cmd = parser.parse(options, args); - String namespaceToImport = cmd.getOptionValue("n"); - String tableToImport = cmd.getOptionValue("t"); - String fileToImport = cmd.getOptionValue("f"); - Configuration atlasConf = ApplicationProperties.get(); - String[] urls = atlasConf.getStringArray(ATLAS_ENDPOINT); - - if (urls == null || urls.length == 0) { - urls = new String[] { DEFAULT_ATLAS_URL }; - } - - - if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { - String[] basicAuthUsernamePassword = AuthenticationUtil.getBasicAuthenticationInput(); - - atlasClientV2 = new AtlasClientV2(urls, basicAuthUsernamePassword); - } else { - UserGroupInformation ugi = UserGroupInformation.getCurrentUser(); - - atlasClientV2 = new AtlasClientV2(ugi, ugi.getShortUserName(), urls); - } - - HBaseBridge importer = new HBaseBridge(atlasConf, atlasClientV2); - - if (StringUtils.isNotEmpty(fileToImport)) { - File f = new File(fileToImport); - - if (f.exists() && f.canRead()) { - BufferedReader br = new BufferedReader(new FileReader(f)); - String line = null; - - while((line = br.readLine()) != null) { - String val[] = line.split(":"); - - if (ArrayUtils.isNotEmpty(val)) { - namespaceToImport = val[0]; - - if (val.length > 1) { - tableToImport = val[1]; - } else { - tableToImport = ""; - } - - importer.importHBaseEntities(namespaceToImport, tableToImport); - } - } - - exitCode = EXIT_CODE_SUCCESS; - } else { - LOG.error("Failed to read the file"); - } - } else { - importer.importHBaseEntities(namespaceToImport, tableToImport); - - exitCode = EXIT_CODE_SUCCESS; - } - } catch(ParseException e) { - LOG.error("Failed to parse arguments. Error: ", e.getMessage()); - printUsage(); - } catch(Exception e) { - System.out.println("ImportHBaseEntities failed. Please check the log file for the detailed error message"); - - LOG.error("ImportHBaseEntities failed", e); - }finally { - if(atlasClientV2!=null) { - atlasClientV2.close(); - } - } - - System.exit(exitCode); - } - - public HBaseBridge(Configuration atlasConf, AtlasClientV2 atlasClientV2) throws Exception { - this.atlasClientV2 = atlasClientV2; - this.metadataNamespace = getMetadataNamespace(atlasConf); - - org.apache.hadoop.conf.Configuration conf = HBaseConfiguration.create(); - - LOG.info("checking HBase availability.."); - - HBaseAdmin.available(conf); - - LOG.info("HBase is available"); - - Connection conn = ConnectionFactory.createConnection(conf); - - hbaseAdmin = conn.getAdmin(); - } - - private String getMetadataNamespace(Configuration config) { - return AtlasConfigurationUtil.getRecentString(config, HBASE_METADATA_NAMESPACE, getClusterName(config)); - } - - private String getClusterName(Configuration config) { - return config.getString(CLUSTER_NAME_KEY, DEFAULT_CLUSTER_NAME); - } - - private boolean importHBaseEntities(String namespaceToImport, String tableToImport) throws Exception { - boolean ret = false; - - if (StringUtils.isEmpty(namespaceToImport) && StringUtils.isEmpty(tableToImport)) { - // when both NameSpace and Table options are not present - importNameSpaceAndTable(); - ret = true; - } else if (StringUtils.isNotEmpty(namespaceToImport)) { - // When Namespace option is present or both namespace and table options are present - importNameSpaceWithTable(namespaceToImport, tableToImport); - ret = true; - } else if (StringUtils.isNotEmpty(tableToImport)) { - importTable(tableToImport); - ret = true; - } - - return ret; - } - - public void importNameSpace(final String nameSpace) throws Exception { - List matchingNameSpaceDescriptors = getMatchingNameSpaces(nameSpace); - - if (CollectionUtils.isNotEmpty(matchingNameSpaceDescriptors)) { - for (NamespaceDescriptor namespaceDescriptor : matchingNameSpaceDescriptors) { - createOrUpdateNameSpace(namespaceDescriptor); - } - } else { - throw new AtlasHookException("No NameSpace found for the given criteria. NameSpace = " + nameSpace); - } - } - - public void importTable(final String tableName) throws Exception { - String tableNameStr = null; - TableDescriptor[] htds = hbaseAdmin.listTables(Pattern.compile(tableName)); - - if (ArrayUtils.isNotEmpty(htds)) { - for (TableDescriptor htd : htds) { - String tblNameWithNameSpace = htd.getTableName().getNameWithNamespaceInclAsString(); - String tblNameWithOutNameSpace = htd.getTableName().getNameAsString(); - - if (tableName.equals(tblNameWithNameSpace)) { - tableNameStr = tblNameWithNameSpace; - } else if (tableName.equals(tblNameWithOutNameSpace)) { - tableNameStr = tblNameWithOutNameSpace; - } else { - // when wild cards are used in table name - if (tblNameWithNameSpace != null) { - tableNameStr = tblNameWithNameSpace; - } else if (tblNameWithOutNameSpace != null) { - tableNameStr = tblNameWithOutNameSpace; - } - } - - byte[] nsByte = htd.getTableName().getNamespace(); - String nsName = new String(nsByte); - NamespaceDescriptor nsDescriptor = hbaseAdmin.getNamespaceDescriptor(nsName); - AtlasEntityWithExtInfo entity = createOrUpdateNameSpace(nsDescriptor); - ColumnFamilyDescriptor[] hcdts = htd.getColumnFamilies(); - - createOrUpdateTable(nsName, tableNameStr, entity.getEntity(), htd, hcdts); - } - } else { - throw new AtlasHookException("No Table found for the given criteria. Table = " + tableName); - } - } - - private void importNameSpaceAndTable() throws Exception { - NamespaceDescriptor[] namespaceDescriptors = hbaseAdmin.listNamespaceDescriptors(); - - if (ArrayUtils.isNotEmpty(namespaceDescriptors)) { - for (NamespaceDescriptor namespaceDescriptor : namespaceDescriptors) { - String namespace = namespaceDescriptor.getName(); - - importNameSpace(namespace); - } - } - - TableDescriptor[] htds = hbaseAdmin.listTables(); - - if (ArrayUtils.isNotEmpty(htds)) { - for (TableDescriptor htd : htds) { - String tableName = htd.getTableName().getNameAsString(); - - importTable(tableName); - } - } - } - - private void importNameSpaceWithTable(String namespaceToImport, String tableToImport) throws Exception { - importNameSpace(namespaceToImport); - - List hTableDescriptors = new ArrayList<>(); - - if (StringUtils.isEmpty(tableToImport)) { - List matchingNameSpaceDescriptors = getMatchingNameSpaces(namespaceToImport); - - if (CollectionUtils.isNotEmpty(matchingNameSpaceDescriptors)) { - hTableDescriptors = getTableDescriptors(matchingNameSpaceDescriptors); - } - } else { - tableToImport = namespaceToImport +":" + tableToImport; - - TableDescriptor[] htds = hbaseAdmin.listTables(Pattern.compile(tableToImport)); - - hTableDescriptors.addAll(Arrays.asList(htds)); - } - - if (CollectionUtils.isNotEmpty(hTableDescriptors)) { - for (TableDescriptor htd : hTableDescriptors) { - String tblName = htd.getTableName().getNameAsString(); - - importTable(tblName); - } - } - } - - private List getMatchingNameSpaces(String nameSpace) throws Exception { - List ret = new ArrayList<>(); - NamespaceDescriptor[] namespaceDescriptors = hbaseAdmin.listNamespaceDescriptors(); - Pattern pattern = Pattern.compile(nameSpace); - - for (NamespaceDescriptor namespaceDescriptor:namespaceDescriptors){ - String nmSpace = namespaceDescriptor.getName(); - Matcher matcher = pattern.matcher(nmSpace); - - if (matcher.find()){ - ret.add(namespaceDescriptor); - } - } - - return ret; - } - - private List getTableDescriptors(List namespaceDescriptors) throws Exception { - List ret = new ArrayList<>(); - - for(NamespaceDescriptor namespaceDescriptor:namespaceDescriptors) { - TableDescriptor[] tableDescriptors = hbaseAdmin.listTableDescriptorsByNamespace(namespaceDescriptor.getName()); - - ret.addAll(Arrays.asList(tableDescriptors)); - } - - return ret; - } - - protected AtlasEntityWithExtInfo createOrUpdateNameSpace(NamespaceDescriptor namespaceDescriptor) throws Exception { - String nsName = namespaceDescriptor.getName(); - String nsQualifiedName = getNameSpaceQualifiedName(metadataNamespace, nsName); - AtlasEntityWithExtInfo nsEntity = findNameSpaceEntityInAtlas(nsQualifiedName); - - if (nsEntity == null) { - LOG.info("Importing NameSpace: " + nsQualifiedName); - - AtlasEntity entity = getNameSpaceEntity(nsName, null); - - nsEntity = createEntityInAtlas(new AtlasEntityWithExtInfo(entity)); - } else { - LOG.info("NameSpace already present in Atlas. Updating it..: " + nsQualifiedName); - - AtlasEntity entity = getNameSpaceEntity(nsName, nsEntity.getEntity()); - - nsEntity.setEntity(entity); - - nsEntity = updateEntityInAtlas(nsEntity); - } - return nsEntity; - } - - protected AtlasEntityWithExtInfo createOrUpdateTable(String nameSpace, String tableName, AtlasEntity nameSapceEntity, TableDescriptor htd, ColumnFamilyDescriptor[] hcdts) throws Exception { - String owner = htd.getOwnerString(); - String tblQualifiedName = getTableQualifiedName(metadataNamespace, nameSpace, tableName); - AtlasEntityWithExtInfo ret = findTableEntityInAtlas(tblQualifiedName); - - if (ret == null) { - LOG.info("Importing Table: " + tblQualifiedName); - - AtlasEntity entity = getTableEntity(nameSpace, tableName, owner, nameSapceEntity, htd, null); - - ret = createEntityInAtlas(new AtlasEntityWithExtInfo(entity)); - } else { - LOG.info("Table already present in Atlas. Updating it..: " + tblQualifiedName); - - AtlasEntity entity = getTableEntity(nameSpace, tableName, owner, nameSapceEntity, htd, ret.getEntity()); - - ret.setEntity(entity); - - ret = updateEntityInAtlas(ret); - } - - AtlasEntity tableEntity = ret.getEntity(); - - if (tableEntity != null) { - List cfEntities = createOrUpdateColumnFamilies(nameSpace, tableName, owner, hcdts, tableEntity); - - List cfIDs = new ArrayList<>(); - - if (CollectionUtils.isNotEmpty(cfEntities)) { - for (AtlasEntityWithExtInfo cfEntity : cfEntities) { - cfIDs.add(AtlasTypeUtil.getAtlasObjectId(cfEntity.getEntity())); - } - } - tableEntity.setRelationshipAttribute(COLUMN_FAMILIES, AtlasTypeUtil.getAtlasRelatedObjectIdList(cfIDs, HBaseAtlasHook.RELATIONSHIP_HBASE_TABLE_COLUMN_FAMILIES)); - } - - return ret; - } - - protected List createOrUpdateColumnFamilies(String nameSpace, String tableName, String owner, ColumnFamilyDescriptor[] hcdts , AtlasEntity tableEntity) throws Exception { - List ret = new ArrayList<>(); - - if (hcdts != null) { - AtlasObjectId tableId = AtlasTypeUtil.getAtlasObjectId(tableEntity); - - for (ColumnFamilyDescriptor columnFamilyDescriptor : hcdts) { - String cfName = columnFamilyDescriptor.getNameAsString(); - String cfQualifiedName = getColumnFamilyQualifiedName(metadataNamespace, nameSpace, tableName, cfName); - AtlasEntityWithExtInfo cfEntity = findColumnFamiltyEntityInAtlas(cfQualifiedName); - - if (cfEntity == null) { - LOG.info("Importing Column-family: " + cfQualifiedName); - - AtlasEntity entity = getColumnFamilyEntity(nameSpace, tableName, owner, columnFamilyDescriptor, tableId, null); - - cfEntity = createEntityInAtlas(new AtlasEntityWithExtInfo(entity)); - } else { - LOG.info("ColumnFamily already present in Atlas. Updating it..: " + cfQualifiedName); - - AtlasEntity entity = getColumnFamilyEntity(nameSpace, tableName, owner, columnFamilyDescriptor, tableId, cfEntity.getEntity()); - - cfEntity.setEntity(entity); - - cfEntity = updateEntityInAtlas(cfEntity); - } - - ret.add(cfEntity); - } - } - - return ret; - } - - private AtlasEntityWithExtInfo findNameSpaceEntityInAtlas(String nsQualifiedName) { - AtlasEntityWithExtInfo ret = null; - - try { - ret = findEntityInAtlas(HBaseDataTypes.HBASE_NAMESPACE.getName(), nsQualifiedName); - clearRelationshipAttributes(ret); - } catch (Exception e) { - ret = null; // entity doesn't exist in Atlas - } - - return ret; - } - - private AtlasEntityWithExtInfo findTableEntityInAtlas(String tableQualifiedName) { - AtlasEntityWithExtInfo ret = null; - - try { - ret = findEntityInAtlas(HBaseDataTypes.HBASE_TABLE.getName(), tableQualifiedName); - clearRelationshipAttributes(ret); - } catch (Exception e) { - ret = null; // entity doesn't exist in Atlas - } - - return ret; - } - - private AtlasEntityWithExtInfo findColumnFamiltyEntityInAtlas(String columnFamilyQualifiedName) { - AtlasEntityWithExtInfo ret = null; - - try { - ret = findEntityInAtlas(HBaseDataTypes.HBASE_COLUMN_FAMILY.getName(), columnFamilyQualifiedName); - clearRelationshipAttributes(ret); - } catch (Exception e) { - ret = null; // entity doesn't exist in Atlas - } - - return ret; - } - - private AtlasEntityWithExtInfo findEntityInAtlas(String typeName, String qualifiedName) throws Exception { - Map attributes = Collections.singletonMap(QUALIFIED_NAME, qualifiedName); - - return atlasClientV2.getEntityByAttribute(typeName, attributes); - } - - private AtlasEntity getNameSpaceEntity(String nameSpace, AtlasEntity nsEtity) { - AtlasEntity ret = null ; - - if (nsEtity == null) { - ret = new AtlasEntity(HBaseDataTypes.HBASE_NAMESPACE.getName()); - } else { - ret = nsEtity; - } - - String qualifiedName = getNameSpaceQualifiedName(metadataNamespace, nameSpace); - - ret.setAttribute(QUALIFIED_NAME, qualifiedName); - ret.setAttribute(CLUSTERNAME, metadataNamespace); - ret.setAttribute(NAME, nameSpace); - ret.setAttribute(DESCRIPTION_ATTR, nameSpace); - - return ret; - } - - private AtlasEntity getTableEntity(String nameSpace, String tableName, String owner, AtlasEntity nameSpaceEntity, TableDescriptor htd, AtlasEntity atlasEntity) { - AtlasEntity ret = null; - - if (atlasEntity == null) { - ret = new AtlasEntity(HBaseDataTypes.HBASE_TABLE.getName()); - } else { - ret = atlasEntity; - } - - String tableQualifiedName = getTableQualifiedName(metadataNamespace, nameSpace, tableName); - - ret.setAttribute(QUALIFIED_NAME, tableQualifiedName); - ret.setAttribute(CLUSTERNAME, metadataNamespace); - ret.setRelationshipAttribute(NAMESPACE, AtlasTypeUtil.getAtlasRelatedObjectId(nameSpaceEntity, HBaseAtlasHook.RELATIONSHIP_HBASE_TABLE_NAMESPACE)); - ret.setAttribute(NAME, tableName); - ret.setAttribute(DESCRIPTION_ATTR, tableName); - ret.setAttribute(OWNER, owner); - ret.setAttribute(URI, tableName); - ret.setAttribute(ATTR_TABLE_MAX_FILESIZE, htd.getMaxFileSize()); - ret.setAttribute(ATTR_TABLE_REPLICATION_PER_REGION, htd.getRegionReplication()); - ret.setAttribute(ATTR_TABLE_ISREADONLY, htd.isReadOnly()); - ret.setAttribute(ATTR_TABLE_ISCOMPACTION_ENABLED, htd.isCompactionEnabled()); - ret.setAttribute(ATTR_TABLE_DURABLILITY, (htd.getDurability() != null ? htd.getDurability().name() : null)); - ret.setAttribute(ATTR_TABLE_NORMALIZATION_ENABLED, htd.isNormalizationEnabled()); - - return ret; - } - - private AtlasEntity getColumnFamilyEntity(String nameSpace, String tableName, String owner, ColumnFamilyDescriptor hcdt, AtlasObjectId tableId, AtlasEntity atlasEntity){ - AtlasEntity ret = null; - - if (atlasEntity == null) { - ret = new AtlasEntity(HBaseDataTypes.HBASE_COLUMN_FAMILY.getName()); - } else { - ret = atlasEntity; - } - - String cfName = hcdt.getNameAsString(); - String cfQualifiedName = getColumnFamilyQualifiedName(metadataNamespace, nameSpace, tableName, cfName); - - ret.setAttribute(QUALIFIED_NAME, cfQualifiedName); - ret.setAttribute(CLUSTERNAME, metadataNamespace); - ret.setRelationshipAttribute(TABLE, AtlasTypeUtil.getAtlasRelatedObjectId(tableId, HBaseAtlasHook.RELATIONSHIP_HBASE_TABLE_COLUMN_FAMILIES)); - ret.setAttribute(NAME, cfName); - ret.setAttribute(DESCRIPTION_ATTR, cfName); - ret.setAttribute(OWNER, owner); - ret.setAttribute(ATTR_CF_BLOCK_CACHE_ENABLED, hcdt.isBlockCacheEnabled()); - ret.setAttribute(ATTR_CF_BLOOMFILTER_TYPE, (hcdt.getBloomFilterType() != null ? hcdt.getBloomFilterType().name():null)); - ret.setAttribute(ATTR_CF_CACHED_BLOOM_ON_WRITE, hcdt.isCacheBloomsOnWrite()); - ret.setAttribute(ATTR_CF_CACHED_DATA_ON_WRITE, hcdt.isCacheDataOnWrite()); - ret.setAttribute(ATTR_CF_CACHED_INDEXES_ON_WRITE, hcdt.isCacheIndexesOnWrite()); - ret.setAttribute(ATTR_CF_COMPACTION_COMPRESSION_TYPE, (hcdt.getCompactionCompressionType() != null ? hcdt.getCompactionCompressionType().name():null)); - ret.setAttribute(ATTR_CF_COMPRESSION_TYPE, (hcdt.getCompressionType() != null ? hcdt.getCompressionType().name():null)); - ret.setAttribute(ATTR_CF_DATA_BLOCK_ENCODING, (hcdt.getDataBlockEncoding() != null ? hcdt.getDataBlockEncoding().name():null)); - ret.setAttribute(ATTR_CF_ENCRYPTION_TYPE, hcdt.getEncryptionType()); - ret.setAttribute(ATTR_CF_EVICT_BLOCK_ONCLOSE, hcdt.isEvictBlocksOnClose()); - ret.setAttribute(ATTR_CF_KEEP_DELETE_CELLS, ( hcdt.getKeepDeletedCells() != null ? hcdt.getKeepDeletedCells().name():null)); - ret.setAttribute(ATTR_CF_MAX_VERSIONS, hcdt.getMaxVersions()); - ret.setAttribute(ATTR_CF_MIN_VERSIONS, hcdt.getMinVersions()); - ret.setAttribute(ATTR_CF_PREFETCH_BLOCK_ONOPEN, hcdt.isPrefetchBlocksOnOpen()); - ret.setAttribute(ATTR_CF_TTL, hcdt.getTimeToLive()); - ret.setAttribute(ATTR_CF_INMEMORY_COMPACTION_POLICY, (hcdt.getInMemoryCompaction() != null ? hcdt.getInMemoryCompaction().name():null)); - ret.setAttribute(ATTR_CF_MOB_COMPATCTPARTITION_POLICY, ( hcdt.getMobCompactPartitionPolicy() != null ? hcdt.getMobCompactPartitionPolicy().name():null)); - ret.setAttribute(ATTR_CF_MOB_ENABLED,hcdt.isMobEnabled()); - ret.setAttribute(ATTR_CF_NEW_VERSION_BEHAVIOR,hcdt.isNewVersionBehavior()); - - return ret; - } - - private AtlasEntityWithExtInfo createEntityInAtlas(AtlasEntityWithExtInfo entity) throws Exception { - AtlasEntityWithExtInfo ret = null; - EntityMutationResponse response = atlasClientV2.createEntity(entity); - List entities = response.getCreatedEntities(); - - if (CollectionUtils.isNotEmpty(entities)) { - AtlasEntityWithExtInfo getByGuidResponse = atlasClientV2.getEntityByGuid(entities.get(0).getGuid()); - - ret = getByGuidResponse; - - LOG.info("Created {} entity: name={}, guid={}", ret.getEntity().getTypeName(), ret.getEntity().getAttribute(ATTRIBUTE_QUALIFIED_NAME), ret.getEntity().getGuid()); - } - return ret; - } - - private AtlasEntityWithExtInfo updateEntityInAtlas(AtlasEntityWithExtInfo entity) throws Exception { - AtlasEntityWithExtInfo ret = null; - EntityMutationResponse response = atlasClientV2.updateEntity(entity); - - if (response != null) { - List entities = response.getUpdatedEntities(); - - if (CollectionUtils.isNotEmpty(entities)) { - AtlasEntityWithExtInfo getByGuidResponse = atlasClientV2.getEntityByGuid(entities.get(0).getGuid()); - - ret = getByGuidResponse; - - LOG.info("Updated {} entity: name={}, guid={} ", ret.getEntity().getTypeName(), ret.getEntity().getAttribute(ATTRIBUTE_QUALIFIED_NAME), ret.getEntity().getGuid()); - } else { - LOG.info("Entity: name={} ", entity.toString() + " not updated as it is unchanged from what is in Atlas" ); - ret = entity; - } - } else { - LOG.info("Entity: name={} ", entity.toString() + " not updated as it is unchanged from what is in Atlas" ); - ret = entity; - } - - return ret; - } - - /** - * Construct the qualified name used to uniquely identify a ColumnFamily instance in Atlas. - * @param metadataNamespace Metadata namespace of the cluster to which the Hbase component belongs - * @param nameSpace Name of the Hbase database to which the Table belongs - * @param tableName Name of the Hbase table - * @param columnFamily Name of the ColumnFamily - * @return Unique qualified name to identify the Table instance in Atlas. - */ - private static String getColumnFamilyQualifiedName(String metadataNamespace, String nameSpace, String tableName, String columnFamily) { - tableName = stripNameSpace(tableName); - return String.format(HBASE_COLUMN_FAMILY_QUALIFIED_NAME_FORMAT, nameSpace, tableName, columnFamily, metadataNamespace); - } - - /** - * Construct the qualified name used to uniquely identify a Table instance in Atlas. - * @param metadataNamespace Metadata namespace of the cluster to which the Hbase component belongs - * @param nameSpace Name of the Hbase database to which the Table belongs - * @param tableName Name of the Hbase table - * @return Unique qualified name to identify the Table instance in Atlas. - */ - private static String getTableQualifiedName(String metadataNamespace, String nameSpace, String tableName) { - tableName = stripNameSpace(tableName); - return String.format(HBASE_TABLE_QUALIFIED_NAME_FORMAT, nameSpace, tableName, metadataNamespace); - } - - /** - * Construct the qualified name used to uniquely identify a Hbase NameSpace instance in Atlas. - * @param metadataNamespace Metadata namespace of the cluster to which the Hbase component belongs - * @param nameSpace Name of the NameSpace - * @return Unique qualified name to identify the HBase NameSpace instance in Atlas. - */ - private static String getNameSpaceQualifiedName(String metadataNamespace, String nameSpace) { - return String.format(HBASE_NAMESPACE_QUALIFIED_NAME, nameSpace, metadataNamespace); - } - - private static String stripNameSpace(String tableName){ - tableName = tableName.substring(tableName.indexOf(":")+1); - - return tableName; - } - - private static void printUsage() { - System.out.println("Usage 1: import-hbase.sh [-n OR --namespace ] [-t

OR --table
]"); - System.out.println("Usage 2: import-hbase.sh [-f ]" ); - System.out.println(" Format:"); - System.out.println(" namespace1:tbl1"); - System.out.println(" namespace1:tbl2"); - System.out.println(" namespace2:tbl1"); - } - - private void clearRelationshipAttributes(AtlasEntityWithExtInfo entity) { - if (entity != null) { - clearRelationshipAttributes(entity.getEntity()); - - if (entity.getReferredEntities() != null) { - clearRelationshipAttributes(entity.getReferredEntities().values()); - } - } - } - - private void clearRelationshipAttributes(Collection entities) { - if (entities != null) { - for (AtlasEntity entity : entities) { - clearRelationshipAttributes(entity); - } - } - } - - private void clearRelationshipAttributes(AtlasEntity entity) { - if (entity != null && entity.getRelationshipAttributes() != null) { - entity.getRelationshipAttributes().clear(); - } - } -} diff --git a/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/hook/HBaseAtlasCoprocessor.java b/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/hook/HBaseAtlasCoprocessor.java deleted file mode 100644 index 313132de6c1..00000000000 --- a/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/hook/HBaseAtlasCoprocessor.java +++ /dev/null @@ -1,134 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hbase.hook; - - -import org.apache.atlas.hbase.bridge.HBaseAtlasHook; -import org.apache.hadoop.hbase.TableName; -import org.apache.hadoop.hbase.NamespaceDescriptor; -import org.apache.hadoop.hbase.client.RegionInfo; -import org.apache.hadoop.hbase.client.SnapshotDescription; -import org.apache.hadoop.hbase.client.TableDescriptor; -import org.apache.hadoop.hbase.coprocessor.MasterCoprocessor; -import org.apache.hadoop.hbase.coprocessor.BulkLoadObserver; -import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment; -import org.apache.hadoop.hbase.coprocessor.MasterObserver; -import org.apache.hadoop.hbase.coprocessor.ObserverContext; -import org.apache.hadoop.hbase.coprocessor.RegionObserver; -import org.apache.hadoop.hbase.coprocessor.RegionServerObserver; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; - -public class HBaseAtlasCoprocessor implements MasterCoprocessor, MasterObserver, RegionObserver, RegionServerObserver { - private static final Logger LOG = LoggerFactory.getLogger(HBaseAtlasCoprocessor.class); - - final HBaseAtlasHook hbaseAtlasHook; - - public HBaseAtlasCoprocessor() { - hbaseAtlasHook = HBaseAtlasHook.getInstance(); - } - - @Override - public void postCreateTable(ObserverContext observerContext, TableDescriptor tableDescriptor, RegionInfo[] hRegionInfos) throws IOException { - LOG.info("==> HBaseAtlasCoprocessor.postCreateTable()"); - - hbaseAtlasHook.sendHBaseTableOperation(tableDescriptor, null, HBaseAtlasHook.OPERATION.CREATE_TABLE, observerContext); - if (LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.postCreateTable()"); - } - } - - @Override - public void postDeleteTable(ObserverContext observerContext, TableName tableName) throws IOException { - LOG.info("==> HBaseAtlasCoprocessor.postDeleteTable()"); - hbaseAtlasHook.sendHBaseTableOperation(null, tableName, HBaseAtlasHook.OPERATION.DELETE_TABLE, observerContext); - if (LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.postDeleteTable()"); - } - } - - @Override - public void postModifyTable(ObserverContext observerContext, TableName tableName, TableDescriptor tableDescriptor) throws IOException { - LOG.info("==> HBaseAtlasCoprocessor.postModifyTable()"); - hbaseAtlasHook.sendHBaseTableOperation(tableDescriptor, tableName, HBaseAtlasHook.OPERATION.ALTER_TABLE, observerContext); - if (LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.postModifyTable()"); - } - } - - @Override - public void postCreateNamespace(ObserverContext observerContext, NamespaceDescriptor namespaceDescriptor) throws IOException { - LOG.info("==> HBaseAtlasCoprocessor.postCreateNamespace()"); - - hbaseAtlasHook.sendHBaseNameSpaceOperation(namespaceDescriptor, null, HBaseAtlasHook.OPERATION.CREATE_NAMESPACE, observerContext); - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.postCreateNamespace()"); - } - } - - @Override - public void postDeleteNamespace(ObserverContext observerContext, String s) throws IOException { - LOG.info("==> HBaseAtlasCoprocessor.postDeleteNamespace()"); - - hbaseAtlasHook.sendHBaseNameSpaceOperation(null, s, HBaseAtlasHook.OPERATION.DELETE_NAMESPACE, observerContext); - - if (LOG.isDebugEnabled()) { - LOG.debug("==> HBaseAtlasCoprocessor.postDeleteNamespace()"); - } - } - - @Override - public void postModifyNamespace(ObserverContext observerContext, NamespaceDescriptor namespaceDescriptor) throws IOException { - LOG.info("==> HBaseAtlasCoprocessor.postModifyNamespace()"); - - hbaseAtlasHook.sendHBaseNameSpaceOperation(namespaceDescriptor, null, HBaseAtlasHook.OPERATION.ALTER_NAMESPACE, observerContext); - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.postModifyNamespace()"); - } - } - - @Override - public void postCloneSnapshot(ObserverContext observerContext, SnapshotDescription snapshot, TableDescriptor tableDescriptor) throws IOException { - LOG.info("==> HBaseAtlasCoprocessor.postCloneSnapshot()"); - - hbaseAtlasHook.sendHBaseTableOperation(tableDescriptor, null, HBaseAtlasHook.OPERATION.CREATE_TABLE, observerContext); - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.postCloneSnapshot()"); - } - } - - @Override - public void postRestoreSnapshot(ObserverContext observerContext, SnapshotDescription snapshot, TableDescriptor tableDescriptor) throws IOException { - LOG.info("==> HBaseAtlasCoprocessor.postRestoreSnapshot()"); - - hbaseAtlasHook.sendHBaseTableOperation(tableDescriptor, snapshot.getTableName(), HBaseAtlasHook.OPERATION.ALTER_TABLE, observerContext); - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HBaseAtlasCoprocessor.postRestoreSnapshot()"); - } - } - -} - - diff --git a/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/model/HBaseDataTypes.java b/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/model/HBaseDataTypes.java deleted file mode 100644 index b83e1b54bab..00000000000 --- a/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/model/HBaseDataTypes.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hbase.model; - -/** - * HBASE Data Types for model and bridge. - */ -public enum HBaseDataTypes { - // Classes - HBASE_NAMESPACE, - HBASE_TABLE, - HBASE_COLUMN_FAMILY, - HBASE_COLUMN; - - public String getName() { - return name().toLowerCase(); - } -} diff --git a/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/model/HBaseOperationContext.java b/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/model/HBaseOperationContext.java deleted file mode 100644 index 1ef7c07dec6..00000000000 --- a/addons/hbase-bridge/src/main/java/org/apache/atlas/hbase/model/HBaseOperationContext.java +++ /dev/null @@ -1,174 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hbase.model; - -import org.apache.atlas.hbase.bridge.HBaseAtlasHook; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.hadoop.hbase.NamespaceDescriptor; -import org.apache.hadoop.hbase.HTableDescriptor; -import org.apache.hadoop.hbase.HColumnDescriptor; -import org.apache.hadoop.hbase.TableName; -import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; -import org.apache.hadoop.hbase.client.TableDescriptor; -import org.apache.hadoop.security.UserGroupInformation; - -import java.util.ArrayList; -import java.util.List; - -import java.util.Map; - -public class HBaseOperationContext { - private final UserGroupInformation ugi; - private final Map hbaseConf; - private final HBaseAtlasHook.OPERATION operation; - private final String user; - private final NamespaceDescriptor namespaceDescriptor; - private final TableDescriptor tableDescriptor; - private final ColumnFamilyDescriptor[] columnFamilyDescriptors; - private final TableName tableName; - private final String nameSpace; - private final String columnFamily; - private final String owner; - private final ColumnFamilyDescriptor columnFamilyDescriptor; - - public HBaseOperationContext(NamespaceDescriptor namespaceDescriptor, String nameSpace, TableDescriptor tableDescriptor, TableName tableName, ColumnFamilyDescriptor[] columnFamilyDescriptors, - ColumnFamilyDescriptor columnFamilyDescriptor, String columnFamily, HBaseAtlasHook.OPERATION operation, UserGroupInformation ugi , String user, String owner, - Map hbaseConf) { - this.namespaceDescriptor = namespaceDescriptor; - this.nameSpace = nameSpace; - this.tableDescriptor = tableDescriptor; - this.tableName = tableName; - this.columnFamilyDescriptors = columnFamilyDescriptors; - this.columnFamilyDescriptor = columnFamilyDescriptor; - this.columnFamily = columnFamily; - this.operation = operation; - this.ugi = ugi; - this.user = user; - this.owner = owner; - this.hbaseConf = hbaseConf; - } - - public HBaseOperationContext(NamespaceDescriptor namespaceDescriptor, String nameSpace, HBaseAtlasHook.OPERATION operation, UserGroupInformation ugi , String user, String owner) { - this(namespaceDescriptor, nameSpace, null, null, null, null, null, operation, ugi, user, owner, null); - } - - public HBaseOperationContext(String nameSpace, TableDescriptor tableDescriptor, TableName tableName, ColumnFamilyDescriptor[] columnFamilyDescriptors, HBaseAtlasHook.OPERATION operation, UserGroupInformation ugi, String user, String owner, Map hbaseConf) { - this(null, nameSpace, tableDescriptor, tableName, columnFamilyDescriptors, null, null, operation, ugi, user, owner, hbaseConf); - } - - public HBaseOperationContext(String nameSpace, TableName tableName, ColumnFamilyDescriptor columnFamilyDescriptor, String columnFamily, HBaseAtlasHook.OPERATION operation, UserGroupInformation ugi, String user, String owner, Map hbaseConf) { - this(null, nameSpace, null, tableName, null, columnFamilyDescriptor, columnFamily, operation, ugi, user, owner, hbaseConf); - } - - private List messages = new ArrayList<>(); - - public UserGroupInformation getUgi() { - return ugi; - } - - public Map getHbaseConf() { - return hbaseConf; - } - - public String getUser() { - return user; - } - - public HBaseAtlasHook.OPERATION getOperation() { - return operation; - } - - public NamespaceDescriptor getNamespaceDescriptor() { - return namespaceDescriptor; - } - - public TableDescriptor gethTableDescriptor() { - return tableDescriptor; - } - - public ColumnFamilyDescriptor[] gethColumnDescriptors() { - return columnFamilyDescriptors; - } - - public TableName getTableName() { - return tableName; - } - - public String getNameSpace() { - return nameSpace; - } - - public ColumnFamilyDescriptor gethColumnDescriptor() { - return columnFamilyDescriptor; - } - - public String getColummFamily() { - return columnFamily; - } - - public void addMessage(HookNotification message) { - messages.add(message); - } - - public String getOwner() { - return owner; - } - - public List getMessages() { - return messages; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - toString(sb); - return sb.toString(); - } - - public StringBuilder toString(StringBuilder sb) { - sb.append("HBaseOperationContext={"); - sb.append("Operation={").append(operation).append("} "); - sb.append("User ={").append(user).append("} "); - if (nameSpace != null ) { - sb.append("NameSpace={").append(nameSpace).append("}"); - } else { - if (namespaceDescriptor != null) { - sb.append("NameSpace={").append(namespaceDescriptor.toString()).append("}"); - } - } - if (tableName != null ) { - sb.append("Table={").append(tableName).append("}"); - } else { - if ( columnFamilyDescriptor != null) { - sb.append("Table={").append(tableDescriptor.toString()).append("}"); - } - } - if (columnFamily != null ) { - sb.append("Columm Family={").append(columnFamily).append("}"); - } else { - if ( columnFamilyDescriptor != null) { - sb.append("Columm Family={").append(columnFamilyDescriptor.toString()).append("}"); - } - } - sb.append("Message ={").append(getMessages()).append("} "); - sb.append(" }"); - return sb; - } - -} diff --git a/addons/hbase-bridge/src/main/resources/atlas-hbase-import-log4j.xml b/addons/hbase-bridge/src/main/resources/atlas-hbase-import-log4j.xml deleted file mode 100644 index 3fc2dcf9c30..00000000000 --- a/addons/hbase-bridge/src/main/resources/atlas-hbase-import-log4j.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/hbase-bridge/src/test/java/org/apache/atlas/hbase/HBaseAtlasHookIT.java b/addons/hbase-bridge/src/test/java/org/apache/atlas/hbase/HBaseAtlasHookIT.java deleted file mode 100644 index e3467887135..00000000000 --- a/addons/hbase-bridge/src/test/java/org/apache/atlas/hbase/HBaseAtlasHookIT.java +++ /dev/null @@ -1,307 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hbase; - -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasClient; -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.hbase.bridge.HBaseAtlasHook; -import org.apache.atlas.hbase.model.HBaseDataTypes; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; -import org.apache.atlas.utils.AuthenticationUtil; -import org.apache.atlas.utils.ParamChecker; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hbase.*; -import org.apache.hadoop.hbase.client.Admin; -import org.apache.hadoop.hbase.client.Connection; -import org.apache.hadoop.hbase.client.ConnectionFactory; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import java.io.IOException; -import java.net.ServerSocket; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.fail; -import static org.testng.AssertJUnit.assertFalse; - - -public class HBaseAtlasHookIT { - private static final Logger LOG = LoggerFactory.getLogger(HBaseAtlasHookIT.class); - protected static final String ATLAS_URL = "http://localhost:31000/"; - protected static final String CLUSTER_NAME = "primary"; - - private HBaseTestingUtility utility; - private int port; - private AtlasClientV2 atlasClient; - - - @BeforeClass - public void setUp() { - try { - createHBaseCluster(); - createAtlasClient(); - } catch (Exception e) { - LOG.error("Unable to create Hbase Admin for Testing ", e); - } - } - - @AfterClass - public void cleanup() throws Exception { - LOG.info("Stopping mini cluster.. "); - utility.shutdownMiniCluster(); - } - - @Test - public void testGetMetaTableRows() throws Exception { - List results = utility.getMetaTableRows(); - assertFalse("results should have some entries and is empty.", results.isEmpty()); - } - - @Test (enabled = false) - public void testCreateNamesapce() throws Exception { - final Configuration conf = HBaseConfiguration.create(); - - conf.set("hbase.zookeeper.quorum", "localhost"); - conf.set("hbase.zookeeper.property.clientPort", String.valueOf(port)); - conf.set("zookeeper.znode.parent", "/hbase-unsecure"); - - Connection conn = ConnectionFactory.createConnection(conf); - Admin admin = conn.getAdmin(); - NamespaceDescriptor ns = NamespaceDescriptor.create("test_namespace").build(); - - admin.createNamespace(ns); - - //assert on qualified name - String nameSpace = assertNameSpaceIsRegistered(ns.getName()); - AtlasClientV2 atlasClient = getAtlasClient(); - - if (atlasClient != null) { - AtlasEntityWithExtInfo nameSpaceRef = atlasClient.getEntityByGuid(nameSpace); - String nameSpaceQualifiedName = HBaseAtlasHook.getNameSpaceQualifiedName(CLUSTER_NAME, ns.getName()); - - Assert.assertEquals(nameSpaceRef.getEntity().getAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME), nameSpaceQualifiedName); - } else { - Assert.fail("Unable to create AtlasClient for Testing"); - } - } - - @Test (enabled = false) - public void testCreateTable() throws Exception { - final Configuration conf = HBaseConfiguration.create(); - - conf.set("hbase.zookeeper.quorum", "localhost"); - conf.set("hbase.zookeeper.property.clientPort", String.valueOf(port)); - conf.set("zookeeper.znode.parent", "/hbase-unsecure"); - - Connection conn = ConnectionFactory.createConnection(conf); - Admin admin = conn.getAdmin(); - String namespace = "test_namespace1"; - String tablename = "test_table"; - - // Create a table - if (!admin.tableExists(TableName.valueOf(namespace, tablename))) { - NamespaceDescriptor ns = NamespaceDescriptor.create(namespace).build(); - - admin.createNamespace(ns); - - HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(namespace, tablename)); - - tableDescriptor.addFamily(new HColumnDescriptor("colfam1")); - - admin.createTable(tableDescriptor); - } - - //assert on qualified name - String table = assertTableIsRegistered(namespace, tablename); - AtlasClientV2 atlasClient = getAtlasClient(); - - if (atlasClient != null) { - AtlasEntityWithExtInfo tableRef = atlasClient.getEntityByGuid(table); - String entityName = HBaseAtlasHook.getTableQualifiedName(CLUSTER_NAME, namespace, tablename); - - Assert.assertEquals(tableRef.getEntity().getAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME), entityName); - } else { - Assert.fail("Unable to create AtlasClient for Testing"); - } - } - - // Methods for creating HBase - - private void createAtlasClient() { - try { - org.apache.commons.configuration.Configuration configuration = ApplicationProperties.get(); - String[] atlasEndPoint = configuration.getStringArray(HBaseAtlasHook.ATTR_ATLAS_ENDPOINT); - - configuration.setProperty("atlas.cluster.name", CLUSTER_NAME); - - if (atlasEndPoint == null || atlasEndPoint.length == 0) { - atlasEndPoint = new String[]{ATLAS_URL}; - } - - Iterator keys = configuration.getKeys(); - while (keys.hasNext()) { - String key = keys.next(); - LOG.info("{} = {} ", key, configuration.getString(key)); - } - - if (AuthenticationUtil.isKerberosAuthenticationEnabled()) { - atlasClient = new AtlasClientV2(atlasEndPoint); - } else { - atlasClient = new AtlasClientV2(configuration, atlasEndPoint, new String[]{"admin", "admin"}); - } - } catch (Exception e) { - LOG.error("Unable to create AtlasClient for Testing ", e); - } - } - - private static int getFreePort() throws IOException { - ServerSocket serverSocket = new ServerSocket(0); - int port = serverSocket.getLocalPort(); - - serverSocket.close(); - - return port; - } - - private void createHBaseCluster() throws Exception { - LOG.info("Creating Hbase Admin..."); - - port = getFreePort(); - utility = new HBaseTestingUtility(); - - utility.getConfiguration().set("test.hbase.zookeeper.property.clientPort", String.valueOf(port)); - utility.getConfiguration().set("hbase.master.port", String.valueOf(getFreePort())); - utility.getConfiguration().set("hbase.master.info.port", String.valueOf(getFreePort())); - utility.getConfiguration().set("hbase.regionserver.port", String.valueOf(getFreePort())); - utility.getConfiguration().set("hbase.regionserver.info.port", String.valueOf(getFreePort())); - utility.getConfiguration().set("zookeeper.znode.parent", "/hbase-unsecure"); - utility.getConfiguration().set("hbase.table.sanity.checks", "false"); - utility.getConfiguration().set("hbase.coprocessor.master.classes", "org.apache.atlas.hbase.hook.HBaseAtlasCoprocessor"); - - utility.startMiniCluster(); - } - - - public AtlasClientV2 getAtlasClient() { - AtlasClientV2 ret = null; - if (atlasClient != null) { - ret = atlasClient; - } - return ret; - } - - protected String assertNameSpaceIsRegistered(String nameSpace) throws Exception { - return assertNameSpaceIsRegistered(nameSpace, null); - } - - protected String assertNameSpaceIsRegistered(String nameSpace, HBaseAtlasHookIT.AssertPredicate assertPredicate) throws Exception { - if (LOG.isDebugEnabled()) { - LOG.debug("Searching for nameSpace {}", nameSpace); - } - String nameSpaceQualifiedName = HBaseAtlasHook.getNameSpaceQualifiedName(CLUSTER_NAME, nameSpace); - return assertEntityIsRegistered(HBaseDataTypes.HBASE_NAMESPACE.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - nameSpaceQualifiedName, assertPredicate); - } - - protected String assertTableIsRegistered(String nameSpace, String tableName) throws Exception { - return assertTableIsRegistered(nameSpace, tableName, null); - } - - protected String assertTableIsRegistered(String nameSpace, String tableName, HBaseAtlasHookIT.AssertPredicate assertPredicate) throws Exception { - if (LOG.isDebugEnabled()) { - LOG.debug("Searching for nameSpace:Table {} {}", nameSpace, tableName); - } - String tableQualifiedName = HBaseAtlasHook.getTableQualifiedName(CLUSTER_NAME, nameSpace, tableName); - return assertEntityIsRegistered(HBaseDataTypes.HBASE_TABLE.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, tableQualifiedName, - assertPredicate); - } - - public interface AssertPredicate { - void assertOnEntity(AtlasEntity entity) throws Exception; - } - - public interface Predicate { - /** - * Perform a predicate evaluation. - * - * @return the boolean result of the evaluation. - * @throws Exception thrown if the predicate evaluation could not evaluate. - */ - void evaluate() throws Exception; - } - - - protected String assertEntityIsRegistered(final String typeName, final String property, final String value, - final HBaseAtlasHookIT.AssertPredicate assertPredicate) throws Exception { - waitFor(30000, new HBaseAtlasHookIT.Predicate() { - @Override - public void evaluate() throws Exception { - AtlasEntityWithExtInfo entity = atlasClient.getEntityByAttribute(typeName, Collections.singletonMap(property, value)); - - assertNotNull(entity); - - if (assertPredicate != null) { - assertPredicate.assertOnEntity(entity.getEntity()); - } - } - }); - - AtlasEntityWithExtInfo entity = atlasClient.getEntityByAttribute(typeName, Collections.singletonMap(property, value)); - - return entity.getEntity().getGuid(); - } - - /** - * Wait for a condition, expressed via a {@link HBaseAtlasHookIT.Predicate} to become true. - * - * @param timeout maximum time in milliseconds to wait for the predicate to become true. - * @param predicate predicate waiting on. - */ - protected void waitFor(int timeout, HBaseAtlasHookIT.Predicate predicate) throws Exception { - ParamChecker.notNull(predicate, "predicate"); - long mustEnd = System.currentTimeMillis() + timeout; - - while (true) { - try { - predicate.evaluate(); - return; - } catch (Error | Exception e) { - if (System.currentTimeMillis() >= mustEnd) { - fail("Assertions failed. Failing after waiting for timeout " + timeout + " msecs", e); - } - if (LOG.isDebugEnabled()) { - LOG.debug("Waiting up to {} msec as assertion failed", mustEnd - System.currentTimeMillis(), e); - } - Thread.sleep(5000); - } - } - } - - -} diff --git a/addons/hbase-bridge/src/test/resources/atlas-application.properties b/addons/hbase-bridge/src/test/resources/atlas-application.properties deleted file mode 100644 index 3b12e5fb333..00000000000 --- a/addons/hbase-bridge/src/test/resources/atlas-application.properties +++ /dev/null @@ -1,125 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# - -######### Atlas Server Configs ######### -atlas.rest.address=http://localhost:31000 - -######### Graph Database Configs ######### - - -# Graph database implementation. Value inserted by maven. -atlas.graphdb.backend=org.apache.atlas.repository.graphdb.janus.AtlasJanusGraphDatabase -atlas.graph.index.search.solr.wait-searcher=true - -# Graph Storage -atlas.graph.storage.backend=berkeleyje - -# Entity repository implementation -atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.InMemoryEntityAuditRepository - -# Graph Search Index Backend -atlas.graph.index.search.backend=solr - -#Berkeley storage directory -atlas.graph.storage.directory=${sys:atlas.data}/berkley - -#hbase -#For standalone mode , specify localhost -#for distributed mode, specify zookeeper quorum here - -atlas.graph.storage.hostname=${graph.storage.hostname} -atlas.graph.storage.hbase.regions-per-server=1 -atlas.graph.storage.lock.wait-time=10000 - -#ElasticSearch -atlas.graph.index.search.directory=${sys:atlas.data}/es -atlas.graph.index.search.elasticsearch.client-only=false -atlas.graph.index.search.elasticsearch.local-mode=true -atlas.graph.index.search.elasticsearch.create.sleep=2000 - -# Solr cloud mode properties -atlas.graph.index.search.solr.mode=cloud -atlas.graph.index.search.solr.zookeeper-url=${solr.zk.address} -atlas.graph.index.search.solr.embedded=true -atlas.graph.index.search.max-result-set-size=150 - - -######### Notification Configs ######### -atlas.notification.embedded=true - -atlas.kafka.zookeeper.connect=localhost:19026 -atlas.kafka.bootstrap.servers=localhost:19027 -atlas.kafka.data=${sys:atlas.data}/kafka -atlas.kafka.zookeeper.session.timeout.ms=4000 -atlas.kafka.zookeeper.sync.time.ms=20 -atlas.kafka.consumer.timeout.ms=4000 -atlas.kafka.auto.commit.interval.ms=100 -atlas.kafka.hook.group.id=atlas -atlas.kafka.entities.group.id=atlas_entities -#atlas.kafka.auto.commit.enable=false - -atlas.kafka.enable.auto.commit=false -atlas.kafka.auto.offset.reset=earliest -atlas.kafka.session.timeout.ms=30000 -atlas.kafka.offsets.topic.replication.factor=1 - - - -######### Entity Audit Configs ######### -atlas.audit.hbase.tablename=ATLAS_ENTITY_AUDIT_EVENTS -atlas.audit.zookeeper.session.timeout.ms=1000 -atlas.audit.hbase.zookeeper.quorum=localhost -atlas.audit.hbase.zookeeper.property.clientPort=19026 - -######### Security Properties ######### - -# SSL config -atlas.enableTLS=false -atlas.server.https.port=31443 - -######### Security Properties ######### - -hbase.security.authentication=simple - -atlas.hook.falcon.synchronous=true - -######### JAAS Configuration ######## - -atlas.jaas.KafkaClient.loginModuleName = com.sun.security.auth.module.Krb5LoginModule -atlas.jaas.KafkaClient.loginModuleControlFlag = required -atlas.jaas.KafkaClient.option.useKeyTab = true -atlas.jaas.KafkaClient.option.storeKey = true -atlas.jaas.KafkaClient.option.serviceName = kafka -atlas.jaas.KafkaClient.option.keyTab = /etc/security/keytabs/atlas.service.keytab -atlas.jaas.KafkaClient.option.principal = atlas/_HOST@EXAMPLE.COM - -######### High Availability Configuration ######## -atlas.server.ha.enabled=false -#atlas.server.ids=id1 -#atlas.server.address.id1=localhost:21000 - -######### Atlas Authorization ######### -atlas.authorizer.impl=none -# atlas.authorizer.impl=simple -# atlas.authorizer.simple.authz.policy.file=atlas-simple-authz-policy.json - -######### Atlas Authentication ######### -atlas.authentication.method.file=true -atlas.authentication.method.ldap.type=none -atlas.authentication.method.kerberos=false -# atlas.authentication.method.file.filename=users-credentials.properties diff --git a/addons/hbase-bridge/src/test/resources/atlas-log4j.xml b/addons/hbase-bridge/src/test/resources/atlas-log4j.xml deleted file mode 100755 index 2c9815ff540..00000000000 --- a/addons/hbase-bridge/src/test/resources/atlas-log4j.xml +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/hbase-bridge/src/test/resources/users-credentials.properties b/addons/hbase-bridge/src/test/resources/users-credentials.properties deleted file mode 100644 index 5046dbaf646..00000000000 --- a/addons/hbase-bridge/src/test/resources/users-credentials.properties +++ /dev/null @@ -1,3 +0,0 @@ -#username=group::sha256-password -admin=ADMIN::a4a88c0872bf652bb9ed803ece5fd6e82354838a9bf59ab4babb1dab322154e1 -rangertagsync=RANGER_TAG_SYNC::0afe7a1968b07d4c3ff4ed8c2d809a32ffea706c66cd795ead9048e81cfaf034 diff --git a/addons/hbase-testing-util/pom.xml b/addons/hbase-testing-util/pom.xml deleted file mode 100644 index 982e9c85ea3..00000000000 --- a/addons/hbase-testing-util/pom.xml +++ /dev/null @@ -1,228 +0,0 @@ - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - hbase-testing-util - Apache HBase - Testing Util - HBase Testing Utilities. - jar - - - 3.0.3 - 9.3.14.v20161028 - - - - - org.testng - testng - - - - org.apache.hbase - hbase-server - ${hbase.version} - compile - - - - org.apache.hbase - hbase-server - ${hbase.version} - test-jar - compile - - - - org.apache.hbase - hbase-zookeeper - ${hbase.version} - jar - compile - - - - org.apache.hbase - hbase-zookeeper - ${hbase.version} - test-jar - compile - - - - org.apache.hadoop - hadoop-hdfs - ${hadoop.version} - compile - - - - org.apache.hadoop - hadoop-hdfs - ${hadoop.version} - test-jar - compile - - - - org.apache.hadoop - hadoop-common - ${hadoop.version} - - - junit - junit - - - - - - junit - junit - ${junit.version} - - - - org.apache.hadoop - hadoop-minicluster - ${hadoop.version} - compile - - - org.apache.htrace - htrace-core - - - - - org.apache.hadoop - hadoop-minikdc - ${hadoop.version} - - - - org.apache.hbase - hbase-hadoop-compat - ${hbase.version} - jar - compile - - - - org.apache.hbase - hbase-hadoop-compat - ${hbase.version} - test-jar - compile - - - - org.apache.hbase - hbase-hadoop2-compat - ${hbase.version} - jar - compile - - - com.github.stephenc.findbugs - findbugs-annotations - - - - - - org.apache.hbase - hbase-hadoop2-compat - ${hbase.version} - test-jar - compile - - - - - org.slf4j - slf4j-log4j12 - - - - org.apache.hbase - hbase-common - ${hbase.version} - jar - compile - - - com.github.stephenc.findbugs - findbugs-annotations - - - - - - org.apache.hbase - hbase-common - ${hbase.version} - test-jar - compile - - - - org.apache.hbase - hbase-annotations - ${hbase.version} - test-jar - compile - - - jdk.tools - jdk.tools - - - - - - org.apache.hbase - hbase-protocol - ${hbase.version} - jar - compile - - - - org.apache.hbase - hbase-client - ${hbase.version} - jar - compile - - - - - - - - diff --git a/addons/hbase-testing-util/src/test/java/org/apache/atlas/hbase/TestHBaseTestingUtilSpinup.java b/addons/hbase-testing-util/src/test/java/org/apache/atlas/hbase/TestHBaseTestingUtilSpinup.java deleted file mode 100644 index 0beb0355211..00000000000 --- a/addons/hbase-testing-util/src/test/java/org/apache/atlas/hbase/TestHBaseTestingUtilSpinup.java +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hbase; - -import org.apache.hadoop.hbase.HBaseTestingUtility; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.List; - -import static org.testng.AssertJUnit.assertFalse; - - -/** - * Make sure we can spin up a HBTU without a hbase-site.xml - */ -public class TestHBaseTestingUtilSpinup { - private static final Logger LOG = LoggerFactory.getLogger(TestHBaseTestingUtilSpinup.class); - private final static HBaseTestingUtility UTIL = new HBaseTestingUtility(); - - @BeforeClass - public static void beforeClass() throws Exception { - UTIL.startMiniCluster(); - if (!UTIL.getHBaseCluster().waitForActiveAndReadyMaster(30000)) { - throw new RuntimeException("Active master not ready"); - } - } - - @AfterClass - public static void afterClass() throws Exception { - UTIL.shutdownMiniCluster(); - } - - @Test - public void testGetMetaTableRows() throws Exception { - List results = UTIL.getMetaTableRows(); - assertFalse("results should have some entries and is empty.", results.isEmpty()); - } - -} diff --git a/addons/hbase-testing-util/src/test/resources/atlas-log4j.xml b/addons/hbase-testing-util/src/test/resources/atlas-log4j.xml deleted file mode 100755 index 47d4d5c7ce0..00000000000 --- a/addons/hbase-testing-util/src/test/resources/atlas-log4j.xml +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/hdfs-model/pom.xml b/addons/hdfs-model/pom.xml deleted file mode 100644 index 05ba173684d..00000000000 --- a/addons/hdfs-model/pom.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - hdfs-model - Apache Atlas FileSystem Model - Apache Atlas FileSystem Model - jar - - - - - org.slf4j - slf4j-api - - - - org.slf4j - slf4j-log4j12 - - - - - org.apache.atlas - atlas-client-v1 - - - - org.apache.atlas - atlas-notification - - - - org.mockito - mockito-all - - - - - - - org.testng - testng - - - - org.apache.atlas - atlas-graphdb-impls - pom - test - - - - org.apache.atlas - atlas-repository - test - - - - - - - org.apache.maven.plugins - maven-site-plugin - - - org.apache.maven.doxia - doxia-module-twiki - ${doxia.version} - - - org.apache.maven.doxia - doxia-core - ${doxia.version} - - - - - - site - - prepare-package - - - - false - false - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.2.1 - false - - - - - - - - diff --git a/addons/hive-bridge-shim/pom.xml b/addons/hive-bridge-shim/pom.xml deleted file mode 100755 index 849ca2a8f64..00000000000 --- a/addons/hive-bridge-shim/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - hive-bridge-shim - Apache Atlas Hive Bridge Shim Module - Apache Atlas Hive Bridge Shim - jar - - - - - org.apache.atlas - atlas-plugin-classloader - - - - org.apache.hive - hive-exec - ${hive.version} - provided - - - diff --git a/addons/hive-bridge-shim/src/main/java/org/apache/atlas/hive/hook/HiveHook.java b/addons/hive-bridge-shim/src/main/java/org/apache/atlas/hive/hook/HiveHook.java deleted file mode 100755 index 2a4d067e59b..00000000000 --- a/addons/hive-bridge-shim/src/main/java/org/apache/atlas/hive/hook/HiveHook.java +++ /dev/null @@ -1,99 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook; - - -import org.apache.atlas.plugin.classloader.AtlasPluginClassLoader; -import org.apache.hadoop.hive.ql.hooks.ExecuteWithHookContext; -import org.apache.hadoop.hive.ql.hooks.HookContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Hive hook used for atlas entity registration. - */ -public class HiveHook implements ExecuteWithHookContext { - private static final Logger LOG = LoggerFactory.getLogger(HiveHook.class); - - private static final String ATLAS_PLUGIN_TYPE = "hive"; - private static final String ATLAS_HIVE_HOOK_IMPL_CLASSNAME = "org.apache.atlas.hive.hook.HiveHook"; - - private AtlasPluginClassLoader atlasPluginClassLoader = null; - private ExecuteWithHookContext hiveHookImpl = null; - - public HiveHook() { - this.initialize(); - } - - @Override - public void run(final HookContext hookContext) throws Exception { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HiveHook.run({})", hookContext); - } - - try { - activatePluginClassLoader(); - hiveHookImpl.run(hookContext); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HiveHook.run({})", hookContext); - } - } - - private void initialize() { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HiveHook.initialize()"); - } - - try { - atlasPluginClassLoader = AtlasPluginClassLoader.getInstance(ATLAS_PLUGIN_TYPE, this.getClass()); - - @SuppressWarnings("unchecked") - Class cls = (Class) Class - .forName(ATLAS_HIVE_HOOK_IMPL_CLASSNAME, true, atlasPluginClassLoader); - - activatePluginClassLoader(); - - hiveHookImpl = cls.newInstance(); - } catch (Exception excp) { - LOG.error("Error instantiating Atlas hook implementation", excp); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HiveHook.initialize()"); - } - } - - private void activatePluginClassLoader() { - if (atlasPluginClassLoader != null) { - atlasPluginClassLoader.activate(); - } - } - - private void deactivatePluginClassLoader() { - if (atlasPluginClassLoader != null) { - atlasPluginClassLoader.deactivate(); - } - } -} diff --git a/addons/hive-bridge-shim/src/main/java/org/apache/atlas/hive/hook/HiveMetastoreHook.java b/addons/hive-bridge-shim/src/main/java/org/apache/atlas/hive/hook/HiveMetastoreHook.java deleted file mode 100644 index 2894e99bddd..00000000000 --- a/addons/hive-bridge-shim/src/main/java/org/apache/atlas/hive/hook/HiveMetastoreHook.java +++ /dev/null @@ -1,199 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook; - -import org.apache.atlas.plugin.classloader.AtlasPluginClassLoader; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hive.metastore.MetaStoreEventListener; -import org.apache.hadoop.hive.metastore.api.MetaException; -import org.apache.hadoop.hive.metastore.events.*; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Hive Metastore hook to capture DDL operations for atlas entity registration. - */ -public class HiveMetastoreHook extends MetaStoreEventListener { - private static final String ATLAS_PLUGIN_TYPE = "hive"; - private static final String ATLAS_HIVE_METASTORE_HOOK_IMPL_CLASSNAME = "org.apache.atlas.hive.hook.HiveMetastoreHookImpl"; - public static final Logger LOG = LoggerFactory.getLogger(HiveMetastoreHook.class); - - private AtlasPluginClassLoader atlasPluginClassLoader = null; - private MetaStoreEventListener atlasMetastoreHookImpl = null; - private Configuration config; - - public HiveMetastoreHook(Configuration config) { - super(config); - - this.config = config; - - this.initialize(); - } - - private void initialize() { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HiveMetastoreHook.initialize()"); - } - - try { - atlasPluginClassLoader = AtlasPluginClassLoader.getInstance(ATLAS_PLUGIN_TYPE, this.getClass()); - - @SuppressWarnings("unchecked") - Class cls = (Class) - Class.forName(ATLAS_HIVE_METASTORE_HOOK_IMPL_CLASSNAME, true, atlasPluginClassLoader); - - activatePluginClassLoader(); - - atlasMetastoreHookImpl = cls.getDeclaredConstructor(Configuration.class).newInstance(config); - } catch (Exception ex) { - LOG.error("Error instantiating Atlas hook implementation", ex); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HiveMetastoreHook.initialize()"); - } - } - - @Override - public void onCreateTable(CreateTableEvent tableEvent) throws MetaException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HiveMetastoreHook.onCreateTable()"); - } - - try { - activatePluginClassLoader(); - - atlasMetastoreHookImpl.onCreateTable(tableEvent); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HiveMetastoreHook.onCreateTable()"); - } - } - - @Override - public void onDropTable(DropTableEvent tableEvent) throws MetaException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HiveMetastoreHook.onDropTable()"); - } - - try { - activatePluginClassLoader(); - - atlasMetastoreHookImpl.onDropTable(tableEvent); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HiveMetastoreHook.onDropTable()"); - } - } - - @Override - public void onAlterTable(AlterTableEvent tableEvent) throws MetaException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HiveMetastoreHook.onAlterTable()"); - } - - try { - activatePluginClassLoader(); - - atlasMetastoreHookImpl.onAlterTable(tableEvent); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HiveMetastoreHook.onAlterTable()"); - } - } - - @Override - public void onCreateDatabase(CreateDatabaseEvent dbEvent) throws MetaException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HiveMetastoreHook.onCreateDatabase()"); - } - - try { - activatePluginClassLoader(); - - atlasMetastoreHookImpl.onCreateDatabase(dbEvent); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HiveMetastoreHook.onCreateDatabase()"); - } - } - - @Override - public void onDropDatabase(DropDatabaseEvent dbEvent) throws MetaException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HiveMetastoreHook.onDropDatabase()"); - } - - try { - activatePluginClassLoader(); - - atlasMetastoreHookImpl.onDropDatabase(dbEvent); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HiveMetastoreHook.onDropDatabase()"); - } - } - - @Override - public void onAlterDatabase(AlterDatabaseEvent dbEvent) throws MetaException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HiveMetastoreHook.onAlterDatabase()"); - } - - try { - activatePluginClassLoader(); - - atlasMetastoreHookImpl.onAlterDatabase(dbEvent); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HiveMetastoreHook.onAlterDatabase()"); - } - } - - private void activatePluginClassLoader() { - if (atlasPluginClassLoader != null) { - atlasPluginClassLoader.activate(); - } - } - - private void deactivatePluginClassLoader() { - if (atlasPluginClassLoader != null) { - atlasPluginClassLoader.deactivate(); - } - } -} \ No newline at end of file diff --git a/addons/hive-bridge/pom.xml b/addons/hive-bridge/pom.xml deleted file mode 100755 index 8c3636e5d62..00000000000 --- a/addons/hive-bridge/pom.xml +++ /dev/null @@ -1,535 +0,0 @@ - - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - hive-bridge - Apache Atlas Hive Bridge Module - Apache Atlas Hive Bridge - jar - - - - - org.slf4j - slf4j-api - - - - org.slf4j - slf4j-log4j12 - - - - org.apache.hive - hive-metastore - ${hive.version} - provided - - - org.mortbay.jetty - * - - - org.eclipse.jetty - * - - - com.github.stephenc.findbugs - findbugs-annotations - - - - - - - org.apache.hive - hive-exec - ${hive.version} - provided - - - javax.servlet - * - - - - - - org.apache.hive - hive-jdbc - ${hive.version} - test - - - javax.servlet - * - - - javax.ws.rs - * - - - org.eclipse.jetty - * - - - - - - org.apache.hive - hive-cli - ${hive.version} - test - - - javax.servlet - * - - - org.eclipse.jetty.aggregate - * - - - - - - - org.apache.atlas - atlas-client-v1 - - - - org.apache.atlas - atlas-client-v2 - ${project.version} - - - - org.apache.atlas - atlas-notification - - - - - org.apache.atlas - atlas-webapp - war - test - - - - org.apache.hadoop - hadoop-client - - - javax.servlet - servlet-api - - - org.eclipse.jetty - * - - - - - - org.apache.hadoop - hadoop-annotations - - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.databind.version} - - - - org.testng - testng - - - - org.mockito - mockito-all - - - - org.eclipse.jetty - jetty-server - test - - - - org.apache.atlas - atlas-graphdb-impls - pom - test - - - - org.apache.atlas - atlas-intg - tests - test - - - - org.apache.atlas - atlas-repository - tests - test - - - - com.fasterxml.jackson.core - jackson-core - ${jackson.version} - test - - - - - - dist - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-hook - package - - copy - - - ${project.build.directory}/dependency/hook/hive/atlas-hive-plugin-impl - false - false - true - - - ${project.groupId} - ${project.artifactId} - ${project.version} - - - ${project.groupId} - atlas-client-common - ${project.version} - - - ${project.groupId} - atlas-client-v1 - ${project.version} - - - ${project.groupId} - atlas-client-v2 - ${project.version} - - - ${project.groupId} - atlas-intg - ${project.version} - - - ${project.groupId} - atlas-notification - ${project.version} - - - ${project.groupId} - atlas-common - ${project.version} - - - org.apache.kafka - kafka_${kafka.scala.binary.version} - ${kafka.version} - - - org.apache.kafka - kafka-clients - ${kafka.version} - - - com.sun.jersey.contribs - jersey-multipart - ${jersey.version} - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.databind.version} - - - com.fasterxml.jackson.core - jackson-core - ${jackson.version} - - - com.fasterxml.jackson.core - jackson-annotations - ${jackson.version} - - - commons-configuration - commons-configuration - ${commons-conf.version} - - - com.sun.jersey - jersey-json - ${jersey.version} - - - javax.ws.rs - jsr311-api - ${jsr.version} - - - - - - copy-hook-shim - package - - copy - - - ${project.build.directory}/dependency/hook/hive - false - false - true - - - ${project.groupId} - hive-bridge-shim - ${project.version} - - - ${project.groupId} - atlas-plugin-classloader - ${project.version} - - - - - - - - - - - - - - org.eclipse.jetty - jetty-maven-plugin - ${jetty.version} - - ${skipTests} - - - 31000 - 60000 - - ../../webapp/target/atlas-webapp-${project.version}.war - true - ../../webapp/src/main/webapp - - / - ${project.basedir}/../../webapp/src/main/webapp/WEB-INF/web.xml - - true - - true - - atlas.home - ${project.build.directory} - - - atlas.conf - ${project.build.directory}/test-classes - - - atlas.data - ${project.build.directory}/data - - - atlas.log.dir - ${project.build.directory}/logs - - - atlas.log.file - application.log - - - log4j.configuration - file:///${project.build.directory}/test-classes/atlas-log4j.xml - - - atlas.graphdb.backend - ${graphdb.backend.impl} - - - embedded.solr.directory - ${project.build.directory} - - - solr.log.dir - ${project.build.directory}/logs - - - org.eclipse.jetty.annotations.maxWait - 5000 - - - atlas-stop - 31001 - ${jetty-maven-plugin.stopWait} - ${debug.jetty.daemon} - ${project.build.testOutputDirectory} - true - jar - - - - org.apache.curator - curator-client - ${curator.version} - - - - org.apache.zookeeper - zookeeper - ${zookeeper.version} - - - - - start-jetty - pre-integration-test - - - stop - deploy-war - - - - stop-jetty - post-integration-test - - stop - - - - - - - org.apache.maven.plugins - maven-site-plugin - - - org.apache.maven.doxia - doxia-module-twiki - ${doxia.version} - - - org.apache.maven.doxia - doxia-core - ${doxia.version} - - - - - - site - - prepare-package - - - - false - false - - - - - org.codehaus.mojo - exec-maven-plugin - 1.2.1 - false - - - - - - org.apache.maven.plugins - maven-resources-plugin - - - copy-resources - validate - - copy-resources - - - ${basedir}/target/models - - - ${basedir}/../models - - 0000-Area0/0010-base_model.json - 1000-Hadoop/** - - - - - - - copy-solr-resources - validate - - copy-resources - - - ${project.build.directory}/solr - - - ${basedir}/../../test-tools/src/main/resources/solr - - - - - - - - - - diff --git a/addons/hive-bridge/src/bin/import-hive.sh b/addons/hive-bridge/src/bin/import-hive.sh deleted file mode 100755 index ebe6976f0ef..00000000000 --- a/addons/hive-bridge/src/bin/import-hive.sh +++ /dev/null @@ -1,173 +0,0 @@ -#!/bin/bash -# -# 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. See accompanying LICENSE file. -# -# resolve links - $0 may be a softlink -PRG="${0}" - -[[ `uname -s` == *"CYGWIN"* ]] && CYGWIN=true - -while [ -h "${PRG}" ]; do - ls=`ls -ld "${PRG}"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "${PRG}"`/"$link" - fi -done - -BASEDIR=`dirname ${PRG}` -BASEDIR=`cd ${BASEDIR}/..;pwd` - -if test -z "${JAVA_HOME}" -then - JAVA_BIN=`which java` - JAR_BIN=`which jar` -else - JAVA_BIN="${JAVA_HOME}/bin/java" - JAR_BIN="${JAVA_HOME}/bin/jar" -fi -export JAVA_BIN - -if [ ! -e "${JAVA_BIN}" ] || [ ! -e "${JAR_BIN}" ]; then - echo "$JAVA_BIN and/or $JAR_BIN not found on the system. Please make sure java and jar commands are available." - exit 1 -fi - -# Construct Atlas classpath using jars from hook/hive/atlas-hive-plugin-impl/ directory. -for i in "${BASEDIR}/hook/hive/atlas-hive-plugin-impl/"*.jar; do - ATLASCPPATH="${ATLASCPPATH}:$i" -done - -if [ -z "${ATLAS_CONF_DIR}" ] && [ -e /etc/atlas/conf ];then - ATLAS_CONF_DIR=/etc/atlas/conf -fi -ATLASCPPATH=${ATLASCPPATH}:${ATLAS_CONF_DIR} - -# log dir for applications -ATLAS_LOG_DIR="${ATLAS_LOG_DIR:-/var/log/atlas}" -export ATLAS_LOG_DIR -LOGFILE="$ATLAS_LOG_DIR/import-hive.log" - -TIME=`date +%Y%m%d%H%M%s` - -#Add hive conf in classpath -if [ ! -z "$HIVE_CONF_DIR" ]; then - HIVE_CONF=$HIVE_CONF_DIR -elif [ ! -z "$HIVE_HOME" ]; then - HIVE_CONF="$HIVE_HOME/conf" -elif [ -e /etc/hive/conf ]; then - HIVE_CONF="/etc/hive/conf" -else - echo "Could not find a valid HIVE configuration" - exit 1 -fi - -echo Using Hive configuration directory ["$HIVE_CONF"] - - -if [ -f "${HIVE_CONF}/hive-env.sh" ]; then - . "${HIVE_CONF}/hive-env.sh" -fi - -if [ -z "$HIVE_HOME" ]; then - if [ -d "${BASEDIR}/../hive" ]; then - HIVE_HOME=${BASEDIR}/../hive - else - echo "Please set HIVE_HOME to the root of Hive installation" - exit 1 - fi -fi - -HIVE_CP="${HIVE_CONF}" -# Multiple jars in HIVE_CP_EXCLUDE_LIST can be added using "\|" separator -# Ex: HIVE_CP_EXCLUDE_LIST="javax.ws.rs-api\|jersey-multipart" -# exclude log4j libs from hive classpath to avoid conflict -HIVE_CP_EXCLUDE_LIST="javax.ws.rs-api\|log4j-slf4j-impl\|log4j-1.2-api\|log4j-api\|log4j-core\|log4j-web" - -for i in $(find "${HIVE_HOME}/lib/" -name "*.jar" | grep -v "$HIVE_CP_EXCLUDE_LIST"); do - HIVE_CP="${HIVE_CP}:$i" -done - -#Add hadoop conf in classpath -if [ ! -z "$HADOOP_CLASSPATH" ]; then - HADOOP_CP=$HADOOP_CLASSPATH -elif [ ! -z "$HADOOP_HOME" ]; then - HADOOP_CP=`$HADOOP_HOME/bin/hadoop classpath` -elif [ $(command -v hadoop) ]; then - HADOOP_CP=`hadoop classpath` - echo $HADOOP_CP -else - echo "Environment variable HADOOP_CLASSPATH or HADOOP_HOME need to be set" - exit 1 -fi - -CP="${HIVE_CP}:${HADOOP_CP}:${ATLASCPPATH}" - -# If running in cygwin, convert pathnames and classpath to Windows format. -if [ "${CYGWIN}" == "true" ] -then - ATLAS_LOG_DIR=`cygpath -w ${ATLAS_LOG_DIR}` - LOGFILE=`cygpath -w ${LOGFILE}` - HIVE_CP=`cygpath -w ${HIVE_CP}` - HADOOP_CP=`cygpath -w ${HADOOP_CP}` - CP=`cygpath -w -p ${CP}` -fi - -JAVA_PROPERTIES="$ATLAS_OPTS -Datlas.log.dir=$ATLAS_LOG_DIR -Datlas.log.file=import-hive.log --Dlog4j.configuration=atlas-hive-import-log4j.xml" - -IMPORT_ARGS= -JVM_ARGS= - -while true -do - option=$1 - shift - - case "$option" in - -d) IMPORT_ARGS="$IMPORT_ARGS -d $1"; shift;; - -t) IMPORT_ARGS="$IMPORT_ARGS -t $1"; shift;; - -f) IMPORT_ARGS="$IMPORT_ARGS -f $1"; shift;; - -o) IMPORT_ARGS="$IMPORT_ARGS -o $1"; shift;; - -i) IMPORT_ARGS="$IMPORT_ARGS -i";; - -h) export HELP_OPTION="true"; IMPORT_ARGS="$IMPORT_ARGS -h";; - --database) IMPORT_ARGS="$IMPORT_ARGS --database $1"; shift;; - --table) IMPORT_ARGS="$IMPORT_ARGS --table $1"; shift;; - --filename) IMPORT_ARGS="$IMPORT_ARGS --filename $1"; shift;; - --output) IMPORT_ARGS="$IMPORT_ARGS --output $1"; shift;; - --ignoreBulkImport) IMPORT_ARGS="$IMPORT_ARGS --ignoreBulkImport";; - --help) export HELP_OPTION="true"; IMPORT_ARGS="$IMPORT_ARGS --help";; - -deleteNonExisting) IMPORT_ARGS="$IMPORT_ARGS -deleteNonExisting";; - "") break;; - *) IMPORT_ARGS="$IMPORT_ARGS $option" - esac -done - -JAVA_PROPERTIES="${JAVA_PROPERTIES} ${JVM_ARGS}" - -if [ -z ${HELP_OPTION} ]; then - echo "Log file for import is $LOGFILE" -fi - -"${JAVA_BIN}" ${JAVA_PROPERTIES} -cp "${CP}" org.apache.atlas.hive.bridge.HiveMetaStoreBridge $IMPORT_ARGS - -RETVAL=$? -if [ -z ${HELP_OPTION} ]; then - [ $RETVAL -eq 0 ] && echo Hive Meta Data imported successfully! - [ $RETVAL -eq 1 ] && echo Failed to import Hive Meta Data! Check logs at: $LOGFILE for details. -fi - -exit $RETVAL - diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridge.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridge.java deleted file mode 100755 index 28365bc5c31..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridge.java +++ /dev/null @@ -1,1264 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.bridge; - -import com.google.common.annotations.VisibleForTesting; -import com.sun.jersey.api.client.ClientResponse; -import org.apache.atlas.type.AtlasTypeUtil; -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.AtlasServiceException; -import org.apache.atlas.hive.hook.events.BaseHiveEvent; -import org.apache.atlas.hive.model.HiveDataTypes; -import org.apache.atlas.hook.AtlasHookException; -import org.apache.atlas.model.discovery.AtlasSearchResult; -import org.apache.atlas.model.discovery.SearchParameters; -import org.apache.atlas.model.instance.AtlasEntityHeader; -import org.apache.atlas.model.instance.EntityMutationResponse; -import org.apache.atlas.model.instance.EntityMutations; -import org.apache.atlas.utils.AtlasPathExtractorUtil; -import org.apache.atlas.utils.AuthenticationUtil; -import org.apache.atlas.utils.HdfsNameServiceResolver; -import org.apache.atlas.utils.AtlasConfigurationUtil; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.model.instance.AtlasStruct; -import org.apache.atlas.utils.PathExtractorContext; - -import org.apache.commons.cli.BasicParser; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; -import org.apache.commons.cli.HelpFormatter; -import org.apache.commons.cli.MissingArgumentException; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections.MapUtils; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.RandomStringUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.hive.conf.HiveConf; -import org.apache.hadoop.hive.metastore.TableType; -import org.apache.hadoop.hive.metastore.api.Database; -import org.apache.hadoop.hive.metastore.api.FieldSchema; -import org.apache.hadoop.hive.metastore.api.Order; -import org.apache.hadoop.hive.metastore.api.SerDeInfo; -import org.apache.hadoop.hive.metastore.api.StorageDescriptor; -import org.apache.hadoop.hive.ql.metadata.Hive; -import org.apache.hadoop.hive.ql.metadata.HiveException; -import org.apache.hadoop.hive.ql.metadata.InvalidTableException; -import org.apache.hadoop.hive.ql.metadata.Table; -import org.apache.hadoop.hive.ql.session.SessionState; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import static org.apache.atlas.hive.hook.events.BaseHiveEvent.*; - -/** - * A Bridge Utility that imports metadata from the Hive Meta Store - * and registers them in Atlas. - */ - -public class HiveMetaStoreBridge { - private static final Logger LOG = LoggerFactory.getLogger(HiveMetaStoreBridge.class); - - public static final String CONF_PREFIX = "atlas.hook.hive."; - public static final String CLUSTER_NAME_KEY = "atlas.cluster.name"; - public static final String HIVE_USERNAME = "atlas.hook.hive.default.username"; - public static final String HIVE_METADATA_NAMESPACE = "atlas.metadata.namespace"; - public static final String HDFS_PATH_CONVERT_TO_LOWER_CASE = CONF_PREFIX + "hdfs_path.convert_to_lowercase"; - public static final String HOOK_AWS_S3_ATLAS_MODEL_VERSION = CONF_PREFIX + "aws_s3.atlas.model.version"; - public static final String DEFAULT_CLUSTER_NAME = "primary"; - public static final String TEMP_TABLE_PREFIX = "_temp-"; - public static final String ATLAS_ENDPOINT = "atlas.rest.address"; - public static final String SEP = ":".intern(); - public static final String HDFS_PATH = "hdfs_path"; - public static final String DEFAULT_METASTORE_CATALOG = "hive"; - public static final String HIVE_TABLE_DB_EDGE_LABEL = "__hive_table.db"; - public static final String HOOK_HIVE_PAGE_LIMIT = CONF_PREFIX + "page.limit"; - - static final String OPTION_OUTPUT_FILEPATH_SHORT = "o"; - static final String OPTION_OUTPUT_FILEPATH_LONG = "output"; - static final String OPTION_IGNORE_BULK_IMPORT_SHORT = "i"; - static final String OPTION_IGNORE_BULK_IMPORT_LONG = "ignoreBulkImport"; - static final String OPTION_DATABASE_SHORT = "d"; - static final String OPTION_DATABASE_LONG = "database"; - static final String OPTION_TABLE_SHORT = "t"; - static final String OPTION_TABLE_LONG = "table"; - static final String OPTION_IMPORT_DATA_FILE_SHORT = "f"; - static final String OPTION_IMPORT_DATA_FILE_LONG = "filename"; - static final String OPTION_FAIL_ON_ERROR = "failOnError"; - static final String OPTION_DELETE_NON_EXISTING = "deleteNonExisting"; - static final String OPTION_HELP_SHORT = "h"; - static final String OPTION_HELP_LONG = "help"; - - public static final String HOOK_AWS_S3_ATLAS_MODEL_VERSION_V2 = "v2"; - - private static final int EXIT_CODE_SUCCESS = 0; - private static final int EXIT_CODE_FAILED = 1; - private static final int EXIT_CODE_INVALID_ARG = 2; - - private static final String DEFAULT_ATLAS_URL = "http://localhost:21000/"; - private static int pageLimit = 10000; - - private final String metadataNamespace; - private final Hive hiveClient; - private final AtlasClientV2 atlasClientV2; - private final boolean convertHdfsPathToLowerCase; - - private String awsS3AtlasModelVersion = null; - - public static void main(String[] args) { - int exitCode = EXIT_CODE_FAILED; - AtlasClientV2 atlasClientV2 = null; - Options acceptedCliOptions = prepareCommandLineOptions(); - - try { - CommandLine cmd = new BasicParser().parse(acceptedCliOptions, args); - List argsNotProcessed = cmd.getArgList(); - - if (argsNotProcessed != null && argsNotProcessed.size() > 0) { - throw new ParseException("Unrecognized arguments."); - } - - if (cmd.hasOption(OPTION_HELP_SHORT)) { - printUsage(acceptedCliOptions); - exitCode = EXIT_CODE_SUCCESS; - } else { - Configuration atlasConf = ApplicationProperties.get(); - String[] atlasEndpoint = atlasConf.getStringArray(ATLAS_ENDPOINT); - - if (atlasEndpoint == null || atlasEndpoint.length == 0) { - atlasEndpoint = new String[] { DEFAULT_ATLAS_URL }; - } - - if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { - String[] basicAuthUsernamePassword = AuthenticationUtil.getBasicAuthenticationInput(); - - atlasClientV2 = new AtlasClientV2(atlasEndpoint, basicAuthUsernamePassword); - } else { - UserGroupInformation ugi = UserGroupInformation.getCurrentUser(); - - atlasClientV2 = new AtlasClientV2(ugi, ugi.getShortUserName(), atlasEndpoint); - } - - boolean createZip = cmd.hasOption(OPTION_OUTPUT_FILEPATH_LONG); - - if (createZip) { - HiveMetaStoreBridgeV2 hiveMetaStoreBridgeV2 = new HiveMetaStoreBridgeV2(atlasConf, new HiveConf(), atlasClientV2); - - if (hiveMetaStoreBridgeV2.exportDataToZipAndRunAtlasImport(cmd)) { - exitCode = EXIT_CODE_SUCCESS; - } - } else { - HiveMetaStoreBridge hiveMetaStoreBridge = new HiveMetaStoreBridge(atlasConf, new HiveConf(), atlasClientV2); - - if (hiveMetaStoreBridge.importDataDirectlyToAtlas(cmd)) { - exitCode = EXIT_CODE_SUCCESS; - } - } - } - } catch(ParseException e) { - LOG.error("Invalid argument. Error: {}", e.getMessage()); - System.out.println("Invalid argument. Error: " + e.getMessage()); - exitCode = EXIT_CODE_INVALID_ARG; - - if (!(e instanceof MissingArgumentException)) { - printUsage(acceptedCliOptions); - } - } catch(Exception e) { - LOG.error("Import Failed", e); - } finally { - if( atlasClientV2 !=null) { - atlasClientV2.close(); - } - } - - System.exit(exitCode); - } - - private static Options prepareCommandLineOptions() { - Options acceptedCliOptions = new Options(); - - return acceptedCliOptions.addOption(OPTION_OUTPUT_FILEPATH_SHORT, OPTION_OUTPUT_FILEPATH_LONG, true, "Output path or file for Zip import") - .addOption(OPTION_IGNORE_BULK_IMPORT_SHORT, OPTION_IGNORE_BULK_IMPORT_LONG, false, "Ignore bulk Import for Zip import") - .addOption(OPTION_DATABASE_SHORT, OPTION_DATABASE_LONG, true, "Database name") - .addOption(OPTION_TABLE_SHORT, OPTION_TABLE_LONG, true, "Table name") - .addOption(OPTION_IMPORT_DATA_FILE_SHORT, OPTION_IMPORT_DATA_FILE_LONG, true, "Filename") - .addOption(OPTION_FAIL_ON_ERROR, false, "failOnError") - .addOption(OPTION_DELETE_NON_EXISTING, false, "Delete database and table entities in Atlas if not present in Hive") - .addOption(OPTION_HELP_SHORT, OPTION_HELP_LONG, false, "Print this help message"); - } - - private static void printUsage(Options options) { - HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp("import-hive.sh", options); - System.out.println(); - System.out.println("Usage options:"); - System.out.println(" Usage 1: import-hive.sh [-d OR --database ] " ); - System.out.println(" Imports specified database and its tables ..."); - System.out.println(); - System.out.println(" Usage 2: import-hive.sh [-d OR --database ] [-t

OR --table
]"); - System.out.println(" Imports specified table within that database ..."); - System.out.println(); - System.out.println(" Usage 3: import-hive.sh"); - System.out.println(" Imports all databases and tables..."); - System.out.println(); - System.out.println(" Usage 4: import-hive.sh -f "); - System.out.println(" Imports all databases and tables in the file..."); - System.out.println(" Format:"); - System.out.println(" database1:tbl1"); - System.out.println(" database1:tbl2"); - System.out.println(" database2:tbl2"); - System.out.println(); - System.out.println(" Usage 5: import-hive.sh [-deleteNonExisting] " ); - System.out.println(" Deletes databases and tables which are not in Hive ..."); - System.out.println(); - System.out.println(" Usage 6: import-hive.sh -o [-f ] [-d OR --database ] [-t
OR --table
]"); - System.out.println(" To create zip file with exported data and import the zip file at Atlas ..."); - System.out.println(); - System.out.println(" Usage 7: import-hive.sh -i -o [-f ] [-d OR --database ] [-t
OR --table
]"); - System.out.println(" To create zip file with exported data without importing to Atlas which can be imported later ..."); - System.out.println(); - } - - /** - * Construct a HiveMetaStoreBridge. - * @param hiveConf {@link HiveConf} for Hive component in the cluster - */ - public HiveMetaStoreBridge(Configuration atlasProperties, HiveConf hiveConf, AtlasClientV2 atlasClientV2) throws Exception { - this.metadataNamespace = getMetadataNamespace(atlasProperties); - this.hiveClient = Hive.get(hiveConf); - this.atlasClientV2 = atlasClientV2; - this.convertHdfsPathToLowerCase = atlasProperties.getBoolean(HDFS_PATH_CONVERT_TO_LOWER_CASE, false); - this.awsS3AtlasModelVersion = atlasProperties.getString(HOOK_AWS_S3_ATLAS_MODEL_VERSION, HOOK_AWS_S3_ATLAS_MODEL_VERSION_V2); - if (atlasProperties != null) { - pageLimit = atlasProperties.getInteger(HOOK_HIVE_PAGE_LIMIT, 10000); - } - } - - /** - * Construct a HiveMetaStoreBridge. - * @param hiveConf {@link HiveConf} for Hive component in the cluster - */ - public HiveMetaStoreBridge(Configuration atlasProperties, HiveConf hiveConf) throws Exception { - this(atlasProperties, hiveConf, null); - } - - HiveMetaStoreBridge(String metadataNamespace, Hive hiveClient, AtlasClientV2 atlasClientV2) { - this(metadataNamespace, hiveClient, atlasClientV2, true); - } - - HiveMetaStoreBridge(String metadataNamespace, Hive hiveClient, AtlasClientV2 atlasClientV2, boolean convertHdfsPathToLowerCase) { - this.metadataNamespace = metadataNamespace; - this.hiveClient = hiveClient; - this.atlasClientV2 = atlasClientV2; - this.convertHdfsPathToLowerCase = convertHdfsPathToLowerCase; - } - - public String getMetadataNamespace(Configuration config) { - return AtlasConfigurationUtil.getRecentString(config, HIVE_METADATA_NAMESPACE, getClusterName(config)); - } - - private String getClusterName(Configuration config) { - return config.getString(CLUSTER_NAME_KEY, DEFAULT_CLUSTER_NAME); - } - - public String getMetadataNamespace() { - return metadataNamespace; - } - - public Hive getHiveClient() { - return hiveClient; - } - - public boolean isConvertHdfsPathToLowerCase() { - return convertHdfsPathToLowerCase; - } - - public boolean importDataDirectlyToAtlas(CommandLine cmd) throws Exception { - LOG.info("Importing Hive metadata"); - boolean ret = false; - - String databaseToImport = cmd.getOptionValue(OPTION_DATABASE_SHORT); - String tableToImport = cmd.getOptionValue(OPTION_TABLE_SHORT); - String fileToImport = cmd.getOptionValue(OPTION_IMPORT_DATA_FILE_SHORT); - - boolean failOnError = cmd.hasOption(OPTION_FAIL_ON_ERROR); - boolean deleteNonExisting = cmd.hasOption(OPTION_DELETE_NON_EXISTING); - - LOG.info("delete non existing flag : {} ", deleteNonExisting); - - if (deleteNonExisting) { - deleteEntitiesForNonExistingHiveMetadata(failOnError); - ret = true; - } else if (StringUtils.isNotEmpty(fileToImport)) { - File f = new File(fileToImport); - - if (f.exists() && f.canRead()) { - BufferedReader br = new BufferedReader(new FileReader(f)); - String line = null; - - while((line = br.readLine()) != null) { - String val[] = line.split(":"); - - if (ArrayUtils.isNotEmpty(val)) { - databaseToImport = val[0]; - - if (val.length > 1) { - tableToImport = val[1]; - } else { - tableToImport = ""; - } - - importDatabases(failOnError, databaseToImport, tableToImport); - } - } - ret = true; - } else { - LOG.error("Failed to read the input file: " + fileToImport); - } - } else { - importDatabases(failOnError, databaseToImport, tableToImport); - ret = true; - } - return ret; - } - - @VisibleForTesting - public void importHiveMetadata(String databaseToImport, String tableToImport, boolean failOnError) throws Exception { - LOG.info("Importing Hive metadata"); - - importDatabases(failOnError, databaseToImport, tableToImport); - } - - private void importDatabases(boolean failOnError, String databaseToImport, String tableToImport) throws Exception { - List databaseNames = null; - - if (StringUtils.isEmpty(databaseToImport) && StringUtils.isEmpty(tableToImport)) { - //when both database and table to import are empty, import all - databaseNames = hiveClient.getAllDatabases(); - } else if (StringUtils.isEmpty(databaseToImport) && StringUtils.isNotEmpty(tableToImport)) { - //when database is empty and table is not, then check table has database name in it and import that db and table - if (isTableWithDatabaseName(tableToImport)) { - String val[] = tableToImport.split("\\."); - if (val.length > 1) { - databaseToImport = val[0]; - tableToImport = val[1]; - } - databaseNames = hiveClient.getDatabasesByPattern(databaseToImport); - } else { - databaseNames = hiveClient.getAllDatabases(); - } - } else { - //when database to import has some value then, import that db and all table under it. - databaseNames = hiveClient.getDatabasesByPattern(databaseToImport); - } - - if(!CollectionUtils.isEmpty(databaseNames)) { - LOG.info("Found {} databases", databaseNames.size()); - - for (String databaseName : databaseNames) { - AtlasEntityWithExtInfo dbEntity = registerDatabase(databaseName); - - if (dbEntity != null) { - importTables(dbEntity.getEntity(), databaseName, tableToImport, failOnError); - } - } - } else { - LOG.error("No database found"); - System.exit(EXIT_CODE_FAILED); - } - } - - /** - * Imports all tables for the given db - * @param dbEntity - * @param databaseName - * @param failOnError - * @throws Exception - */ - private int importTables(AtlasEntity dbEntity, String databaseName, String tblName, final boolean failOnError) throws Exception { - int tablesImported = 0; - - final List tableNames; - - if (StringUtils.isEmpty(tblName)) { - tableNames = hiveClient.getAllTables(databaseName); - } else { - tableNames = hiveClient.getTablesByPattern(databaseName, tblName); - } - - if(!CollectionUtils.isEmpty(tableNames)) { - LOG.info("Found {} tables to import in database {}", tableNames.size(), databaseName); - - try { - for (String tableName : tableNames) { - int imported = importTable(dbEntity, databaseName, tableName, failOnError); - - tablesImported += imported; - } - } finally { - if (tablesImported == tableNames.size()) { - LOG.info("Successfully imported {} tables from database {}", tablesImported, databaseName); - } else { - LOG.error("Imported {} of {} tables from database {}. Please check logs for errors during import", tablesImported, tableNames.size(), databaseName); - } - } - } else { - LOG.error("No tables to import in database {}", databaseName); - } - - return tablesImported; - } - - @VisibleForTesting - public int importTable(AtlasEntity dbEntity, String databaseName, String tableName, final boolean failOnError) throws Exception { - try { - Table table = hiveClient.getTable(databaseName, tableName); - AtlasEntityWithExtInfo tableEntity = registerTable(dbEntity, table); - - if (table.getTableType() == TableType.EXTERNAL_TABLE) { - String processQualifiedName = getTableProcessQualifiedName(metadataNamespace, table); - AtlasEntityWithExtInfo processEntity = findProcessEntity(processQualifiedName); - - if (processEntity == null) { - String tableLocationString = isConvertHdfsPathToLowerCase() ? lower(table.getDataLocation().toString()) : table.getDataLocation().toString(); - Path location = table.getDataLocation(); - String query = getCreateTableString(table, tableLocationString); - - PathExtractorContext pathExtractorCtx = new PathExtractorContext(getMetadataNamespace(), isConvertHdfsPathToLowerCase(), awsS3AtlasModelVersion); - AtlasEntityWithExtInfo entityWithExtInfo = AtlasPathExtractorUtil.getPathEntity(location, pathExtractorCtx); - AtlasEntity pathInst = entityWithExtInfo.getEntity(); - AtlasEntity tableInst = tableEntity.getEntity(); - AtlasEntity processInst = new AtlasEntity(HiveDataTypes.HIVE_PROCESS.getName()); - - long now = System.currentTimeMillis(); - - processInst.setAttribute(ATTRIBUTE_QUALIFIED_NAME, processQualifiedName); - processInst.setAttribute(ATTRIBUTE_NAME, query); - processInst.setAttribute(ATTRIBUTE_CLUSTER_NAME, metadataNamespace); - processInst.setRelationshipAttribute(ATTRIBUTE_INPUTS, Collections.singletonList(AtlasTypeUtil.getAtlasRelatedObjectId(pathInst, RELATIONSHIP_DATASET_PROCESS_INPUTS))); - processInst.setRelationshipAttribute(ATTRIBUTE_OUTPUTS, Collections.singletonList(AtlasTypeUtil.getAtlasRelatedObjectId(tableInst, RELATIONSHIP_PROCESS_DATASET_OUTPUTS))); - String userName = table.getOwner(); - if (StringUtils.isEmpty(userName)) { - userName = ApplicationProperties.get().getString(HIVE_USERNAME, "hive"); - } - processInst.setAttribute(ATTRIBUTE_USER_NAME, userName); - processInst.setAttribute(ATTRIBUTE_START_TIME, now); - processInst.setAttribute(ATTRIBUTE_END_TIME, now); - processInst.setAttribute(ATTRIBUTE_OPERATION_TYPE, "CREATETABLE"); - processInst.setAttribute(ATTRIBUTE_QUERY_TEXT, query); - processInst.setAttribute(ATTRIBUTE_QUERY_ID, query); - processInst.setAttribute(ATTRIBUTE_QUERY_PLAN, "{}"); - processInst.setAttribute(ATTRIBUTE_RECENT_QUERIES, Collections.singletonList(query)); - - AtlasEntitiesWithExtInfo createTableProcess = new AtlasEntitiesWithExtInfo(); - - createTableProcess.addEntity(processInst); - - if (pathExtractorCtx.getKnownEntities() != null) { - pathExtractorCtx.getKnownEntities().values().forEach(entity -> createTableProcess.addEntity(entity)); - } else { - createTableProcess.addEntity(pathInst); - } - - registerInstances(createTableProcess); - } else { - LOG.info("Process {} is already registered", processQualifiedName); - } - } - - return 1; - } catch (Exception e) { - LOG.error("Import failed for hive_table {}", tableName, e); - - if (failOnError) { - throw e; - } - - return 0; - } - } - - /** - * Checks if db is already registered, else creates and registers db entity - * @param databaseName - * @return - * @throws Exception - */ - private AtlasEntityWithExtInfo registerDatabase(String databaseName) throws Exception { - AtlasEntityWithExtInfo ret = null; - Database db = hiveClient.getDatabase(databaseName); - - if (db != null) { - ret = findDatabase(metadataNamespace, databaseName); - - if (ret == null) { - ret = registerInstance(new AtlasEntityWithExtInfo(toDbEntity(db))); - } else { - LOG.info("Database {} is already registered - id={}. Updating it.", databaseName, ret.getEntity().getGuid()); - - ret.setEntity(toDbEntity(db, ret.getEntity())); - - updateInstance(ret); - } - } - - return ret; - } - - private AtlasEntityWithExtInfo registerTable(AtlasEntity dbEntity, Table table) throws AtlasHookException { - try { - AtlasEntityWithExtInfo ret; - AtlasEntityWithExtInfo tableEntity = findTableEntity(table); - - if (tableEntity == null) { - tableEntity = toTableEntity(dbEntity, table); - - ret = registerInstance(tableEntity); - } else { - LOG.info("Table {}.{} is already registered with id {}. Updating entity.", table.getDbName(), table.getTableName(), tableEntity.getEntity().getGuid()); - - ret = toTableEntity(dbEntity, table, tableEntity); - - updateInstance(ret); - } - - return ret; - } catch (Exception e) { - throw new AtlasHookException("HiveMetaStoreBridge.registerTable() failed.", e); - } - } - - /** - * Registers an entity in atlas - * @param entity - * @return - * @throws Exception - */ - private AtlasEntityWithExtInfo registerInstance(AtlasEntityWithExtInfo entity) throws Exception { - if (LOG.isDebugEnabled()) { - LOG.debug("creating {} entity: {}", entity.getEntity().getTypeName(), entity); - } - - AtlasEntityWithExtInfo ret = null; - EntityMutationResponse response = atlasClientV2.createEntity(entity); - List createdEntities = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE); - - if (CollectionUtils.isNotEmpty(createdEntities)) { - for (AtlasEntityHeader createdEntity : createdEntities) { - if (ret == null) { - ret = atlasClientV2.getEntityByGuid(createdEntity.getGuid()); - - LOG.info("Created {} entity: name={}, guid={}", ret.getEntity().getTypeName(), ret.getEntity().getAttribute(ATTRIBUTE_QUALIFIED_NAME), ret.getEntity().getGuid()); - } else if (ret.getEntity(createdEntity.getGuid()) == null) { - AtlasEntityWithExtInfo newEntity = atlasClientV2.getEntityByGuid(createdEntity.getGuid()); - - ret.addReferredEntity(newEntity.getEntity()); - - if (MapUtils.isNotEmpty(newEntity.getReferredEntities())) { - for (Map.Entry entry : newEntity.getReferredEntities().entrySet()) { - ret.addReferredEntity(entry.getKey(), entry.getValue()); - } - } - - LOG.info("Created {} entity: name={}, guid={}", newEntity.getEntity().getTypeName(), newEntity.getEntity().getAttribute(ATTRIBUTE_QUALIFIED_NAME), newEntity.getEntity().getGuid()); - } - } - } - - clearRelationshipAttributes(ret); - - return ret; - } - - /** - * Registers an entity in atlas - * @param entities - * @return - * @throws Exception - */ - private AtlasEntitiesWithExtInfo registerInstances(AtlasEntitiesWithExtInfo entities) throws Exception { - if (LOG.isDebugEnabled()) { - LOG.debug("creating {} entities: {}", entities.getEntities().size(), entities); - } - - AtlasEntitiesWithExtInfo ret = null; - EntityMutationResponse response = atlasClientV2.createEntities(entities); - List createdEntities = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE); - - if (CollectionUtils.isNotEmpty(createdEntities)) { - ret = new AtlasEntitiesWithExtInfo(); - - for (AtlasEntityHeader createdEntity : createdEntities) { - AtlasEntityWithExtInfo entity = atlasClientV2.getEntityByGuid(createdEntity.getGuid()); - - ret.addEntity(entity.getEntity()); - - if (MapUtils.isNotEmpty(entity.getReferredEntities())) { - for (Map.Entry entry : entity.getReferredEntities().entrySet()) { - ret.addReferredEntity(entry.getKey(), entry.getValue()); - } - } - - LOG.info("Created {} entity: name={}, guid={}", entity.getEntity().getTypeName(), entity.getEntity().getAttribute(ATTRIBUTE_QUALIFIED_NAME), entity.getEntity().getGuid()); - } - } - - clearRelationshipAttributes(ret); - - return ret; - } - - private void updateInstance(AtlasEntityWithExtInfo entity) throws AtlasServiceException { - if (LOG.isDebugEnabled()) { - LOG.debug("updating {} entity: {}", entity.getEntity().getTypeName(), entity); - } - - atlasClientV2.updateEntity(entity); - - LOG.info("Updated {} entity: name={}, guid={}", entity.getEntity().getTypeName(), entity.getEntity().getAttribute(ATTRIBUTE_QUALIFIED_NAME), entity.getEntity().getGuid()); - } - - /** - * Create a Hive Database entity - * @param hiveDB The Hive {@link Database} object from which to map properties - * @return new Hive Database AtlasEntity - * @throws HiveException - */ - private AtlasEntity toDbEntity(Database hiveDB) throws HiveException { - return toDbEntity(hiveDB, null); - } - - private AtlasEntity toDbEntity(Database hiveDB, AtlasEntity dbEntity) { - if (dbEntity == null) { - dbEntity = new AtlasEntity(HiveDataTypes.HIVE_DB.getName()); - } - - String dbName = getDatabaseName(hiveDB); - - dbEntity.setAttribute(ATTRIBUTE_QUALIFIED_NAME, getDBQualifiedName(metadataNamespace, dbName)); - dbEntity.setAttribute(ATTRIBUTE_NAME, dbName); - dbEntity.setAttribute(ATTRIBUTE_DESCRIPTION, hiveDB.getDescription()); - dbEntity.setAttribute(ATTRIBUTE_OWNER, hiveDB.getOwnerName()); - - dbEntity.setAttribute(ATTRIBUTE_CLUSTER_NAME, metadataNamespace); - dbEntity.setAttribute(ATTRIBUTE_LOCATION, HdfsNameServiceResolver.getPathWithNameServiceID(hiveDB.getLocationUri())); - dbEntity.setAttribute(ATTRIBUTE_PARAMETERS, hiveDB.getParameters()); - - if (hiveDB.getOwnerType() != null) { - dbEntity.setAttribute(ATTRIBUTE_OWNER_TYPE, OWNER_TYPE_TO_ENUM_VALUE.get(hiveDB.getOwnerType().getValue())); - } - - return dbEntity; - } - - public static String getDatabaseName(Database hiveDB) { - String dbName = hiveDB.getName().toLowerCase(); - String catalogName = hiveDB.getCatalogName() != null ? hiveDB.getCatalogName().toLowerCase() : null; - - if (StringUtils.isNotEmpty(catalogName) && !StringUtils.equals(catalogName, DEFAULT_METASTORE_CATALOG)) { - dbName = catalogName + SEP + dbName; - } - - return dbName; - } - - /** - * Create a new table instance in Atlas - * @param database AtlasEntity for Hive {@link AtlasEntity} to which this table belongs - * @param hiveTable reference to the Hive {@link Table} from which to map properties - * @return Newly created Hive AtlasEntity - * @throws Exception - */ - private AtlasEntityWithExtInfo toTableEntity(AtlasEntity database, Table hiveTable) throws AtlasHookException { - return toTableEntity(database, hiveTable, null); - } - - private AtlasEntityWithExtInfo toTableEntity(AtlasEntity database, final Table hiveTable, AtlasEntityWithExtInfo table) throws AtlasHookException { - if (table == null) { - table = new AtlasEntityWithExtInfo(new AtlasEntity(HiveDataTypes.HIVE_TABLE.getName())); - } - - AtlasEntity tableEntity = table.getEntity(); - String tableQualifiedName = getTableQualifiedName(metadataNamespace, hiveTable); - long createTime = BaseHiveEvent.getTableCreateTime(hiveTable); - long lastAccessTime = hiveTable.getLastAccessTime() > 0 ? hiveTable.getLastAccessTime() : createTime; - - tableEntity.setRelationshipAttribute(ATTRIBUTE_DB, AtlasTypeUtil.getAtlasRelatedObjectId(database, RELATIONSHIP_HIVE_TABLE_DB)); - tableEntity.setAttribute(ATTRIBUTE_QUALIFIED_NAME, tableQualifiedName); - tableEntity.setAttribute(ATTRIBUTE_NAME, hiveTable.getTableName().toLowerCase()); - tableEntity.setAttribute(ATTRIBUTE_OWNER, hiveTable.getOwner()); - - tableEntity.setAttribute(ATTRIBUTE_CREATE_TIME, createTime); - tableEntity.setAttribute(ATTRIBUTE_LAST_ACCESS_TIME, lastAccessTime); - tableEntity.setAttribute(ATTRIBUTE_RETENTION, hiveTable.getRetention()); - tableEntity.setAttribute(ATTRIBUTE_PARAMETERS, hiveTable.getParameters()); - tableEntity.setAttribute(ATTRIBUTE_COMMENT, hiveTable.getParameters().get(ATTRIBUTE_COMMENT)); - tableEntity.setAttribute(ATTRIBUTE_TABLE_TYPE, hiveTable.getTableType().name()); - tableEntity.setAttribute(ATTRIBUTE_TEMPORARY, hiveTable.isTemporary()); - - if (hiveTable.getViewOriginalText() != null) { - tableEntity.setAttribute(ATTRIBUTE_VIEW_ORIGINAL_TEXT, hiveTable.getViewOriginalText()); - } - - if (hiveTable.getViewExpandedText() != null) { - tableEntity.setAttribute(ATTRIBUTE_VIEW_EXPANDED_TEXT, hiveTable.getViewExpandedText()); - } - - AtlasEntity sdEntity = toStorageDescEntity(hiveTable.getSd(), tableQualifiedName, getStorageDescQFName(tableQualifiedName), AtlasTypeUtil.getObjectId(tableEntity)); - List partKeys = toColumns(hiveTable.getPartitionKeys(), tableEntity, RELATIONSHIP_HIVE_TABLE_PART_KEYS); - List columns = toColumns(hiveTable.getCols(), tableEntity, RELATIONSHIP_HIVE_TABLE_COLUMNS); - - tableEntity.setRelationshipAttribute(ATTRIBUTE_STORAGEDESC, AtlasTypeUtil.getAtlasRelatedObjectId(sdEntity, RELATIONSHIP_HIVE_TABLE_STORAGE_DESC)); - tableEntity.setRelationshipAttribute(ATTRIBUTE_PARTITION_KEYS, AtlasTypeUtil.getAtlasRelatedObjectIds(partKeys, RELATIONSHIP_HIVE_TABLE_PART_KEYS)); - tableEntity.setRelationshipAttribute(ATTRIBUTE_COLUMNS, AtlasTypeUtil.getAtlasRelatedObjectIds(columns, RELATIONSHIP_HIVE_TABLE_COLUMNS)); - - table.addReferredEntity(database); - table.addReferredEntity(sdEntity); - - if (partKeys != null) { - for (AtlasEntity partKey : partKeys) { - table.addReferredEntity(partKey); - } - } - - if (columns != null) { - for (AtlasEntity column : columns) { - table.addReferredEntity(column); - } - } - - table.setEntity(tableEntity); - - return table; - } - - private AtlasEntity toStorageDescEntity(StorageDescriptor storageDesc, String tableQualifiedName, String sdQualifiedName, AtlasObjectId tableId ) throws AtlasHookException { - AtlasEntity ret = new AtlasEntity(HiveDataTypes.HIVE_STORAGEDESC.getName()); - - ret.setRelationshipAttribute(ATTRIBUTE_TABLE, AtlasTypeUtil.getAtlasRelatedObjectId(tableId, RELATIONSHIP_HIVE_TABLE_STORAGE_DESC)); - ret.setAttribute(ATTRIBUTE_QUALIFIED_NAME, sdQualifiedName); - ret.setAttribute(ATTRIBUTE_PARAMETERS, storageDesc.getParameters()); - ret.setAttribute(ATTRIBUTE_LOCATION, HdfsNameServiceResolver.getPathWithNameServiceID(storageDesc.getLocation())); - ret.setAttribute(ATTRIBUTE_INPUT_FORMAT, storageDesc.getInputFormat()); - ret.setAttribute(ATTRIBUTE_OUTPUT_FORMAT, storageDesc.getOutputFormat()); - ret.setAttribute(ATTRIBUTE_COMPRESSED, storageDesc.isCompressed()); - ret.setAttribute(ATTRIBUTE_NUM_BUCKETS, storageDesc.getNumBuckets()); - ret.setAttribute(ATTRIBUTE_STORED_AS_SUB_DIRECTORIES, storageDesc.isStoredAsSubDirectories()); - - if (storageDesc.getBucketCols().size() > 0) { - ret.setAttribute(ATTRIBUTE_BUCKET_COLS, storageDesc.getBucketCols()); - } - - if (storageDesc.getSerdeInfo() != null) { - SerDeInfo serdeInfo = storageDesc.getSerdeInfo(); - - LOG.debug("serdeInfo = {}", serdeInfo); - // SkewedInfo skewedInfo = storageDesc.getSkewedInfo(); - - AtlasStruct serdeInfoStruct = new AtlasStruct(HiveDataTypes.HIVE_SERDE.getName()); - - serdeInfoStruct.setAttribute(ATTRIBUTE_NAME, serdeInfo.getName()); - serdeInfoStruct.setAttribute(ATTRIBUTE_SERIALIZATION_LIB, serdeInfo.getSerializationLib()); - serdeInfoStruct.setAttribute(ATTRIBUTE_PARAMETERS, serdeInfo.getParameters()); - - ret.setAttribute(ATTRIBUTE_SERDE_INFO, serdeInfoStruct); - } - - if (CollectionUtils.isNotEmpty(storageDesc.getSortCols())) { - List sortColsStruct = new ArrayList<>(); - - for (Order sortcol : storageDesc.getSortCols()) { - String hiveOrderName = HiveDataTypes.HIVE_ORDER.getName(); - AtlasStruct colStruct = new AtlasStruct(hiveOrderName); - colStruct.setAttribute("col", sortcol.getCol()); - colStruct.setAttribute("order", sortcol.getOrder()); - - sortColsStruct.add(colStruct); - } - - ret.setAttribute(ATTRIBUTE_SORT_COLS, sortColsStruct); - } - - return ret; - } - - private List toColumns(List schemaList, AtlasEntity table, String relationshipType) throws AtlasHookException { - List ret = new ArrayList<>(); - - int columnPosition = 0; - for (FieldSchema fs : schemaList) { - LOG.debug("Processing field {}", fs); - - AtlasEntity column = new AtlasEntity(HiveDataTypes.HIVE_COLUMN.getName()); - - column.setRelationshipAttribute(ATTRIBUTE_TABLE, AtlasTypeUtil.getAtlasRelatedObjectId(table, relationshipType)); - column.setAttribute(ATTRIBUTE_QUALIFIED_NAME, getColumnQualifiedName((String) table.getAttribute(ATTRIBUTE_QUALIFIED_NAME), fs.getName())); - column.setAttribute(ATTRIBUTE_NAME, fs.getName()); - column.setAttribute(ATTRIBUTE_OWNER, table.getAttribute(ATTRIBUTE_OWNER)); - column.setAttribute(ATTRIBUTE_COL_TYPE, fs.getType()); - column.setAttribute(ATTRIBUTE_COL_POSITION, columnPosition++); - column.setAttribute(ATTRIBUTE_COMMENT, fs.getComment()); - - ret.add(column); - } - return ret; - } - - /** - * Gets the atlas entity for the database - * @param databaseName database Name - * @param metadataNamespace cluster name - * @return AtlasEntity for database if exists, else null - * @throws Exception - */ - private AtlasEntityWithExtInfo findDatabase(String metadataNamespace, String databaseName) throws Exception { - if (LOG.isDebugEnabled()) { - LOG.debug("Searching Atlas for database {}", databaseName); - } - - String typeName = HiveDataTypes.HIVE_DB.getName(); - - return findEntity(typeName, getDBQualifiedName(metadataNamespace, databaseName), true, true); - } - - /** - * Gets Atlas Entity for the table - * - * @param hiveTable - * @return table entity from Atlas if exists, else null - * @throws Exception - */ - private AtlasEntityWithExtInfo findTableEntity(Table hiveTable) throws Exception { - if (LOG.isDebugEnabled()) { - LOG.debug("Searching Atlas for table {}.{}", hiveTable.getDbName(), hiveTable.getTableName()); - } - - String typeName = HiveDataTypes.HIVE_TABLE.getName(); - String tblQualifiedName = getTableQualifiedName(getMetadataNamespace(), hiveTable.getDbName(), hiveTable.getTableName()); - - return findEntity(typeName, tblQualifiedName, true, true); - } - - private AtlasEntityWithExtInfo findProcessEntity(String qualifiedName) throws Exception{ - if (LOG.isDebugEnabled()) { - LOG.debug("Searching Atlas for process {}", qualifiedName); - } - - String typeName = HiveDataTypes.HIVE_PROCESS.getName(); - - return findEntity(typeName, qualifiedName , true , true); - } - - private AtlasEntityWithExtInfo findEntity(final String typeName, final String qualifiedName , boolean minExtInfo, boolean ignoreRelationship) throws AtlasServiceException { - AtlasEntityWithExtInfo ret = null; - - try { - ret = atlasClientV2.getEntityByAttribute(typeName, Collections.singletonMap(ATTRIBUTE_QUALIFIED_NAME, qualifiedName), minExtInfo, ignoreRelationship); - } catch (AtlasServiceException e) { - if(e.getStatus() == ClientResponse.Status.NOT_FOUND) { - return null; - } - - throw e; - } - - return ret; - } - - private String getCreateTableString(Table table, String location){ - String colString = ""; - List colList = table.getAllCols(); - - if (colList != null) { - for (FieldSchema col : colList) { - colString += col.getName() + " " + col.getType() + ","; - } - - if (colList.size() > 0) { - colString = colString.substring(0, colString.length() - 1); - colString = "(" + colString + ")"; - } - } - - String query = "create external table " + table.getTableName() + colString + " location '" + location + "'"; - - return query; - } - - private String lower(String str) { - if (StringUtils.isEmpty(str)) { - return ""; - } - - return str.toLowerCase().trim(); - } - - - /** - * Construct the qualified name used to uniquely identify a Table instance in Atlas. - * @param metadataNamespace Metadata namespace of the cluster to which the Hive component belongs - * @param table hive table for which the qualified name is needed - * @return Unique qualified name to identify the Table instance in Atlas. - */ - private static String getTableQualifiedName(String metadataNamespace, Table table) { - return getTableQualifiedName(metadataNamespace, table.getDbName(), table.getTableName(), table.isTemporary()); - } - - private String getHdfsPathQualifiedName(String hdfsPath) { - return String.format("%s@%s", hdfsPath, metadataNamespace); - } - - /** - * Construct the qualified name used to uniquely identify a Database instance in Atlas. - * @param metadataNamespace Name of the cluster to which the Hive component belongs - * @param dbName Name of the Hive database - * @return Unique qualified name to identify the Database instance in Atlas. - */ - public static String getDBQualifiedName(String metadataNamespace, String dbName) { - return String.format("%s@%s", dbName.toLowerCase(), metadataNamespace); - } - - /** - * Construct the qualified name used to uniquely identify a Table instance in Atlas. - * @param metadataNamespace Name of the cluster to which the Hive component belongs - * @param dbName Name of the Hive database to which the Table belongs - * @param tableName Name of the Hive table - * @param isTemporaryTable is this a temporary table - * @return Unique qualified name to identify the Table instance in Atlas. - */ - public static String getTableQualifiedName(String metadataNamespace, String dbName, String tableName, boolean isTemporaryTable) { - String tableTempName = tableName; - - if (isTemporaryTable) { - if (SessionState.get() != null && SessionState.get().getSessionId() != null) { - tableTempName = tableName + TEMP_TABLE_PREFIX + SessionState.get().getSessionId(); - } else { - tableTempName = tableName + TEMP_TABLE_PREFIX + RandomStringUtils.random(10); - } - } - - return String.format("%s.%s@%s", dbName.toLowerCase(), tableTempName.toLowerCase(), metadataNamespace); - } - - public static String getTableProcessQualifiedName(String metadataNamespace, Table table) { - String tableQualifiedName = getTableQualifiedName(metadataNamespace, table); - long createdTime = getTableCreatedTime(table); - - return tableQualifiedName + SEP + createdTime; - } - - - /** - * Construct the qualified name used to uniquely identify a Table instance in Atlas. - * @param metadataNamespace Metadata namespace of the cluster to which the Hive component belongs - * @param dbName Name of the Hive database to which the Table belongs - * @param tableName Name of the Hive table - * @return Unique qualified name to identify the Table instance in Atlas. - */ - public static String getTableQualifiedName(String metadataNamespace, String dbName, String tableName) { - return getTableQualifiedName(metadataNamespace, dbName, tableName, false); - } - public static String getStorageDescQFName(String tableQualifiedName) { - return tableQualifiedName + "_storage"; - } - - public static String getColumnQualifiedName(final String tableQualifiedName, final String colName) { - final String[] parts = tableQualifiedName.split("@"); - final String tableName = parts[0]; - final String metadataNamespace = parts[1]; - - return String.format("%s.%s@%s", tableName, colName.toLowerCase(), metadataNamespace); - } - - public static long getTableCreatedTime(Table table) { - return table.getTTable().getCreateTime() * MILLIS_CONVERT_FACTOR; - } - - private void clearRelationshipAttributes(AtlasEntitiesWithExtInfo entities) { - if (entities != null) { - if (entities.getEntities() != null) { - for (AtlasEntity entity : entities.getEntities()) { - clearRelationshipAttributes(entity);; - } - } - - if (entities.getReferredEntities() != null) { - clearRelationshipAttributes(entities.getReferredEntities().values()); - } - } - } - - private void clearRelationshipAttributes(AtlasEntityWithExtInfo entity) { - if (entity != null) { - clearRelationshipAttributes(entity.getEntity()); - - if (entity.getReferredEntities() != null) { - clearRelationshipAttributes(entity.getReferredEntities().values()); - } - } - } - - private void clearRelationshipAttributes(Collection entities) { - if (entities != null) { - for (AtlasEntity entity : entities) { - clearRelationshipAttributes(entity); - } - } - } - - private void clearRelationshipAttributes(AtlasEntity entity) { - if (entity != null && entity.getRelationshipAttributes() != null) { - entity.getRelationshipAttributes().clear(); - } - } - - private boolean isTableWithDatabaseName(String tableName) { - boolean ret = false; - if (tableName.contains(".")) { - ret = true; - } - return ret; - } - - private List getAllDatabaseInCluster() throws AtlasServiceException { - - List entities = new ArrayList<>(); - final int pageSize = pageLimit; - - SearchParameters.FilterCriteria fc = new SearchParameters.FilterCriteria(); - fc.setAttributeName(ATTRIBUTE_CLUSTER_NAME); - fc.setAttributeValue(metadataNamespace); - fc.setOperator(SearchParameters.Operator.EQ); - - for (int i = 0; ; i++) { - int offset = pageSize * i; - LOG.info("Retrieving databases: offset={}, pageSize={}", offset, pageSize); - - AtlasSearchResult searchResult = atlasClientV2.basicSearch(HIVE_TYPE_DB, fc,null, null, true, pageSize, offset); - - List entityHeaders = searchResult == null ? null : searchResult.getEntities(); - int dbCount = entityHeaders == null ? 0 : entityHeaders.size(); - - LOG.info("Retrieved {} databases of {} cluster", dbCount, metadataNamespace); - - if (dbCount > 0) { - entities.addAll(entityHeaders); - } - - if (dbCount < pageSize) { // last page - break; - } - } - - return entities; - } - - private List getAllTablesInDb(String databaseGuid) throws AtlasServiceException { - - List entities = new ArrayList<>(); - final int pageSize = pageLimit; - - for (int i = 0; ; i++) { - int offset = pageSize * i; - LOG.info("Retrieving tables: offset={}, pageSize={}", offset, pageSize); - - AtlasSearchResult searchResult = atlasClientV2.relationshipSearch(databaseGuid, HIVE_TABLE_DB_EDGE_LABEL, null, null, true, pageSize, offset); - - List entityHeaders = searchResult == null ? null : searchResult.getEntities(); - int tableCount = entityHeaders == null ? 0 : entityHeaders.size(); - - LOG.info("Retrieved {} tables of {} database", tableCount, databaseGuid); - - if (tableCount > 0) { - entities.addAll(entityHeaders); - } - - if (tableCount < pageSize) { // last page - break; - } - } - - return entities; - } - - public String getHiveDatabaseName(String qualifiedName) { - - if (StringUtils.isNotEmpty(qualifiedName)) { - String[] split = qualifiedName.split("@"); - if (split.length > 0) { - return split[0]; - } - } - return null; - } - - - public String getHiveTableName(String qualifiedName, boolean isTemporary) { - - if (StringUtils.isNotEmpty(qualifiedName)) { - String tableName = StringUtils.substringBetween(qualifiedName, ".", "@"); - if (!isTemporary) { - return tableName; - } else { - if (StringUtils.isNotEmpty(tableName)) { - String[] splitTemp = tableName.split(TEMP_TABLE_PREFIX); - if (splitTemp.length > 0) { - return splitTemp[0]; - } - } - } - } - return null; - } - - private void deleteByGuid(List guidTodelete) throws AtlasServiceException { - - if (CollectionUtils.isNotEmpty(guidTodelete)) { - - for (String guid : guidTodelete) { - EntityMutationResponse response = atlasClientV2.deleteEntityByGuid(guid); - - if (response.getDeletedEntities().size() < 1) { - LOG.info("Entity with guid : {} is not deleted", guid); - } else { - LOG.info("Entity with guid : {} is deleted", guid); - } - } - } else { - LOG.info("No Entity to delete from Atlas"); - } - } - - public void deleteEntitiesForNonExistingHiveMetadata(boolean failOnError) throws Exception { - - //fetch databases from Atlas - List dbs = null; - try { - dbs = getAllDatabaseInCluster(); - LOG.info("Total Databases in cluster {} : {} ", metadataNamespace, dbs.size()); - } catch (AtlasServiceException e) { - LOG.error("Failed to retrieve database entities for cluster {} from Atlas", metadataNamespace, e); - if (failOnError) { - throw e; - } - } - - if (CollectionUtils.isNotEmpty(dbs)) { - //iterate all dbs to check if exists in hive - for (AtlasEntityHeader db : dbs) { - - String dbGuid = db.getGuid(); - String hiveDbName = getHiveDatabaseName((String) db.getAttribute(ATTRIBUTE_QUALIFIED_NAME)); - - if (StringUtils.isEmpty(hiveDbName)) { - LOG.error("Failed to get database from qualifiedName: {}, guid: {} ", db.getAttribute(ATTRIBUTE_QUALIFIED_NAME), dbGuid); - continue; - } - - List tables; - try { - tables = getAllTablesInDb(dbGuid); - LOG.info("Total Tables in database {} : {} ", hiveDbName, tables.size()); - } catch (AtlasServiceException e) { - LOG.error("Failed to retrieve table entities for database {} from Atlas", hiveDbName, e); - if (failOnError) { - throw e; - } - continue; - } - - List guidsToDelete = new ArrayList<>(); - if (!hiveClient.databaseExists(hiveDbName)) { - - //table guids - if (CollectionUtils.isNotEmpty(tables)) { - for (AtlasEntityHeader table : tables) { - guidsToDelete.add(table.getGuid()); - } - } - - //db guid - guidsToDelete.add(db.getGuid()); - LOG.info("Added database {}.{} and its {} tables to delete", metadataNamespace, hiveDbName, tables.size()); - - } else { - //iterate all table of db to check if it exists - if (CollectionUtils.isNotEmpty(tables)) { - for (AtlasEntityHeader table : tables) { - String hiveTableName = getHiveTableName((String) table.getAttribute(ATTRIBUTE_QUALIFIED_NAME), true); - - if (StringUtils.isEmpty(hiveTableName)) { - LOG.error("Failed to get table from qualifiedName: {}, guid: {} ", table.getAttribute(ATTRIBUTE_QUALIFIED_NAME), table.getGuid()); - continue; - } - - try { - hiveClient.getTable(hiveDbName, hiveTableName, true); - } catch (InvalidTableException e) { //table doesn't exists - LOG.info("Added table {}.{} to delete", hiveDbName, hiveTableName); - - guidsToDelete.add(table.getGuid()); - } catch (HiveException e) { - LOG.error("Failed to get table {}.{} from Hive", hiveDbName, hiveTableName, e); - - if (failOnError) { - throw e; - } - } - } - } - } - - //delete entities - if (CollectionUtils.isNotEmpty(guidsToDelete)) { - try { - deleteByGuid(guidsToDelete); - } catch (AtlasServiceException e) { - LOG.error("Failed to delete Atlas entities for database {}", hiveDbName, e); - - if (failOnError) { - throw e; - } - } - - } - } - - } else { - LOG.info("No database found in service."); - } - - } -} diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridgeV2.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridgeV2.java deleted file mode 100644 index 0627c0e095c..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridgeV2.java +++ /dev/null @@ -1,1036 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.bridge; - -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.AtlasServiceException; -import org.apache.atlas.exception.AtlasBaseException; -import org.apache.atlas.model.impexp.AtlasImportRequest; -import org.apache.atlas.model.impexp.AtlasImportResult; -import org.apache.atlas.model.typedef.AtlasTypesDef; -import org.apache.atlas.type.AtlasType; -import org.apache.atlas.type.AtlasTypeUtil; -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.hive.hook.events.BaseHiveEvent; -import org.apache.atlas.hive.model.HiveDataTypes; -import org.apache.atlas.hook.AtlasHookException; -import org.apache.atlas.utils.AtlasPathExtractorUtil; -import org.apache.atlas.utils.HdfsNameServiceResolver; -import org.apache.atlas.utils.AtlasConfigurationUtil; -import org.apache.atlas.utils.PathExtractorContext; -import org.apache.atlas.utils.LruCache; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.model.instance.AtlasStruct; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; -import org.apache.commons.cli.MissingArgumentException; -import org.apache.commons.collections.CollectionUtils; - -import org.apache.commons.cli.CommandLine; -import org.apache.commons.collections.MapUtils; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.RandomStringUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.hive.conf.HiveConf; -import org.apache.hadoop.hive.metastore.TableType; -import org.apache.hadoop.hive.metastore.api.Database; -import org.apache.hadoop.hive.metastore.api.FieldSchema; -import org.apache.hadoop.hive.metastore.api.Order; -import org.apache.hadoop.hive.metastore.api.SerDeInfo; -import org.apache.hadoop.hive.metastore.api.StorageDescriptor; -import org.apache.hadoop.hive.ql.metadata.Hive; -import org.apache.hadoop.hive.ql.metadata.HiveException; -import org.apache.hadoop.hive.ql.metadata.Table; -import org.apache.hadoop.hive.ql.session.SessionState; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.OutputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.*; -import java.util.stream.Collectors; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import static org.apache.atlas.hive.hook.events.BaseHiveEvent.*; - -/** - * A Bridge Utility that imports metadata into zip file from the Hive Meta Store - * which can be exported at Atlas - */ -public class HiveMetaStoreBridgeV2 { - private static final Logger LOG = LoggerFactory.getLogger(HiveMetaStoreBridgeV2.class); - - private static final String OPTION_DATABASE_SHORT = "d"; - private static final String OPTION_TABLE_SHORT = "t"; - private static final String OPTION_IMPORT_DATA_FILE_SHORT = "f"; - private static final String OPTION_OUTPUT_FILEPATH_SHORT = "o"; - private static final String OPTION_IGNORE_BULK_IMPORT_SHORT = "i"; - - public static final String CONF_PREFIX = "atlas.hook.hive."; - public static final String HDFS_PATH_CONVERT_TO_LOWER_CASE = CONF_PREFIX + "hdfs_path.convert_to_lowercase"; - public static final String HOOK_AWS_S3_ATLAS_MODEL_VERSION = CONF_PREFIX + "aws_s3.atlas.model.version"; - - public static final String CLUSTER_NAME_KEY = "atlas.cluster.name"; - public static final String HIVE_USERNAME = "atlas.hook.hive.default.username"; - public static final String HIVE_METADATA_NAMESPACE = "atlas.metadata.namespace"; - public static final String DEFAULT_CLUSTER_NAME = "primary"; - public static final String TEMP_TABLE_PREFIX = "_temp-"; - public static final String SEP = ":".intern(); - public static final String DEFAULT_METASTORE_CATALOG = "hive"; - public static final String HOOK_HIVE_PAGE_LIMIT = CONF_PREFIX + "page.limit"; - - private static final String HOOK_AWS_S3_ATLAS_MODEL_VERSION_V2 = "v2"; - private static final String ZIP_FILE_COMMENT_FORMAT = "{\"entitiesCount\":%d, \"total\":%d}"; - private static final int DEFAULT_PAGE_LIMIT = 10000; - private static final String DEFAULT_ZIP_FILE_NAME = "import-hive-output.zip"; - private static final String ZIP_ENTRY_ENTITIES = "entities.json"; - private static final String TYPES_DEF_JSON = "atlas-typesdef.json"; - - private static final String JSON_ARRAY_START = "["; - private static final String JSON_COMMA = ","; - private static final String JSON_EMPTY_OBJECT = "{}"; - private static final String JSON_ARRAY_END = "]"; - - private static int pageLimit = DEFAULT_PAGE_LIMIT; - private String awsS3AtlasModelVersion = null; - - private final String metadataNamespace; - private final Hive hiveClient; - private final AtlasClientV2 atlasClientV2; - private final boolean convertHdfsPathToLowerCase; - - private ZipOutputStream zipOutputStream; - private String outZipFileName; - private int totalProcessedEntities = 0; - - private final Map entityLRUCache = new LruCache<>(10000, 0); - private final Map hiveTablesAndAtlasEntity = new HashMap<>(); - private final Map dbEntities = new HashMap<>(); - private final List> databaseAndTableListToImport = new ArrayList<>(); - private final Map qualifiedNameGuidMap = new HashMap<>(); - - /** - * Construct a HiveMetaStoreBridgeV2. - * @param hiveConf {@link HiveConf} for Hive component in the cluster - */ - public HiveMetaStoreBridgeV2(Configuration atlasProperties, HiveConf hiveConf, AtlasClientV2 atlasClientV2) throws Exception { - this.metadataNamespace = getMetadataNamespace(atlasProperties); - this.hiveClient = Hive.get(hiveConf); - this.atlasClientV2 = atlasClientV2; - this.convertHdfsPathToLowerCase = atlasProperties.getBoolean(HDFS_PATH_CONVERT_TO_LOWER_CASE, false); - this.awsS3AtlasModelVersion = atlasProperties.getString(HOOK_AWS_S3_ATLAS_MODEL_VERSION, HOOK_AWS_S3_ATLAS_MODEL_VERSION_V2); - - if (atlasProperties != null) { - pageLimit = atlasProperties.getInteger(HOOK_HIVE_PAGE_LIMIT, DEFAULT_PAGE_LIMIT); - } - } - - public boolean exportDataToZipAndRunAtlasImport(CommandLine cmd) throws MissingArgumentException, IOException, HiveException, AtlasBaseException { - boolean ret = true; - boolean failOnError = cmd.hasOption("failOnError"); - - String databaseToImport = cmd.getOptionValue(OPTION_DATABASE_SHORT); - String tableToImport = cmd.getOptionValue(OPTION_TABLE_SHORT); - String importDataFile = cmd.getOptionValue(OPTION_IMPORT_DATA_FILE_SHORT); - String outputFileOrPath = cmd.getOptionValue(OPTION_OUTPUT_FILEPATH_SHORT); - - boolean ignoreBulkImport = cmd.hasOption(OPTION_IGNORE_BULK_IMPORT_SHORT); - - validateOutputFileOrPath(outputFileOrPath); - - try { - initializeZipStream(); - - if (isValidImportDataFile(importDataFile)) { - File f = new File(importDataFile); - - BufferedReader br = new BufferedReader(new FileReader(f)); - String line = null; - - while ((line = br.readLine()) != null) { - String val[] = line.split(":"); - - if (ArrayUtils.isNotEmpty(val)) { - databaseToImport = val[0]; - - if (val.length > 1) { - tableToImport = val[1]; - } else { - tableToImport = ""; - } - - importHiveDatabases(databaseToImport, tableToImport, failOnError); - } - } - } else { - importHiveDatabases(databaseToImport, tableToImport, failOnError); - } - - importHiveTables(failOnError); - importHiveColumns(failOnError); - } finally { - endWritingAndZipStream(); - } - - if (!ignoreBulkImport) { - runAtlasImport(); - } - - return ret; - } - - private void validateOutputFileOrPath(String outputFileOrPath) throws MissingArgumentException { - if (StringUtils.isBlank(outputFileOrPath)) { - throw new MissingArgumentException("Output Path/File can't be empty"); - } - - File fileOrDirToImport = new File(outputFileOrPath); - if (fileOrDirToImport.exists()) { - if (fileOrDirToImport.isDirectory()) { - this.outZipFileName = outputFileOrPath + File.separator + DEFAULT_ZIP_FILE_NAME; - LOG.info("The default output zip file {} will be created at {}", DEFAULT_ZIP_FILE_NAME, outputFileOrPath); - } else { - throw new MissingArgumentException("output file: " + outputFileOrPath + " already present"); - } - } else if (fileOrDirToImport.getParentFile().isDirectory() && outputFileOrPath.endsWith(".zip")) { - LOG.info("The mentioned output zip file {} will be created", outputFileOrPath); - this.outZipFileName = outputFileOrPath; - } else { - throw new MissingArgumentException("Invalid File/Path"); - } - } - - private boolean isValidImportDataFile(String importDataFile) throws MissingArgumentException { - boolean ret = false; - if (StringUtils.isNotBlank(importDataFile)) { - File dataFile = new File(importDataFile); - - if (!dataFile.exists() || !dataFile.canRead()) { - throw new MissingArgumentException("Invalid import data file"); - } - ret = true; - } - - return ret; - } - - private void initializeZipStream() throws IOException, AtlasBaseException { - this.zipOutputStream = new ZipOutputStream(getOutputStream(this.outZipFileName)); - - storeTypesDefToZip(new AtlasTypesDef()); - - startWritingEntitiesToZip(); - } - - private void storeTypesDefToZip(AtlasTypesDef typesDef) throws AtlasBaseException { - String jsonData = AtlasType.toJson(typesDef); - saveToZip(TYPES_DEF_JSON, jsonData); - } - - private void saveToZip(String fileName, String jsonData) throws AtlasBaseException { - try { - ZipEntry e = new ZipEntry(fileName); - zipOutputStream.putNextEntry(e); - writeBytes(jsonData); - zipOutputStream.closeEntry(); - } catch (IOException e) { - throw new AtlasBaseException(String.format("Error writing file %s.", fileName), e); - } - } - - private void startWritingEntitiesToZip() throws IOException { - zipOutputStream.putNextEntry(new ZipEntry(ZIP_ENTRY_ENTITIES)); - writeBytes(JSON_ARRAY_START); - } - - private String getDatabaseToImport(String TableWithDatabase) { - String ret = null; - String val[] = TableWithDatabase.split("\\."); - if (val.length > 1) { - ret = val[0]; - } - return ret; - } - - private String getTableToImport(String TableWithDatabase) { - String ret = null; - String val[] = TableWithDatabase.split("\\."); - if (val.length > 1) { - ret = val[1]; - } - return ret; - } - - private void importHiveDatabases(String databaseToImport, String tableWithDatabaseToImport, boolean failOnError) throws HiveException, AtlasBaseException { - LOG.info("Importing Hive Databases"); - - List databaseNames = null; - - if (StringUtils.isEmpty(databaseToImport) && StringUtils.isNotEmpty(tableWithDatabaseToImport)) { - if (isTableWithDatabaseName(tableWithDatabaseToImport)) { - databaseToImport = getDatabaseToImport(tableWithDatabaseToImport); - tableWithDatabaseToImport = getTableToImport(tableWithDatabaseToImport); - } - } - - if (StringUtils.isEmpty(databaseToImport)) { - //when database to import is empty, import all - databaseNames = hiveClient.getAllDatabases(); - } else { - //when database to import has some value then, import that db and all table under it. - databaseNames = hiveClient.getDatabasesByPattern(databaseToImport); - } - - if (!CollectionUtils.isEmpty(databaseNames)) { - LOG.info("Found {} databases", databaseNames.size()); - for (String databaseName : databaseNames) { - try { - if (!dbEntities.containsKey(databaseName)) { - LOG.info("Importing Hive Database {}", databaseName); - AtlasEntityWithExtInfo dbEntity = writeDatabase(databaseName); - if (dbEntity != null) { - dbEntities.put(databaseName, dbEntity.getEntity()); - } - } - databaseAndTableListToImport.add(Collections.singletonMap(databaseName, tableWithDatabaseToImport)); - } catch (IOException e) { - LOG.error("Import failed for hive database {}", databaseName, e); - - if (failOnError) { - throw new AtlasBaseException(e.getMessage(), e); - } - } - } - } else { - LOG.error("No database found"); - if (failOnError) { - throw new AtlasBaseException("No database found"); - } - } - } - - private void writeEntity(AtlasEntity.AtlasEntityWithExtInfo entityWithExtInfo) throws IOException { - if (MapUtils.isNotEmpty(entityWithExtInfo.getReferredEntities())) { - Iterator> itr = entityWithExtInfo.getReferredEntities().entrySet().iterator(); - while (itr.hasNext()) { - Map.Entry eachEntity = itr.next(); - if (eachEntity.getValue().getTypeName().equalsIgnoreCase(HiveDataTypes.HIVE_DB.getName())) { - itr.remove(); - } - } - } - - if (!entityLRUCache.containsKey(entityWithExtInfo.getEntity().getGuid())) { - entityLRUCache.put(entityWithExtInfo.getEntity().getGuid(), entityWithExtInfo); - writeBytes(AtlasType.toJson(entityWithExtInfo) + JSON_COMMA); - } - totalProcessedEntities++; - } - - private void endWritingAndZipStream() throws IOException { - writeBytes(JSON_EMPTY_OBJECT); - writeBytes(JSON_ARRAY_END); - setStreamSize(totalProcessedEntities); - close(); - } - - private void flush() { - try { - zipOutputStream.flush(); - } catch (IOException e) { - LOG.error("Error: Flush: ", e); - } - } - - private void close() throws IOException { - zipOutputStream.flush(); - zipOutputStream.closeEntry(); - zipOutputStream.close(); - } - - private void writeBytes(String payload) throws IOException { - zipOutputStream.write(payload.getBytes()); - } - - private OutputStream getOutputStream(String fileToWrite) throws IOException { - return FileUtils.openOutputStream(new File(fileToWrite)); - } - - public String getMetadataNamespace(Configuration config) { - return AtlasConfigurationUtil.getRecentString(config, HIVE_METADATA_NAMESPACE, getClusterName(config)); - } - - private String getClusterName(Configuration config) { - return config.getString(CLUSTER_NAME_KEY, DEFAULT_CLUSTER_NAME); - } - - public String getMetadataNamespace() { - return metadataNamespace; - } - - public boolean isConvertHdfsPathToLowerCase() { - return convertHdfsPathToLowerCase; - } - - /** - * Imports Hive tables if databaseAndTableListToImport is populated - * @param failOnError - * @throws Exception - */ - public void importHiveTables(boolean failOnError) throws HiveException, AtlasBaseException { - LOG.info("Importing Hive Tables"); - - int tablesImported = 0; - - if (CollectionUtils.isNotEmpty(databaseAndTableListToImport) && MapUtils.isNotEmpty(dbEntities)) { - for (Map eachEntry : databaseAndTableListToImport) { - final List
tableObjects; - - String databaseName = eachEntry.keySet().iterator().next(); - - if (StringUtils.isEmpty(eachEntry.values().iterator().next())) { - tableObjects = hiveClient.getAllTableObjects(databaseName); - - populateQualifiedNameGuidMap(HiveDataTypes.HIVE_DB.getName(), (String) dbEntities.get(databaseName).getAttribute(ATTRIBUTE_QUALIFIED_NAME)); - } else { - List tableNames = hiveClient.getTablesByPattern(databaseName, eachEntry.values().iterator().next()); - tableObjects = new ArrayList<>(); - - for (String tableName : tableNames) { - Table table = hiveClient.getTable(databaseName, tableName); - tableObjects.add(table); - populateQualifiedNameGuidMap(HiveDataTypes.HIVE_TABLE.getName(), getTableQualifiedName(metadataNamespace, table)); - } - } - - if (!CollectionUtils.isEmpty(tableObjects)) { - LOG.info("Found {} tables to import in database {}", tableObjects.size(), databaseName); - - try { - for (Table table : tableObjects) { - int imported = importTable(dbEntities.get(databaseName), table, failOnError); - - tablesImported += imported; - } - } finally { - if (tablesImported == tableObjects.size()) { - LOG.info("Successfully imported {} tables from database {}", tablesImported, databaseName); - } else { - LOG.error("Imported {} of {} tables from database {}. Please check logs for errors during import", - tablesImported, tableObjects.size(), databaseName); - } - } - } else { - LOG.error("No tables to import in database {}", databaseName); - if (failOnError) { - throw new AtlasBaseException("No tables to import in database - " + databaseName); - } - } - } - } - - dbEntities.clear(); - } - - private void populateQualifiedNameGuidMap(String typeName, String qualifiedName) { - try { - AtlasEntitiesWithExtInfo entitiesWithExtInfo = atlasClientV2.getEntitiesByAttribute(typeName, Collections.singletonList(Collections.singletonMap(ATTRIBUTE_QUALIFIED_NAME, qualifiedName)), true, false); - - if (entitiesWithExtInfo != null && entitiesWithExtInfo.getEntities() != null) { - for (AtlasEntity entity : entitiesWithExtInfo.getEntities()) { - qualifiedNameGuidMap.put((String) entity.getAttribute(ATTRIBUTE_QUALIFIED_NAME), entity.getGuid()); - - for(Map.Entry eachEntry : entitiesWithExtInfo.getReferredEntities().entrySet()) { - qualifiedNameGuidMap.put((String) eachEntry.getValue().getAttribute(ATTRIBUTE_QUALIFIED_NAME), eachEntry.getKey()); - } - - if (typeName.equals(HiveDataTypes.HIVE_DB.getName())) { - for (String eachRelatedGuid : getAllRelatedGuids(entity)) { - AtlasEntityWithExtInfo relatedEntity = atlasClientV2.getEntityByGuid(eachRelatedGuid, true, false); - - qualifiedNameGuidMap.put((String) relatedEntity.getEntity().getAttribute(ATTRIBUTE_QUALIFIED_NAME), relatedEntity.getEntity().getGuid()); - for (Map.Entry eachEntry : relatedEntity.getReferredEntities().entrySet()) { - qualifiedNameGuidMap.put((String) eachEntry.getValue().getAttribute(ATTRIBUTE_QUALIFIED_NAME), eachEntry.getKey()); - } - } - } - } - } - } catch (AtlasServiceException e) { - LOG.info("Unable to load the related entities for type {} and qualified name {} from Atlas", typeName, qualifiedName, e); - } - } - - private Set getAllRelatedGuids(AtlasEntity entity) { - Set relGuidsSet = new HashSet<>(); - - for (Object o : entity.getRelationshipAttributes().values()) { - if (o instanceof AtlasObjectId) { - relGuidsSet.add(((AtlasObjectId) o).getGuid()); - } else if (o instanceof List) { - for (Object id : (List) o) { - if (id instanceof AtlasObjectId) { - relGuidsSet.add(((AtlasObjectId) id).getGuid()); - } - if (id instanceof Map) { - relGuidsSet.add((String) ((Map) id).get("guid")); - } - } - } - } - - return relGuidsSet; - } - - public void importHiveColumns(boolean failOnError) throws AtlasBaseException { - LOG.info("Importing Hive Columns"); - - if (MapUtils.isEmpty(hiveTablesAndAtlasEntity)) { - if (LOG.isDebugEnabled()) { - LOG.debug("No hive table present to import columns"); - } - - return; - } - - for (Map.Entry eachTable : hiveTablesAndAtlasEntity.entrySet()) { - int columnsImported = 0; - List columnEntities = new ArrayList<>(); - - try { - List partKeys = toColumns(eachTable.getKey().getPartitionKeys(), eachTable.getValue(), RELATIONSHIP_HIVE_TABLE_PART_KEYS); - List columns = toColumns(eachTable.getKey().getCols(), eachTable.getValue(), RELATIONSHIP_HIVE_TABLE_COLUMNS); - - partKeys.stream().collect(Collectors.toCollection(() -> columnEntities)); - columns.stream().collect(Collectors.toCollection(() -> columnEntities)); - - for (AtlasEntity eachColumnEntity : columnEntities) { - writeEntityToZip(new AtlasEntityWithExtInfo(eachColumnEntity)); - columnsImported++; - } - } catch (IOException e) { - LOG.error("Column Import failed for hive table {}", eachTable.getValue().getAttribute(ATTRIBUTE_QUALIFIED_NAME), e); - - if (failOnError) { - throw new AtlasBaseException(e.getMessage(), e); - } - } finally { - if (columnsImported == columnEntities.size()) { - LOG.info("Successfully imported {} columns for table {}", columnsImported, eachTable.getValue().getAttribute(ATTRIBUTE_QUALIFIED_NAME)); - } else { - LOG.error("Imported {} of {} columns for table {}. Please check logs for errors during import", columnsImported, columnEntities.size(), eachTable.getValue().getAttribute(ATTRIBUTE_QUALIFIED_NAME)); - } - } - } - - } - - private void runAtlasImport() { - AtlasImportRequest request = new AtlasImportRequest(); - request.setOption(AtlasImportRequest.UPDATE_TYPE_DEFINITION_KEY, "false"); - request.setOption(AtlasImportRequest.OPTION_KEY_FORMAT, AtlasImportRequest.OPTION_KEY_FORMAT_ZIP_DIRECT); - - try { - AtlasImportResult importResult = atlasClientV2.importData(request, this.outZipFileName); - - if (importResult.getOperationStatus() == AtlasImportResult.OperationStatus.SUCCESS) { - LOG.info("Successfully imported the zip file {} at Atlas and imported {} entities. Number of entities to be imported {}.", this.outZipFileName, importResult.getProcessedEntities().size(), totalProcessedEntities); - } else { - LOG.error("Failed to import or get the status of import for the zip file {} at Atlas. Number of entities to be imported {}.", this.outZipFileName, totalProcessedEntities); - } - } catch (AtlasServiceException e) { - LOG.error("Failed to import or get the status of import for the zip file {} at Atlas. Number of entities to be imported {}.", this.outZipFileName, totalProcessedEntities, e); - } - } - - public int importTable(AtlasEntity dbEntity, Table table, final boolean failOnError) throws AtlasBaseException { - try { - AtlasEntityWithExtInfo tableEntity = writeTable(dbEntity, table); - - hiveTablesAndAtlasEntity.put(table, tableEntity.getEntity()); - - if (table.getTableType() == TableType.EXTERNAL_TABLE) { - String processQualifiedName = getTableProcessQualifiedName(metadataNamespace, table); - String tableLocationString = isConvertHdfsPathToLowerCase() ? lower(table.getDataLocation().toString()) : table.getDataLocation().toString(); - Path location = table.getDataLocation(); - String query = getCreateTableString(table, tableLocationString); - - PathExtractorContext pathExtractorCtx = new PathExtractorContext(getMetadataNamespace(), isConvertHdfsPathToLowerCase(), awsS3AtlasModelVersion); - AtlasEntityWithExtInfo entityWithExtInfo = AtlasPathExtractorUtil.getPathEntity(location, pathExtractorCtx); - AtlasEntity pathInst = entityWithExtInfo.getEntity(); - AtlasEntity tableInst = tableEntity.getEntity(); - AtlasEntity processInst = new AtlasEntity(HiveDataTypes.HIVE_PROCESS.getName()); - - long now = System.currentTimeMillis(); - - processInst.setGuid(getGuid(processQualifiedName)); - processInst.setAttribute(ATTRIBUTE_QUALIFIED_NAME, processQualifiedName); - processInst.setAttribute(ATTRIBUTE_NAME, query); - processInst.setAttribute(ATTRIBUTE_CLUSTER_NAME, metadataNamespace); - processInst.setRelationshipAttribute(ATTRIBUTE_INPUTS, Collections.singletonList(AtlasTypeUtil.getAtlasRelatedObjectId(pathInst, RELATIONSHIP_DATASET_PROCESS_INPUTS))); - processInst.setRelationshipAttribute(ATTRIBUTE_OUTPUTS, Collections.singletonList(AtlasTypeUtil.getAtlasRelatedObjectId(tableInst, RELATIONSHIP_PROCESS_DATASET_OUTPUTS))); - String userName = table.getOwner(); - if (StringUtils.isEmpty(userName)) { - userName = ApplicationProperties.get().getString(HIVE_USERNAME, "hive"); - } - processInst.setAttribute(ATTRIBUTE_USER_NAME, userName); - processInst.setAttribute(ATTRIBUTE_START_TIME, now); - processInst.setAttribute(ATTRIBUTE_END_TIME, now); - processInst.setAttribute(ATTRIBUTE_OPERATION_TYPE, "CREATETABLE"); - processInst.setAttribute(ATTRIBUTE_QUERY_TEXT, query); - processInst.setAttribute(ATTRIBUTE_QUERY_ID, query); - processInst.setAttribute(ATTRIBUTE_QUERY_PLAN, "{}"); - processInst.setAttribute(ATTRIBUTE_RECENT_QUERIES, Collections.singletonList(query)); - - AtlasEntitiesWithExtInfo createTableProcess = new AtlasEntitiesWithExtInfo(); - - createTableProcess.addEntity(processInst); - - if (pathExtractorCtx.getKnownEntities() != null) { - pathExtractorCtx.getKnownEntities().values().forEach(entity -> createTableProcess.addEntity(entity)); - } else { - createTableProcess.addEntity(pathInst); - } - - writeEntitiesToZip(createTableProcess); - } - - return 1; - } catch (Exception e) { - LOG.error("Import failed for hive_table {}", table.getTableName(), e); - - if (failOnError) { - throw new AtlasBaseException(e.getMessage(), e); - } - - return 0; - } - } - - /** - * Write db entity - * @param databaseName - * @return - * @throws Exception - */ - private AtlasEntityWithExtInfo writeDatabase(String databaseName) throws HiveException, IOException { - AtlasEntityWithExtInfo ret = null; - Database db = hiveClient.getDatabase(databaseName); - - if (db != null) { - ret = new AtlasEntityWithExtInfo(toDbEntity(db)); - writeEntityToZip(ret); - } - - return ret; - } - - private AtlasEntityWithExtInfo writeTable(AtlasEntity dbEntity, Table table) throws AtlasHookException { - try { - AtlasEntityWithExtInfo tableEntity = toTableEntity(dbEntity, table); - writeEntityToZip(tableEntity); - - return tableEntity; - } catch (Exception e) { - throw new AtlasHookException("HiveMetaStoreBridgeV2.registerTable() failed.", e); - } - } - - /** - * Write an entity to Zip file - * @param entity - * @return - * @throws Exception - */ - private void writeEntityToZip(AtlasEntityWithExtInfo entity) throws IOException { - if (LOG.isDebugEnabled()) { - LOG.debug("Writing {} entity: {}", entity.getEntity().getTypeName(), entity); - } - - writeEntity(entity); - clearRelationshipAttributes(entity.getEntity()); - flush(); - } - - /** - * Registers an entity in atlas - * @param entities - * @return - * @throws Exception - */ - private void writeEntitiesToZip(AtlasEntitiesWithExtInfo entities) throws IOException { - if (LOG.isDebugEnabled()) { - LOG.debug("Writing {} entities: {}", entities.getEntities().size(), entities); - } - - for (AtlasEntity entity : entities.getEntities()) { - writeEntity(new AtlasEntityWithExtInfo(entity)); - } - - flush(); - clearRelationshipAttributes(entities); - } - - /** - * Create a Hive Database entity - * @param hiveDB The Hive {@link Database} object from which to map properties - * @return new Hive Database AtlasEntity - * @throws HiveException - */ - private AtlasEntity toDbEntity(Database hiveDB) { - return toDbEntity(hiveDB, null); - } - - private AtlasEntity toDbEntity(Database hiveDB, AtlasEntity dbEntity) { - if (dbEntity == null) { - dbEntity = new AtlasEntity(HiveDataTypes.HIVE_DB.getName()); - } - - String dbName = getDatabaseName(hiveDB); - - String qualifiedName = getDBQualifiedName(metadataNamespace, dbName); - dbEntity.setAttribute(ATTRIBUTE_QUALIFIED_NAME, qualifiedName); - - dbEntity.setGuid(getGuid(true, qualifiedName)); - - dbEntity.setAttribute(ATTRIBUTE_NAME, dbName); - dbEntity.setAttribute(ATTRIBUTE_DESCRIPTION, hiveDB.getDescription()); - dbEntity.setAttribute(ATTRIBUTE_OWNER, hiveDB.getOwnerName()); - - dbEntity.setAttribute(ATTRIBUTE_CLUSTER_NAME, metadataNamespace); - dbEntity.setAttribute(ATTRIBUTE_LOCATION, HdfsNameServiceResolver.getPathWithNameServiceID(hiveDB.getLocationUri())); - dbEntity.setAttribute(ATTRIBUTE_PARAMETERS, hiveDB.getParameters()); - - if (hiveDB.getOwnerType() != null) { - dbEntity.setAttribute(ATTRIBUTE_OWNER_TYPE, OWNER_TYPE_TO_ENUM_VALUE.get(hiveDB.getOwnerType().getValue())); - } - - return dbEntity; - } - - private String getDBGuidFromAtlas(String dBQualifiedName) { - String guid = null; - try { - guid = atlasClientV2.getEntityHeaderByAttribute(HiveDataTypes.HIVE_DB.getName(), Collections.singletonMap(ATTRIBUTE_QUALIFIED_NAME, dBQualifiedName)).getGuid(); - } catch (AtlasServiceException e) { - LOG.warn("Failed to get DB guid from Atlas with qualified name {}", dBQualifiedName, e); - } - return guid; - } - - public static String getDatabaseName(Database hiveDB) { - String dbName = hiveDB.getName().toLowerCase(); - String catalogName = hiveDB.getCatalogName() != null ? hiveDB.getCatalogName().toLowerCase() : null; - - if (StringUtils.isNotEmpty(catalogName) && !StringUtils.equals(catalogName, DEFAULT_METASTORE_CATALOG)) { - dbName = catalogName + SEP + dbName; - } - - return dbName; - } - - /** - * Create a new table instance in Atlas - * @param database AtlasEntity for Hive {@link AtlasEntity} to which this table belongs - * @param hiveTable reference to the Hive {@link Table} from which to map properties - * @return Newly created Hive AtlasEntity - * @throws Exception - */ - private AtlasEntityWithExtInfo toTableEntity(AtlasEntity database, final Table hiveTable) throws AtlasHookException { - AtlasEntityWithExtInfo table = new AtlasEntityWithExtInfo(new AtlasEntity(HiveDataTypes.HIVE_TABLE.getName())); - - AtlasEntity tableEntity = table.getEntity(); - String tableQualifiedName = getTableQualifiedName(metadataNamespace, hiveTable); - long createTime = BaseHiveEvent.getTableCreateTime(hiveTable); - long lastAccessTime = hiveTable.getLastAccessTime() > 0 ? hiveTable.getLastAccessTime() : createTime; - - tableEntity.setGuid(getGuid(tableQualifiedName)); - tableEntity.setRelationshipAttribute(ATTRIBUTE_DB, AtlasTypeUtil.getAtlasRelatedObjectId(database, RELATIONSHIP_HIVE_TABLE_DB)); - tableEntity.setAttribute(ATTRIBUTE_QUALIFIED_NAME, tableQualifiedName); - tableEntity.setAttribute(ATTRIBUTE_NAME, hiveTable.getTableName().toLowerCase()); - tableEntity.setAttribute(ATTRIBUTE_OWNER, hiveTable.getOwner()); - - tableEntity.setAttribute(ATTRIBUTE_CREATE_TIME, createTime); - tableEntity.setAttribute(ATTRIBUTE_LAST_ACCESS_TIME, lastAccessTime); - tableEntity.setAttribute(ATTRIBUTE_RETENTION, hiveTable.getRetention()); - tableEntity.setAttribute(ATTRIBUTE_PARAMETERS, hiveTable.getParameters()); - tableEntity.setAttribute(ATTRIBUTE_COMMENT, hiveTable.getParameters().get(ATTRIBUTE_COMMENT)); - tableEntity.setAttribute(ATTRIBUTE_TABLE_TYPE, hiveTable.getTableType().name()); - tableEntity.setAttribute(ATTRIBUTE_TEMPORARY, hiveTable.isTemporary()); - - if (hiveTable.getViewOriginalText() != null) { - tableEntity.setAttribute(ATTRIBUTE_VIEW_ORIGINAL_TEXT, hiveTable.getViewOriginalText()); - } - - if (hiveTable.getViewExpandedText() != null) { - tableEntity.setAttribute(ATTRIBUTE_VIEW_EXPANDED_TEXT, hiveTable.getViewExpandedText()); - } - - AtlasEntity sdEntity = toStorageDescEntity(hiveTable.getSd(), getStorageDescQFName(tableQualifiedName), AtlasTypeUtil.getObjectId(tableEntity)); - - tableEntity.setRelationshipAttribute(ATTRIBUTE_STORAGEDESC, AtlasTypeUtil.getAtlasRelatedObjectId(sdEntity, RELATIONSHIP_HIVE_TABLE_STORAGE_DESC)); - - table.addReferredEntity(database); - table.addReferredEntity(sdEntity); - table.setEntity(tableEntity); - - return table; - } - - private AtlasEntity toStorageDescEntity(StorageDescriptor storageDesc, String sdQualifiedName, AtlasObjectId tableId) { - AtlasEntity ret = new AtlasEntity(HiveDataTypes.HIVE_STORAGEDESC.getName()); - - ret.setGuid(getGuid(sdQualifiedName)); - ret.setRelationshipAttribute(ATTRIBUTE_TABLE, AtlasTypeUtil.getAtlasRelatedObjectId(tableId, RELATIONSHIP_HIVE_TABLE_STORAGE_DESC)); - ret.setAttribute(ATTRIBUTE_QUALIFIED_NAME, sdQualifiedName); - ret.setAttribute(ATTRIBUTE_PARAMETERS, storageDesc.getParameters()); - ret.setAttribute(ATTRIBUTE_LOCATION, HdfsNameServiceResolver.getPathWithNameServiceID(storageDesc.getLocation())); - ret.setAttribute(ATTRIBUTE_INPUT_FORMAT, storageDesc.getInputFormat()); - ret.setAttribute(ATTRIBUTE_OUTPUT_FORMAT, storageDesc.getOutputFormat()); - ret.setAttribute(ATTRIBUTE_COMPRESSED, storageDesc.isCompressed()); - ret.setAttribute(ATTRIBUTE_NUM_BUCKETS, storageDesc.getNumBuckets()); - ret.setAttribute(ATTRIBUTE_STORED_AS_SUB_DIRECTORIES, storageDesc.isStoredAsSubDirectories()); - - if (storageDesc.getBucketCols().size() > 0) { - ret.setAttribute(ATTRIBUTE_BUCKET_COLS, storageDesc.getBucketCols()); - } - - if (storageDesc.getSerdeInfo() != null) { - SerDeInfo serdeInfo = storageDesc.getSerdeInfo(); - - LOG.info("serdeInfo = {}", serdeInfo); - AtlasStruct serdeInfoStruct = new AtlasStruct(HiveDataTypes.HIVE_SERDE.getName()); - - serdeInfoStruct.setAttribute(ATTRIBUTE_NAME, serdeInfo.getName()); - serdeInfoStruct.setAttribute(ATTRIBUTE_SERIALIZATION_LIB, serdeInfo.getSerializationLib()); - serdeInfoStruct.setAttribute(ATTRIBUTE_PARAMETERS, serdeInfo.getParameters()); - - ret.setAttribute(ATTRIBUTE_SERDE_INFO, serdeInfoStruct); - } - - if (CollectionUtils.isNotEmpty(storageDesc.getSortCols())) { - List sortColsStruct = new ArrayList<>(); - - for (Order sortcol : storageDesc.getSortCols()) { - String hiveOrderName = HiveDataTypes.HIVE_ORDER.getName(); - AtlasStruct colStruct = new AtlasStruct(hiveOrderName); - colStruct.setAttribute("col", sortcol.getCol()); - colStruct.setAttribute("order", sortcol.getOrder()); - - sortColsStruct.add(colStruct); - } - - ret.setAttribute(ATTRIBUTE_SORT_COLS, sortColsStruct); - } - - return ret; - } - - private List toColumns(List schemaList, AtlasEntity table, String relationshipType) { - List ret = new ArrayList<>(); - - int columnPosition = 0; - for (FieldSchema fs : schemaList) { - LOG.debug("Processing field {}", fs); - - AtlasEntity column = new AtlasEntity(HiveDataTypes.HIVE_COLUMN.getName()); - - String columnQualifiedName = getColumnQualifiedName((String) table.getAttribute(ATTRIBUTE_QUALIFIED_NAME), fs.getName()); - - column.setAttribute(ATTRIBUTE_QUALIFIED_NAME, columnQualifiedName); - column.setGuid(getGuid(columnQualifiedName)); - - column.setRelationshipAttribute(ATTRIBUTE_TABLE, AtlasTypeUtil.getAtlasRelatedObjectId(table, relationshipType)); - - column.setAttribute(ATTRIBUTE_NAME, fs.getName()); - column.setAttribute(ATTRIBUTE_OWNER, table.getAttribute(ATTRIBUTE_OWNER)); - column.setAttribute(ATTRIBUTE_COL_TYPE, fs.getType()); - column.setAttribute(ATTRIBUTE_COL_POSITION, columnPosition++); - column.setAttribute(ATTRIBUTE_COMMENT, fs.getComment()); - - ret.add(column); - } - return ret; - } - - private String getCreateTableString(Table table, String location){ - String colString = ""; - List colList = table.getAllCols(); - - if (colList != null) { - for (FieldSchema col : colList) { - colString += col.getName() + " " + col.getType() + ","; - } - - if (colList.size() > 0) { - colString = colString.substring(0, colString.length() - 1); - colString = "(" + colString + ")"; - } - } - - String query = "create external table " + table.getTableName() + colString + " location '" + location + "'"; - - return query; - } - - private String lower(String str) { - if (StringUtils.isEmpty(str)) { - return ""; - } - - return str.toLowerCase().trim(); - } - - /** - * Construct the qualified name used to uniquely identify a Table instance in Atlas. - * @param metadataNamespace Metadata namespace of the cluster to which the Hive component belongs - * @param table hive table for which the qualified name is needed - * @return Unique qualified name to identify the Table instance in Atlas. - */ - private static String getTableQualifiedName(String metadataNamespace, Table table) { - return getTableQualifiedName(metadataNamespace, table.getDbName(), table.getTableName(), table.isTemporary()); - } - - /** - * Construct the qualified name used to uniquely identify a Database instance in Atlas. - * @param metadataNamespace Name of the cluster to which the Hive component belongs - * @param dbName Name of the Hive database - * @return Unique qualified name to identify the Database instance in Atlas. - */ - public static String getDBQualifiedName(String metadataNamespace, String dbName) { - return String.format("%s@%s", dbName.toLowerCase(), metadataNamespace); - } - - /** - * Construct the qualified name used to uniquely identify a Table instance in Atlas. - * @param metadataNamespace Name of the cluster to which the Hive component belongs - * @param dbName Name of the Hive database to which the Table belongs - * @param tableName Name of the Hive table - * @param isTemporaryTable is this a temporary table - * @return Unique qualified name to identify the Table instance in Atlas. - */ - public static String getTableQualifiedName(String metadataNamespace, String dbName, String tableName, boolean isTemporaryTable) { - String tableTempName = tableName; - - if (isTemporaryTable) { - if (SessionState.get() != null && SessionState.get().getSessionId() != null) { - tableTempName = tableName + TEMP_TABLE_PREFIX + SessionState.get().getSessionId(); - } else { - tableTempName = tableName + TEMP_TABLE_PREFIX + RandomStringUtils.random(10); - } - } - - return String.format("%s.%s@%s", dbName.toLowerCase(), tableTempName.toLowerCase(), metadataNamespace); - } - - public static String getTableProcessQualifiedName(String metadataNamespace, Table table) { - String tableQualifiedName = getTableQualifiedName(metadataNamespace, table); - long createdTime = getTableCreatedTime(table); - - return tableQualifiedName + SEP + createdTime; - } - - public static String getStorageDescQFName(String tableQualifiedName) { - return tableQualifiedName + "_storage"; - } - - public static String getColumnQualifiedName(final String tableQualifiedName, final String colName) { - final String[] parts = tableQualifiedName.split("@"); - final String tableName = parts[0]; - final String metadataNamespace = parts[1]; - - return String.format("%s.%s@%s", tableName, colName.toLowerCase(), metadataNamespace); - } - - public static long getTableCreatedTime(Table table) { - return table.getTTable().getCreateTime() * MILLIS_CONVERT_FACTOR; - } - - private void clearRelationshipAttributes(AtlasEntitiesWithExtInfo entities) { - if (entities != null) { - if (entities.getEntities() != null) { - for (AtlasEntity entity : entities.getEntities()) { - clearRelationshipAttributes(entity);; - } - } - - if (entities.getReferredEntities() != null) { - clearRelationshipAttributes(entities.getReferredEntities().values()); - } - } - } - - private void clearRelationshipAttributes(Collection entities) { - if (entities != null) { - for (AtlasEntity entity : entities) { - clearRelationshipAttributes(entity); - } - } - } - - private void clearRelationshipAttributes(AtlasEntity entity) { - if (entity != null && entity.getRelationshipAttributes() != null) { - entity.getRelationshipAttributes().clear(); - } - } - - private boolean isTableWithDatabaseName(String tableName) { - boolean ret = false; - if (tableName.contains(".")) { - ret = true; - } - return ret; - } - - private String getGuid(String qualifiedName) { - return getGuid(false, qualifiedName); - } - - private String getGuid(boolean isDBType, String qualifiedName) { - String guid = null; - - if (qualifiedNameGuidMap.containsKey(qualifiedName)) { - guid = qualifiedNameGuidMap.get(qualifiedName); - } else if (isDBType) { - guid = getDBGuidFromAtlas(qualifiedName); - } - - if (StringUtils.isBlank(guid)) { - guid = generateGuid(); - } - - return guid; - } - - private String generateGuid() { - return UUID.randomUUID().toString(); - } - - public void setStreamSize(long size) { - zipOutputStream.setComment(String.format(ZIP_FILE_COMMENT_FORMAT, size, -1)); - } -} \ No newline at end of file diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/AtlasHiveHookContext.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/AtlasHiveHookContext.java deleted file mode 100644 index 14cc2f20171..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/AtlasHiveHookContext.java +++ /dev/null @@ -1,314 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook; - -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.hive.hook.HiveMetastoreHookImpl.HiveMetastoreHook; -import org.apache.atlas.hive.hook.HiveHook.PreprocessAction; -import org.apache.atlas.hive.hook.HiveHook.HiveHookObjectNamesCache; -import org.apache.commons.lang.RandomStringUtils; -import org.apache.hadoop.hive.metastore.IHMSHandler; -import org.apache.hadoop.hive.metastore.api.Database; -import org.apache.hadoop.hive.metastore.events.*; -import org.apache.hadoop.hive.ql.hooks.*; -import org.apache.hadoop.hive.ql.metadata.Hive; -import org.apache.hadoop.hive.ql.metadata.Table; -import org.apache.hadoop.hive.ql.plan.HiveOperation; -import org.apache.hadoop.hive.ql.session.SessionState; - -import java.util.*; - -import static org.apache.atlas.hive.bridge.HiveMetaStoreBridge.getDatabaseName; -import static org.apache.atlas.hive.hook.events.BaseHiveEvent.toTable; - - -public class AtlasHiveHookContext { - public static final char QNAME_SEP_METADATA_NAMESPACE = '@'; - public static final char QNAME_SEP_ENTITY_NAME = '.'; - public static final char QNAME_SEP_PROCESS = ':'; - public static final String TEMP_TABLE_PREFIX = "_temp-"; - public static final String CREATE_OPERATION = "CREATE"; - public static final String ALTER_OPERATION = "ALTER"; - - private final HiveHook hook; - private final HiveOperation hiveOperation; - private final HookContext hiveContext; - private final Hive hive; - private final Map qNameEntityMap = new HashMap<>(); - private final HiveHookObjectNamesCache knownObjects; - private final HiveMetastoreHook metastoreHook; - private final ListenerEvent metastoreEvent; - private final IHMSHandler metastoreHandler; - - private boolean isSkippedInputEntity; - private boolean isSkippedOutputEntity; - private boolean skipTempTables; - - public AtlasHiveHookContext(HiveHook hook, HiveOperation hiveOperation, HookContext hiveContext, - HiveHookObjectNamesCache knownObjects, boolean skipTempTables) throws Exception { - this(hook, hiveOperation, hiveContext, knownObjects, null, null, skipTempTables); - } - - public AtlasHiveHookContext(HiveHook hook, HiveOperation hiveOperation, HiveHookObjectNamesCache knownObjects, - HiveMetastoreHook metastoreHook, ListenerEvent listenerEvent, boolean skipTempTables) throws Exception { - this(hook, hiveOperation, null, knownObjects, metastoreHook, listenerEvent, skipTempTables); - } - - public AtlasHiveHookContext(HiveHook hook, HiveOperation hiveOperation, HookContext hiveContext, HiveHookObjectNamesCache knownObjects, - HiveMetastoreHook metastoreHook, ListenerEvent listenerEvent, boolean skipTempTables) throws Exception { - this.hook = hook; - this.hiveOperation = hiveOperation; - this.hiveContext = hiveContext; - this.hive = hiveContext != null ? Hive.get(hiveContext.getConf()) : null; - this.knownObjects = knownObjects; - this.metastoreHook = metastoreHook; - this.metastoreEvent = listenerEvent; - this.metastoreHandler = (listenerEvent != null) ? metastoreEvent.getIHMSHandler() : null; - this.skipTempTables = skipTempTables; - - init(); - } - - public boolean isMetastoreHook() { - return metastoreHook != null; - } - - public ListenerEvent getMetastoreEvent() { - return metastoreEvent; - } - - public IHMSHandler getMetastoreHandler() { - return metastoreHandler; - } - - public Set getInputs() { - return hiveContext != null ? hiveContext.getInputs() : Collections.emptySet(); - } - - public Set getOutputs() { - return hiveContext != null ? hiveContext.getOutputs() : Collections.emptySet(); - } - - public boolean isSkippedInputEntity() { - return isSkippedInputEntity; - } - - public boolean isSkippedOutputEntity() { - return isSkippedOutputEntity; - } - - public void registerSkippedEntity(Entity entity) { - if (entity instanceof ReadEntity) { - registerSkippedInputEntity(); - } else if (entity instanceof WriteEntity) { - registerSkippedOutputEntity(); - } - } - - public void registerSkippedInputEntity() { - if (!isSkippedInputEntity) { - isSkippedInputEntity = true; - } - } - - public void registerSkippedOutputEntity() { - if (!isSkippedOutputEntity) { - isSkippedOutputEntity = true; - } - } - - public boolean isSkipTempTables() { - return skipTempTables; - } - - public LineageInfo getLineageInfo() { - return hiveContext != null ? hiveContext.getLinfo() : null; - } - - public HookContext getHiveContext() { - return hiveContext; - } - - public Hive getHive() { - return hive; - } - - public HiveOperation getHiveOperation() { - return hiveOperation; - } - - public void putEntity(String qualifiedName, AtlasEntity entity) { - qNameEntityMap.put(qualifiedName, entity); - } - - public AtlasEntity getEntity(String qualifiedName) { - return qNameEntityMap.get(qualifiedName); - } - - public Collection getEntities() { return qNameEntityMap.values(); } - - public Map getQNameToEntityMap() { return qNameEntityMap; } - - public String getMetadataNamespace() { - return hook.getMetadataNamespace(); - } - - public String getHostName() { return hook.getHostName(); } - - public boolean isConvertHdfsPathToLowerCase() { - return hook.isConvertHdfsPathToLowerCase(); - } - - public String getAwsS3AtlasModelVersion() { - return hook.getAwsS3AtlasModelVersion(); - } - - public boolean getSkipHiveColumnLineageHive20633() { - return hook.getSkipHiveColumnLineageHive20633(); - } - - public int getSkipHiveColumnLineageHive20633InputsThreshold() { - return hook.getSkipHiveColumnLineageHive20633InputsThreshold(); - } - - public PreprocessAction getPreprocessActionForHiveTable(String qualifiedName) { - return hook.getPreprocessActionForHiveTable(qualifiedName); - } - - public List getIgnoreDummyDatabaseName() { - return hook.getIgnoreDummyDatabaseName(); - } - - public List getIgnoreDummyTableName() { - return hook.getIgnoreDummyTableName(); - } - - public String getIgnoreValuesTmpTableNamePrefix() { - return hook.getIgnoreValuesTmpTableNamePrefix(); - } - - public String getQualifiedName(Database db) { - return getDatabaseName(db) + QNAME_SEP_METADATA_NAMESPACE + getMetadataNamespace(); - } - - public String getQualifiedName(Table table) { - String tableName = table.getTableName(); - - if (table.isTemporary()) { - if (SessionState.get() != null && SessionState.get().getSessionId() != null) { - tableName = tableName + TEMP_TABLE_PREFIX + SessionState.get().getSessionId(); - } else { - tableName = tableName + TEMP_TABLE_PREFIX + RandomStringUtils.random(10); - } - } - - return (table.getDbName() + QNAME_SEP_ENTITY_NAME + tableName + QNAME_SEP_METADATA_NAMESPACE).toLowerCase() + getMetadataNamespace(); - } - - public boolean isKnownDatabase(String dbQualifiedName) { - return knownObjects != null && dbQualifiedName != null ? knownObjects.isKnownDatabase(dbQualifiedName) : false; - } - - public boolean isKnownTable(String tblQualifiedName) { - return knownObjects != null && tblQualifiedName != null ? knownObjects.isKnownTable(tblQualifiedName) : false; - } - - public void addToKnownEntities(Collection entities) { - if (knownObjects != null && entities != null) { - knownObjects.addToKnownEntities(entities); - } - } - - public void removeFromKnownDatabase(String dbQualifiedName) { - if (knownObjects != null && dbQualifiedName != null) { - knownObjects.removeFromKnownDatabase(dbQualifiedName); - } - } - - public void removeFromKnownTable(String tblQualifiedName) { - if (knownObjects != null && tblQualifiedName != null) { - knownObjects.removeFromKnownTable(tblQualifiedName); - } - } - - public boolean isHiveProcessPopulateDeprecatedAttributes() { - return hook.isHiveProcessPopulateDeprecatedAttributes(); - } - - private void init() { - if (hiveOperation == null) { - return; - } - - String operation = hiveOperation.getOperationName(); - - if (knownObjects == null || !isCreateAlterOperation(operation)) { - return; - } - - List databases = new ArrayList<>(); - List

tables = new ArrayList<>(); - - if (isMetastoreHook()) { - switch (hiveOperation) { - case CREATEDATABASE: - databases.add(((CreateDatabaseEvent) metastoreEvent).getDatabase()); - break; - case ALTERDATABASE: - databases.add(((AlterDatabaseEvent) metastoreEvent).getOldDatabase()); - databases.add(((AlterDatabaseEvent) metastoreEvent).getNewDatabase()); - break; - case CREATETABLE: - tables.add(toTable(((CreateTableEvent) metastoreEvent).getTable())); - break; - case ALTERTABLE_PROPERTIES: - case ALTERTABLE_RENAME: - case ALTERTABLE_RENAMECOL: - tables.add(toTable(((AlterTableEvent) metastoreEvent).getOldTable())); - tables.add(toTable(((AlterTableEvent) metastoreEvent).getNewTable())); - break; - } - } else { - if (getOutputs() != null) { - for (WriteEntity output : hiveContext.getOutputs()) { - switch (output.getType()) { - case DATABASE: - databases.add(output.getDatabase()); - break; - case TABLE: - tables.add(output.getTable()); - break; - } - } - } - } - - for (Database database : databases) { - knownObjects.removeFromKnownDatabase(getQualifiedName(database)); - } - - for (Table table : tables) { - knownObjects.removeFromKnownTable(getQualifiedName(table)); - } - } - - private static boolean isCreateAlterOperation(String operationName) { - return operationName != null && operationName.startsWith(CREATE_OPERATION) || operationName.startsWith(ALTER_OPERATION); - } -} \ No newline at end of file diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/HiveHook.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/HiveHook.java deleted file mode 100644 index 6ea48482ab7..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/HiveHook.java +++ /dev/null @@ -1,428 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook; - -import org.apache.atlas.hive.hook.events.*; -import org.apache.atlas.hive.hook.utils.ActiveEntityFilter; -import org.apache.atlas.hook.AtlasHook; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.utils.LruCache; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.hadoop.hive.ql.hooks.ExecuteWithHookContext; -import org.apache.hadoop.hive.ql.hooks.HookContext; -import org.apache.hadoop.hive.ql.parse.SemanticAnalyzer; -import org.apache.hadoop.hive.ql.plan.HiveOperation; -import org.apache.hadoop.hive.shims.Utils; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; - -import static org.apache.atlas.hive.hook.events.BaseHiveEvent.ATTRIBUTE_QUALIFIED_NAME; -import static org.apache.atlas.hive.hook.events.BaseHiveEvent.HIVE_TYPE_DB; -import static org.apache.atlas.hive.hook.events.BaseHiveEvent.HIVE_TYPE_TABLE; -import static org.apache.atlas.repository.Constants.HS2_SOURCE; - -public class HiveHook extends AtlasHook implements ExecuteWithHookContext { - private static final Logger LOG = LoggerFactory.getLogger(HiveHook.class); - - public enum PreprocessAction { NONE, IGNORE, PRUNE } - - public static final String CONF_PREFIX = "atlas.hook.hive."; - public static final String HDFS_PATH_CONVERT_TO_LOWER_CASE = CONF_PREFIX + "hdfs_path.convert_to_lowercase"; - public static final String HOOK_NAME_CACHE_ENABLED = CONF_PREFIX + "name.cache.enabled"; - public static final String HOOK_NAME_CACHE_DATABASE_COUNT = CONF_PREFIX + "name.cache.database.count"; - public static final String HOOK_NAME_CACHE_TABLE_COUNT = CONF_PREFIX + "name.cache.table.count"; - public static final String HOOK_NAME_CACHE_REBUID_INTERVAL_SEC = CONF_PREFIX + "name.cache.rebuild.interval.seconds"; - public static final String HOOK_AWS_S3_ATLAS_MODEL_VERSION = CONF_PREFIX + "aws_s3.atlas.model.version"; - public static final String HOOK_AWS_S3_ATLAS_MODEL_VERSION_V2 = "v2"; - public static final String HOOK_HIVE_PROCESS_POPULATE_DEPRECATED_ATTRIBUTES = CONF_PREFIX + "hive_process.populate.deprecated.attributes"; - public static final String HOOK_SKIP_HIVE_COLUMN_LINEAGE_HIVE_20633 = CONF_PREFIX + "skip.hive_column_lineage.hive-20633"; - public static final String HOOK_SKIP_HIVE_COLUMN_LINEAGE_HIVE_20633_INPUTS_THRESHOLD = CONF_PREFIX + "skip.hive_column_lineage.hive-20633.inputs.threshold"; - public static final String HOOK_HIVE_TABLE_IGNORE_PATTERN = CONF_PREFIX + "hive_table.ignore.pattern"; - public static final String HOOK_HIVE_TABLE_PRUNE_PATTERN = CONF_PREFIX + "hive_table.prune.pattern"; - public static final String HOOK_HIVE_TABLE_CACHE_SIZE = CONF_PREFIX + "hive_table.cache.size"; - public static final String HOOK_HIVE_IGNORE_DDL_OPERATIONS = CONF_PREFIX + "hs2.ignore.ddl.operations"; - public static final String HOOK_HIVE_FILTER_ENTITY_ADDITIONAL_TYPES_TO_RETAIN = CONF_PREFIX + "hs2.filter.entity.additional.types.to.retain"; - public static final String HOOK_HIVE_SKIP_TEMP_TABLES = CONF_PREFIX + "skip.temp.tables"; - public static final String DEFAULT_HOST_NAME = "localhost"; - - private static final Map OPERATION_MAP = new HashMap<>(); - - private static final boolean convertHdfsPathToLowerCase; - private static final boolean nameCacheEnabled; - private static final int nameCacheDatabaseMaxCount; - private static final int nameCacheTableMaxCount; - private static final int nameCacheRebuildIntervalSeconds; - private static final String awsS3AtlasModelVersion; - - private static final boolean skipHiveColumnLineageHive20633; - private static final int skipHiveColumnLineageHive20633InputsThreshold; - private static final List hiveTablesToIgnore = new ArrayList<>(); - private static final List hiveTablesToPrune = new ArrayList<>(); - private static final Map hiveTablesCache; - private static final List ignoreDummyDatabaseName; - private static final List ignoreDummyTableName; - private static final String ignoreValuesTmpTableNamePrefix; - private static final boolean hiveProcessPopulateDeprecatedAttributes; - private static HiveHookObjectNamesCache knownObjects = null; - private static String hostName; - private static boolean skipTempTables = true; - - static { - for (HiveOperation hiveOperation : HiveOperation.values()) { - OPERATION_MAP.put(hiveOperation.getOperationName(), hiveOperation); - } - - convertHdfsPathToLowerCase = atlasProperties.getBoolean(HDFS_PATH_CONVERT_TO_LOWER_CASE, false); - nameCacheEnabled = atlasProperties.getBoolean(HOOK_NAME_CACHE_ENABLED, true); - nameCacheDatabaseMaxCount = atlasProperties.getInt(HOOK_NAME_CACHE_DATABASE_COUNT, 10000); - nameCacheTableMaxCount = atlasProperties.getInt(HOOK_NAME_CACHE_TABLE_COUNT, 10000); - nameCacheRebuildIntervalSeconds = atlasProperties.getInt(HOOK_NAME_CACHE_REBUID_INTERVAL_SEC, 60 * 60); // 60 minutes default - awsS3AtlasModelVersion = atlasProperties.getString(HOOK_AWS_S3_ATLAS_MODEL_VERSION, HOOK_AWS_S3_ATLAS_MODEL_VERSION_V2); - skipHiveColumnLineageHive20633 = atlasProperties.getBoolean(HOOK_SKIP_HIVE_COLUMN_LINEAGE_HIVE_20633, false); - skipHiveColumnLineageHive20633InputsThreshold = atlasProperties.getInt(HOOK_SKIP_HIVE_COLUMN_LINEAGE_HIVE_20633_INPUTS_THRESHOLD, 15); // skip if avg # of inputs is > 15 - hiveProcessPopulateDeprecatedAttributes = atlasProperties.getBoolean(HOOK_HIVE_PROCESS_POPULATE_DEPRECATED_ATTRIBUTES, false); - String[] patternHiveTablesToIgnore = atlasProperties.getStringArray(HOOK_HIVE_TABLE_IGNORE_PATTERN); - String[] patternHiveTablesToPrune = atlasProperties.getStringArray(HOOK_HIVE_TABLE_PRUNE_PATTERN); - - if (patternHiveTablesToIgnore != null) { - for (String pattern : patternHiveTablesToIgnore) { - try { - hiveTablesToIgnore.add(Pattern.compile(pattern)); - - LOG.info("{}={}", HOOK_HIVE_TABLE_IGNORE_PATTERN, pattern); - } catch (Throwable t) { - LOG.warn("failed to compile pattern {}", pattern, t); - LOG.warn("Ignoring invalid pattern in configuration {}: {}", HOOK_HIVE_TABLE_IGNORE_PATTERN, pattern); - } - } - } - - if (patternHiveTablesToPrune != null) { - for (String pattern : patternHiveTablesToPrune) { - try { - hiveTablesToPrune.add(Pattern.compile(pattern)); - - LOG.info("{}={}", HOOK_HIVE_TABLE_PRUNE_PATTERN, pattern); - } catch (Throwable t) { - LOG.warn("failed to compile pattern {}", pattern, t); - LOG.warn("Ignoring invalid pattern in configuration {}: {}", HOOK_HIVE_TABLE_PRUNE_PATTERN, pattern); - } - } - } - - if (!hiveTablesToIgnore.isEmpty() || !hiveTablesToPrune.isEmpty()) { - hiveTablesCache = new LruCache<>(atlasProperties.getInt(HOOK_HIVE_TABLE_CACHE_SIZE, 10000), 0); - } else { - hiveTablesCache = Collections.emptyMap(); - } - - knownObjects = nameCacheEnabled ? new HiveHookObjectNamesCache(nameCacheDatabaseMaxCount, nameCacheTableMaxCount, nameCacheRebuildIntervalSeconds) : null; - - List defaultDummyDatabase = new ArrayList<>(); - List defaultDummyTable = new ArrayList<>(); - - defaultDummyDatabase.add(SemanticAnalyzer.DUMMY_DATABASE); - defaultDummyTable.add(SemanticAnalyzer.DUMMY_TABLE); - - ignoreDummyDatabaseName = atlasProperties.getList("atlas.hook.hive.ignore.dummy.database.name", defaultDummyDatabase); - ignoreDummyTableName = atlasProperties.getList("atlas.hook.hive.ignore.dummy.table.name", defaultDummyTable); - ignoreValuesTmpTableNamePrefix = atlasProperties.getString("atlas.hook.hive.ignore.values.tmp.table.name.prefix", "Values__Tmp__Table__"); - skipTempTables = atlasProperties.getBoolean(HOOK_HIVE_SKIP_TEMP_TABLES, true); - - try { - hostName = InetAddress.getLocalHost().getHostName(); - } catch (UnknownHostException e) { - LOG.warn("No hostname found. Setting the hostname to default value {}", DEFAULT_HOST_NAME, e); - hostName = DEFAULT_HOST_NAME; - } - - ActiveEntityFilter.init(atlasProperties); - } - - - public HiveHook() { - } - - public HiveHook(String name) { - super(name); - } - - public String getMessageSource() { - return HS2_SOURCE; - } - - @Override - public void run(HookContext hookContext) throws Exception { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HiveHook.run({})", hookContext.getOperationName()); - } - - try { - HiveOperation oper = OPERATION_MAP.get(hookContext.getOperationName()); - AtlasHiveHookContext context = new AtlasHiveHookContext(this, oper, hookContext, getKnownObjects(), isSkipTempTables()); - BaseHiveEvent event = null; - - switch (oper) { - case CREATEDATABASE: - event = new CreateDatabase(context); - break; - - case DROPDATABASE: - event = new DropDatabase(context); - break; - - case ALTERDATABASE: - case ALTERDATABASE_OWNER: - case ALTERDATABASE_LOCATION: - event = new AlterDatabase(context); - break; - - case CREATETABLE: - event = new CreateTable(context); - break; - - case DROPTABLE: - case DROPVIEW: - case DROP_MATERIALIZED_VIEW: - event = new DropTable(context); - break; - - case CREATETABLE_AS_SELECT: - case CREATE_MATERIALIZED_VIEW: - case CREATEVIEW: - case ALTERVIEW_AS: - case LOAD: - case EXPORT: - case IMPORT: - case QUERY: - event = new CreateHiveProcess(context); - break; - - case ALTERTABLE_FILEFORMAT: - case ALTERTABLE_CLUSTER_SORT: - case ALTERTABLE_BUCKETNUM: - case ALTERTABLE_PROPERTIES: - case ALTERVIEW_PROPERTIES: - case ALTERTABLE_SERDEPROPERTIES: - case ALTERTABLE_SERIALIZER: - case ALTERTABLE_ADDCOLS: - case ALTERTABLE_REPLACECOLS: - case ALTERTABLE_PARTCOLTYPE: - case ALTERTABLE_LOCATION: - event = new AlterTable(context); - break; - - case ALTERTABLE_RENAME: - case ALTERVIEW_RENAME: - event = new AlterTableRename(context); - break; - - case ALTERTABLE_RENAMECOL: - event = new AlterTableRenameCol(context); - break; - - default: - if (LOG.isDebugEnabled()) { - LOG.debug("HiveHook.run({}): operation ignored", hookContext.getOperationName()); - } - break; - } - - if (event != null) { - final UserGroupInformation ugi = hookContext.getUgi() == null ? Utils.getUGI() : hookContext.getUgi(); - - super.notifyEntities(ActiveEntityFilter.apply(event.getNotificationMessages()), ugi); - } - } catch (Throwable t) { - LOG.error("HiveHook.run(): failed to process operation {}", hookContext.getOperationName(), t); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HiveHook.run({})", hookContext.getOperationName()); - } - } - - public boolean isConvertHdfsPathToLowerCase() { - return convertHdfsPathToLowerCase; - } - - public String getAwsS3AtlasModelVersion() { - return awsS3AtlasModelVersion; - } - - public boolean getSkipHiveColumnLineageHive20633() { - return skipHiveColumnLineageHive20633; - } - - public int getSkipHiveColumnLineageHive20633InputsThreshold() { - return skipHiveColumnLineageHive20633InputsThreshold; - } - - public List getIgnoreDummyDatabaseName() { - return ignoreDummyDatabaseName; - } - - public List getIgnoreDummyTableName() { - return ignoreDummyTableName; - } - - public String getIgnoreValuesTmpTableNamePrefix() { - return ignoreValuesTmpTableNamePrefix; - } - - public boolean isHiveProcessPopulateDeprecatedAttributes() { - return hiveProcessPopulateDeprecatedAttributes; - } - - public static boolean isSkipTempTables() { - return skipTempTables; - } - - public PreprocessAction getPreprocessActionForHiveTable(String qualifiedName) { - PreprocessAction ret = PreprocessAction.NONE; - - if (qualifiedName != null && (CollectionUtils.isNotEmpty(hiveTablesToIgnore) || CollectionUtils.isNotEmpty(hiveTablesToPrune))) { - ret = hiveTablesCache.get(qualifiedName); - - if (ret == null) { - if (isMatch(qualifiedName, hiveTablesToIgnore)) { - ret = PreprocessAction.IGNORE; - } else if (isMatch(qualifiedName, hiveTablesToPrune)) { - ret = PreprocessAction.PRUNE; - } else { - ret = PreprocessAction.NONE; - } - - hiveTablesCache.put(qualifiedName, ret); - } - } - - return ret; - } - - private boolean isMatch(String name, List patterns) { - boolean ret = false; - - for (Pattern p : patterns) { - if (p.matcher(name).matches()) { - ret = true; - - break; - } - } - - return ret; - } - - public static HiveHookObjectNamesCache getKnownObjects() { - if (knownObjects != null && knownObjects.isCacheExpired()) { - LOG.info("HiveHook.run(): purging cached databaseNames ({}) and tableNames ({})", knownObjects.getCachedDbCount(), knownObjects.getCachedTableCount()); - - knownObjects = new HiveHook.HiveHookObjectNamesCache(nameCacheDatabaseMaxCount, nameCacheTableMaxCount, nameCacheRebuildIntervalSeconds); - } - - return knownObjects; - } - - public String getHostName() { - return hostName; - } - - public static class HiveHookObjectNamesCache { - private final int dbMaxCacheCount; - private final int tblMaxCacheCount; - private final long cacheExpiryTimeMs; - private final Set knownDatabases; - private final Set knownTables; - - public HiveHookObjectNamesCache(int dbMaxCacheCount, int tblMaxCacheCount, long nameCacheRebuildIntervalSeconds) { - this.dbMaxCacheCount = dbMaxCacheCount; - this.tblMaxCacheCount = tblMaxCacheCount; - this.cacheExpiryTimeMs = nameCacheRebuildIntervalSeconds <= 0 ? Long.MAX_VALUE : (System.currentTimeMillis() + (nameCacheRebuildIntervalSeconds * 1000)); - this.knownDatabases = Collections.synchronizedSet(new HashSet<>()); - this.knownTables = Collections.synchronizedSet(new HashSet<>()); - } - - public int getCachedDbCount() { - return knownDatabases.size(); - } - - public int getCachedTableCount() { - return knownTables.size(); - } - - public boolean isCacheExpired() { - return System.currentTimeMillis() > cacheExpiryTimeMs; - } - - public boolean isKnownDatabase(String dbQualifiedName) { - return knownDatabases.contains(dbQualifiedName); - } - - public boolean isKnownTable(String tblQualifiedName) { - return knownTables.contains(tblQualifiedName); - } - - public void addToKnownEntities(Collection entities) { - for (AtlasEntity entity : entities) { - if (StringUtils.equalsIgnoreCase(entity.getTypeName(), HIVE_TYPE_DB)) { - addToKnownDatabase((String) entity.getAttribute(ATTRIBUTE_QUALIFIED_NAME)); - } else if (StringUtils.equalsIgnoreCase(entity.getTypeName(), HIVE_TYPE_TABLE)) { - addToKnownTable((String) entity.getAttribute(ATTRIBUTE_QUALIFIED_NAME)); - } - } - } - - public void addToKnownDatabase(String dbQualifiedName) { - if (knownDatabases.size() < dbMaxCacheCount) { - knownDatabases.add(dbQualifiedName); - } - } - - public void addToKnownTable(String tblQualifiedName) { - if (knownTables.size() < tblMaxCacheCount) { - knownTables.add(tblQualifiedName); - } - } - - public void removeFromKnownDatabase(String dbQualifiedName) { - knownDatabases.remove(dbQualifiedName); - } - - public void removeFromKnownTable(String tblQualifiedName) { - if (tblQualifiedName != null) { - knownTables.remove(tblQualifiedName); - } - } - } -} diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/HiveMetastoreHookImpl.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/HiveMetastoreHookImpl.java deleted file mode 100644 index 33266ce0b34..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/HiveMetastoreHookImpl.java +++ /dev/null @@ -1,216 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook; - -import org.apache.atlas.hive.hook.events.*; -import org.apache.atlas.hook.AtlasHook; -import org.apache.commons.lang.StringUtils; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hive.metastore.MetaStoreEventListener; -import org.apache.hadoop.hive.metastore.api.FieldSchema; -import org.apache.hadoop.hive.metastore.events.*; -import org.apache.hadoop.hive.metastore.utils.SecurityUtils; -import org.apache.hadoop.hive.ql.metadata.Table; -import org.apache.hadoop.hive.ql.plan.HiveOperation; -import org.apache.hadoop.hive.shims.Utils; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -import static org.apache.atlas.hive.hook.events.AlterTableRenameCol.findRenamedColumn; -import static org.apache.atlas.hive.hook.events.BaseHiveEvent.toTable; -import static org.apache.atlas.repository.Constants.HMS_SOURCE; -import static org.apache.hadoop.hive.ql.plan.HiveOperation.*; - -public class HiveMetastoreHookImpl extends MetaStoreEventListener { - private static final Logger LOG = LoggerFactory.getLogger(HiveMetastoreHookImpl.class); - private final HiveHook hiveHook; - private final HiveMetastoreHook hook; - - public HiveMetastoreHookImpl(Configuration config) { - super(config); - - this.hiveHook = new HiveHook(this.getClass().getSimpleName()); - this.hook = new HiveMetastoreHook(); - } - - @Override - public void onCreateDatabase(CreateDatabaseEvent dbEvent) { - HiveOperationContext context = new HiveOperationContext(CREATEDATABASE, dbEvent); - - hook.handleEvent(context); - } - - @Override - public void onDropDatabase(DropDatabaseEvent dbEvent) { - HiveOperationContext context = new HiveOperationContext(DROPDATABASE, dbEvent); - - hook.handleEvent(context); - } - - @Override - public void onAlterDatabase(AlterDatabaseEvent dbEvent) { - HiveOperationContext context = new HiveOperationContext(ALTERDATABASE, dbEvent); - - hook.handleEvent(context); - } - - @Override - public void onCreateTable(CreateTableEvent tableEvent) { - HiveOperationContext context = new HiveOperationContext(CREATETABLE, tableEvent); - - hook.handleEvent(context); - } - - @Override - public void onDropTable(DropTableEvent tableEvent) { - HiveOperationContext context = new HiveOperationContext(DROPTABLE, tableEvent); - - hook.handleEvent(context); - } - - @Override - public void onAlterTable(AlterTableEvent tableEvent) { - HiveOperationContext context = new HiveOperationContext(tableEvent); - Table oldTable = toTable(tableEvent.getOldTable()); - Table newTable = toTable(tableEvent.getNewTable()); - - if (isTableRename(oldTable, newTable)) { - context.setOperation(ALTERTABLE_RENAME); - } else if (isColumnRename(oldTable, newTable, context)) { - context.setOperation(ALTERTABLE_RENAMECOL); - } else if(isAlterTableProperty(tableEvent, "last_modified_time") || - isAlterTableProperty(tableEvent, "transient_lastDdlTime")) { - context.setOperation(ALTERTABLE_PROPERTIES); // map other alter table operations to ALTERTABLE_PROPERTIES - } - - hook.handleEvent(context); - } - - public class HiveMetastoreHook extends AtlasHook { - public HiveMetastoreHook() { - } - - @Override - public String getMessageSource() { - return HMS_SOURCE; - } - - public void handleEvent(HiveOperationContext operContext) { - ListenerEvent listenerEvent = operContext.getEvent(); - - if (!listenerEvent.getStatus()) { - return; - } - - try { - HiveOperation oper = operContext.getOperation(); - AtlasHiveHookContext context = new AtlasHiveHookContext(hiveHook, oper, hiveHook.getKnownObjects(), this, listenerEvent, hiveHook.isSkipTempTables()); - BaseHiveEvent event = null; - - switch (oper) { - case CREATEDATABASE: - event = new CreateDatabase(context); - break; - - case DROPDATABASE: - event = new DropDatabase(context); - break; - - case ALTERDATABASE: - event = new AlterDatabase(context); - break; - - case CREATETABLE: - event = new CreateTable(context); - break; - - case DROPTABLE: - event = new DropTable(context); - break; - - case ALTERTABLE_PROPERTIES: - event = new AlterTable(context); - break; - - case ALTERTABLE_RENAME: - event = new AlterTableRename(context); - break; - - case ALTERTABLE_RENAMECOL: - FieldSchema columnOld = operContext.getColumnOld(); - FieldSchema columnNew = operContext.getColumnNew(); - - event = new AlterTableRenameCol(columnOld, columnNew, context); - break; - - default: - if (LOG.isDebugEnabled()) { - LOG.debug("HiveMetastoreHook.handleEvent({}): operation ignored.", listenerEvent); - } - break; - } - - if (event != null) { - final UserGroupInformation ugi = SecurityUtils.getUGI() == null ? Utils.getUGI() : SecurityUtils.getUGI(); - - super.notifyEntities(event.getNotificationMessages(), ugi); - } - } catch (Throwable t) { - LOG.error("HiveMetastoreHook.handleEvent({}): failed to process operation {}", listenerEvent, t); - } - } - } - - private static boolean isTableRename(Table oldTable, Table newTable) { - String oldTableName = oldTable.getTableName(); - String newTableName = newTable.getTableName(); - - return !StringUtils.equalsIgnoreCase(oldTableName, newTableName); - } - - private static boolean isColumnRename(Table oldTable, Table newTable, HiveOperationContext context) { - FieldSchema columnOld = findRenamedColumn(oldTable, newTable); - FieldSchema columnNew = findRenamedColumn(newTable, oldTable); - boolean isColumnRename = columnOld != null && columnNew != null; - - if (isColumnRename) { - context.setColumnOld(columnOld); - context.setColumnNew(columnNew); - } - - return isColumnRename; - } - - private boolean isAlterTableProperty(AlterTableEvent tableEvent, String propertyToCheck) { - final boolean ret; - String oldTableModifiedTime = tableEvent.getOldTable().getParameters().get(propertyToCheck); - String newTableModifiedTime = tableEvent.getNewTable().getParameters().get(propertyToCheck); - - - if (oldTableModifiedTime == null) { - ret = newTableModifiedTime != null; - } else { - ret = !oldTableModifiedTime.equals(newTableModifiedTime); - } - - return ret; - - } -} \ No newline at end of file diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/HiveOperationContext.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/HiveOperationContext.java deleted file mode 100644 index 23ea4be690d..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/HiveOperationContext.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook; - -import org.apache.hadoop.hive.metastore.api.FieldSchema; -import org.apache.hadoop.hive.metastore.events.ListenerEvent; -import org.apache.hadoop.hive.ql.plan.HiveOperation; - -public class HiveOperationContext { - HiveOperation operation; - ListenerEvent event; - FieldSchema columnOld; - FieldSchema columnNew; - - public HiveOperationContext(ListenerEvent event) { - this(null, event); - } - - public HiveOperationContext(HiveOperation operation, ListenerEvent event) { - setOperation(operation); - setEvent(event); - setColumnOld(null); - setColumnNew(null); - } - - public ListenerEvent getEvent() { - return event; - } - - public void setEvent(ListenerEvent event) { - this.event = event; - } - - public HiveOperation getOperation() { - return operation; - } - - public void setOperation(HiveOperation operation) { - this.operation = operation; - } - - public FieldSchema getColumnOld() { - return columnOld; - } - - public void setColumnOld(FieldSchema columnOld) { - this.columnOld = columnOld; - } - - public FieldSchema getColumnNew() { - return columnNew; - } - - public void setColumnNew(FieldSchema columnNew) { - this.columnNew = columnNew; - } -} diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/AlterDatabase.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/AlterDatabase.java deleted file mode 100644 index d2623b3636d..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/AlterDatabase.java +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.events; - -import org.apache.atlas.hive.hook.AtlasHiveHookContext; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.model.notification.HookNotification.EntityUpdateRequestV2; -import org.apache.commons.collections.CollectionUtils; -import org.apache.hadoop.hive.metastore.api.Database; -import org.apache.hadoop.hive.metastore.events.AlterDatabaseEvent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.List; - -public class AlterDatabase extends CreateDatabase { - private static final Logger LOG = LoggerFactory.getLogger(AlterDatabase.class); - - public AlterDatabase(AtlasHiveHookContext context) { - super(context); - } - - @Override - public List getNotificationMessages() throws Exception { - List ret = null; - AtlasEntitiesWithExtInfo entities = context.isMetastoreHook() ? getHiveMetastoreEntities() : getHiveEntities(); - - if (entities != null && CollectionUtils.isNotEmpty(entities.getEntities())) { - ret = Collections.singletonList(new EntityUpdateRequestV2(getUserName(), entities)); - } - - return ret; - } - - public AtlasEntitiesWithExtInfo getHiveMetastoreEntities() throws Exception { - AtlasEntitiesWithExtInfo ret = new AtlasEntitiesWithExtInfo(); - AlterDatabaseEvent dbEvent = (AlterDatabaseEvent) context.getMetastoreEvent(); - Database oldDb = dbEvent.getOldDatabase(); - Database newDb = dbEvent.getNewDatabase(); - - if (newDb != null) { - AtlasEntity dbEntity = toDbEntity(newDb); - - ret.addEntity(dbEntity); - - addLocationEntities(dbEntity, ret); - } else { - LOG.error("AlterDatabase.getEntities(): failed to retrieve db"); - } - - addProcessedEntities(ret); - - return ret; - } - - public AtlasEntitiesWithExtInfo getHiveEntities() throws Exception { - return super.getHiveEntities(); - } -} \ No newline at end of file diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/AlterTable.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/AlterTable.java deleted file mode 100644 index d2f09cc1086..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/AlterTable.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.events; - -import org.apache.atlas.hive.hook.AtlasHiveHookContext; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.model.notification.HookNotification.EntityUpdateRequestV2; -import org.apache.commons.collections.CollectionUtils; - -import java.util.Collections; -import java.util.List; - -public class AlterTable extends CreateTable { - public AlterTable(AtlasHiveHookContext context) { - super(context); - } - - @Override - public List getNotificationMessages() throws Exception { - List ret = null; - AtlasEntitiesWithExtInfo entities = context.isMetastoreHook() ? getHiveMetastoreEntities() : getHiveEntities(); - - if (entities != null && CollectionUtils.isNotEmpty(entities.getEntities())) { - ret = Collections.singletonList(new EntityUpdateRequestV2(getUserName(), entities)); - } - - return ret; - } -} \ No newline at end of file diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/AlterTableRename.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/AlterTableRename.java deleted file mode 100644 index 6961fa7c2cd..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/AlterTableRename.java +++ /dev/null @@ -1,198 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.events; - -import org.apache.atlas.hive.hook.AtlasHiveHookContext; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityExtInfo; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.model.notification.HookNotification.EntityPartialUpdateRequestV2; -import org.apache.atlas.model.notification.HookNotification.EntityUpdateRequestV2; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.hadoop.hive.metastore.events.AlterTableEvent; -import org.apache.hadoop.hive.ql.hooks.Entity; -import org.apache.hadoop.hive.ql.hooks.WriteEntity; -import org.apache.hadoop.hive.ql.metadata.Table; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.*; - -public class AlterTableRename extends BaseHiveEvent { - private static final Logger LOG = LoggerFactory.getLogger(AlterTableRename.class); - - public AlterTableRename(AtlasHiveHookContext context) { - super(context); - } - - @Override - public List getNotificationMessages() throws Exception { - return context.isMetastoreHook() ? getHiveMetastoreMessages() : getHiveMessages(); - } - - public List getHiveMetastoreMessages() throws Exception { - List ret = new ArrayList<>(); - AlterTableEvent tblEvent = (AlterTableEvent) context.getMetastoreEvent(); - Table oldTable = toTable(tblEvent.getOldTable()); - Table newTable = toTable(tblEvent.getNewTable()); - - if (newTable == null) { - LOG.error("AlterTableRename: renamed table not found in outputs list"); - - return ret; - } - - processTables(oldTable, newTable, ret); - - return ret; - } - - public List getHiveMessages() throws Exception { - List ret = new ArrayList<>(); - Table oldTable; - Table newTable; - - if (CollectionUtils.isEmpty(getInputs())) { - LOG.error("AlterTableRename: old-table not found in inputs list"); - - return ret; - } - - oldTable = getInputs().iterator().next().getTable(); - newTable = null; - - if (CollectionUtils.isNotEmpty(getOutputs())) { - for (WriteEntity entity : getOutputs()) { - if (entity.getType() == Entity.Type.TABLE) { - newTable = entity.getTable(); - - //Hive sends with both old and new table names in the outputs which is weird. So skipping that with the below check - if (StringUtils.equalsIgnoreCase(newTable.getDbName(), oldTable.getDbName()) && - StringUtils.equalsIgnoreCase(newTable.getTableName(), oldTable.getTableName())) { - newTable = null; - - continue; - } - - newTable = getHive().getTable(newTable.getDbName(), newTable.getTableName()); - - break; - } - } - } - - if (newTable == null) { - LOG.error("AlterTableRename: renamed table not found in outputs list"); - - return ret; - } - - processTables(oldTable, newTable, ret); - - return ret; - } - - private void processTables(Table oldTable, Table newTable, List ret) throws Exception { - AtlasEntityWithExtInfo oldTableEntity = toTableEntity(oldTable); - AtlasEntityWithExtInfo renamedTableEntity = toTableEntity(newTable); - - if (oldTableEntity == null || renamedTableEntity == null) { - return; - } - - // update qualifiedName for all columns, partitionKeys, storageDesc - String renamedTableQualifiedName = (String) renamedTableEntity.getEntity().getAttribute(ATTRIBUTE_QUALIFIED_NAME); - - renameColumns((List) oldTableEntity.getEntity().getRelationshipAttribute(ATTRIBUTE_COLUMNS), oldTableEntity, renamedTableQualifiedName, ret); - renameColumns((List) oldTableEntity.getEntity().getRelationshipAttribute(ATTRIBUTE_PARTITION_KEYS), oldTableEntity, renamedTableQualifiedName, ret); - renameStorageDesc(oldTableEntity, renamedTableEntity, ret); - - // set previous name as the alias - renamedTableEntity.getEntity().setAttribute(ATTRIBUTE_ALIASES, Collections.singletonList(oldTable.getTableName())); - - // make a copy of renamedTableEntity to send as partial-update with no relationship attributes - AtlasEntity renamedTableEntityForPartialUpdate = new AtlasEntity(renamedTableEntity.getEntity()); - renamedTableEntityForPartialUpdate.setRelationshipAttributes(null); - - String oldTableQualifiedName = (String) oldTableEntity.getEntity().getAttribute(ATTRIBUTE_QUALIFIED_NAME); - AtlasObjectId oldTableId = new AtlasObjectId(oldTableEntity.getEntity().getTypeName(), ATTRIBUTE_QUALIFIED_NAME, oldTableQualifiedName); - - // update qualifiedName and other attributes (like params - which include lastModifiedTime, lastModifiedBy) of the table - ret.add(new EntityPartialUpdateRequestV2(getUserName(), oldTableId, new AtlasEntityWithExtInfo(renamedTableEntityForPartialUpdate))); - - // to handle cases where Atlas didn't have the oldTable, send a full update - ret.add(new EntityUpdateRequestV2(getUserName(), new AtlasEntitiesWithExtInfo(renamedTableEntity))); - - // partial update relationship attribute ddl - if (!context.isMetastoreHook()) { - AtlasEntity ddlEntity = createHiveDDLEntity(renamedTableEntity.getEntity(), true); - - if (ddlEntity != null) { - ret.add(new HookNotification.EntityCreateRequestV2(getUserName(), new AtlasEntitiesWithExtInfo(ddlEntity))); - } - } - - context.removeFromKnownTable(oldTableQualifiedName); - } - - private void renameColumns(List columns, AtlasEntityExtInfo oldEntityExtInfo, String newTableQualifiedName, List notifications) { - if (CollectionUtils.isNotEmpty(columns)) { - for (AtlasObjectId columnId : columns) { - AtlasEntity oldColumn = oldEntityExtInfo.getEntity(columnId.getGuid()); - AtlasObjectId oldColumnId = new AtlasObjectId(oldColumn.getTypeName(), ATTRIBUTE_QUALIFIED_NAME, oldColumn.getAttribute(ATTRIBUTE_QUALIFIED_NAME)); - AtlasEntity newColumn = new AtlasEntity(oldColumn.getTypeName(), ATTRIBUTE_QUALIFIED_NAME, getColumnQualifiedName(newTableQualifiedName, (String) oldColumn.getAttribute(ATTRIBUTE_NAME))); - - notifications.add(new EntityPartialUpdateRequestV2(getUserName(), oldColumnId, new AtlasEntityWithExtInfo(newColumn))); - } - } - } - - private void renameStorageDesc(AtlasEntityWithExtInfo oldEntityExtInfo, AtlasEntityWithExtInfo newEntityExtInfo, List notifications) { - AtlasEntity oldSd = getStorageDescEntity(oldEntityExtInfo); - AtlasEntity newSd = new AtlasEntity(getStorageDescEntity(newEntityExtInfo)); // make a copy of newSd, since we will be setting relationshipAttributes to 'null' below - // and we need relationship attributes later during entity full update - - if (oldSd != null && newSd != null) { - AtlasObjectId oldSdId = new AtlasObjectId(oldSd.getTypeName(), ATTRIBUTE_QUALIFIED_NAME, oldSd.getAttribute(ATTRIBUTE_QUALIFIED_NAME)); - - newSd.removeAttribute(ATTRIBUTE_TABLE); - newSd.setRelationshipAttributes(null); - - notifications.add(new EntityPartialUpdateRequestV2(getUserName(), oldSdId, new AtlasEntityWithExtInfo(newSd))); - } - } - - private AtlasEntity getStorageDescEntity(AtlasEntityWithExtInfo tableEntity) { - AtlasEntity ret = null; - - if (tableEntity != null && tableEntity.getEntity() != null) { - Object attrSdId = tableEntity.getEntity().getRelationshipAttribute(ATTRIBUTE_STORAGEDESC); - - if (attrSdId instanceof AtlasObjectId) { - ret = tableEntity.getReferredEntity(((AtlasObjectId) attrSdId).getGuid()); - } - } - - return ret; - } -} diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/AlterTableRenameCol.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/AlterTableRenameCol.java deleted file mode 100644 index 29ca920c64b..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/AlterTableRenameCol.java +++ /dev/null @@ -1,136 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.events; - -import org.apache.atlas.hive.hook.AtlasHiveHookContext; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.model.notification.HookNotification.EntityPartialUpdateRequestV2; -import org.apache.commons.collections.CollectionUtils; -import org.apache.hadoop.hive.metastore.api.FieldSchema; -import org.apache.hadoop.hive.metastore.events.AlterTableEvent; -import org.apache.hadoop.hive.ql.metadata.Table; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -public class AlterTableRenameCol extends AlterTable { - private static final Logger LOG = LoggerFactory.getLogger(AlterTableRenameCol.class); - private final FieldSchema columnOld; - private final FieldSchema columnNew; - - public AlterTableRenameCol(AtlasHiveHookContext context) { - this(null, null, context); - } - - public AlterTableRenameCol(FieldSchema columnOld, FieldSchema columnNew, AtlasHiveHookContext context) { - super(context); - - this.columnOld = columnOld; - this.columnNew = columnNew; - } - - @Override - public List getNotificationMessages() throws Exception { - return context.isMetastoreHook() ? getHiveMetastoreMessages() : getHiveMessages(); - } - - public List getHiveMetastoreMessages() throws Exception { - List baseMsgs = super.getNotificationMessages(); - List ret = new ArrayList<>(baseMsgs); - AlterTableEvent tblEvent = (AlterTableEvent) context.getMetastoreEvent(); - Table oldTable = toTable(tblEvent.getOldTable()); - Table newTable = toTable(tblEvent.getNewTable()); - - processColumns(oldTable, newTable, ret); - - return ret; - } - - public List getHiveMessages() throws Exception { - List baseMsgs = super.getNotificationMessages(); - - if (CollectionUtils.isEmpty(getInputs())) { - LOG.error("AlterTableRenameCol: old-table not found in inputs list"); - - return null; - } - - if (CollectionUtils.isEmpty(getOutputs())) { - LOG.error("AlterTableRenameCol: new-table not found in outputs list"); - - return null; - } - - if (CollectionUtils.isEmpty(baseMsgs)) { - LOG.debug("Skipped processing of column-rename (on a temporary table?)"); - - return null; - } - - List ret = new ArrayList<>(baseMsgs); - Table oldTable = getInputs().iterator().next().getTable(); - Table newTable = getOutputs().iterator().next().getTable(); - - if (newTable != null) { - newTable = getHive().getTable(newTable.getDbName(), newTable.getTableName()); - } - - processColumns(oldTable, newTable, ret); - - return ret; - } - - private void processColumns(Table oldTable, Table newTable, List ret) { - FieldSchema changedColumnOld = (columnOld == null) ? findRenamedColumn(oldTable, newTable) : columnOld; - FieldSchema changedColumnNew = (columnNew == null) ? findRenamedColumn(newTable, oldTable) : columnNew; - - if (changedColumnOld != null && changedColumnNew != null) { - AtlasObjectId oldColumnId = new AtlasObjectId(HIVE_TYPE_COLUMN, ATTRIBUTE_QUALIFIED_NAME, getQualifiedName(oldTable, changedColumnOld)); - AtlasEntity newColumn = new AtlasEntity(HIVE_TYPE_COLUMN); - - newColumn.setAttribute(ATTRIBUTE_NAME, changedColumnNew.getName()); - newColumn.setAttribute(ATTRIBUTE_QUALIFIED_NAME, getQualifiedName(newTable, changedColumnNew)); - - ret.add(0, new EntityPartialUpdateRequestV2(getUserName(), oldColumnId, new AtlasEntityWithExtInfo(newColumn))); - } else { - LOG.error("AlterTableRenameCol: no renamed column detected"); - } - } - - public static FieldSchema findRenamedColumn(Table inputTable, Table outputTable) { - FieldSchema ret = null; - List inputColumns = inputTable.getCols(); - List outputColumns = outputTable.getCols(); - - for (FieldSchema inputColumn : inputColumns) { - if (!outputColumns.contains(inputColumn)) { - ret = inputColumn; - - break; - } - } - - return ret; - } -} \ No newline at end of file diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/BaseHiveEvent.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/BaseHiveEvent.java deleted file mode 100644 index 3f358139bea..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/BaseHiveEvent.java +++ /dev/null @@ -1,1189 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.events; - -import org.apache.atlas.hive.hook.AtlasHiveHookContext; -import org.apache.atlas.hive.hook.HiveHook.PreprocessAction; -import org.apache.atlas.utils.PathExtractorContext; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityExtInfo; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.model.instance.AtlasRelatedObjectId; -import org.apache.atlas.model.instance.AtlasStruct; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.type.AtlasTypeUtil; -import org.apache.atlas.utils.AtlasPathExtractorUtil; -import org.apache.atlas.utils.HdfsNameServiceResolver; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections.MapUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.hive.metastore.api.Database; -import org.apache.hadoop.hive.metastore.api.FieldSchema; -import org.apache.hadoop.hive.metastore.api.Order; -import org.apache.hadoop.hive.metastore.api.SerDeInfo; -import org.apache.hadoop.hive.metastore.api.StorageDescriptor; -import org.apache.hadoop.hive.metastore.utils.SecurityUtils; -import org.apache.hadoop.hive.ql.hooks.*; -import org.apache.hadoop.hive.ql.hooks.LineageInfo.BaseColumnInfo; -import org.apache.hadoop.hive.ql.hooks.LineageInfo.DependencyKey; -import org.apache.hadoop.hive.ql.metadata.Hive; -import org.apache.hadoop.hive.ql.metadata.Table; -import org.apache.hadoop.hive.ql.plan.HiveOperation; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.URI; -import java.util.*; - -import static org.apache.atlas.hive.bridge.HiveMetaStoreBridge.getDatabaseName; -import static org.apache.atlas.hive.hook.AtlasHiveHookContext.QNAME_SEP_METADATA_NAMESPACE; -import static org.apache.atlas.hive.hook.AtlasHiveHookContext.QNAME_SEP_ENTITY_NAME; -import static org.apache.atlas.hive.hook.AtlasHiveHookContext.QNAME_SEP_PROCESS; - -public abstract class BaseHiveEvent { - private static final Logger LOG = LoggerFactory.getLogger(BaseHiveEvent.class); - - public static final String HIVE_TYPE_DB = "hive_db"; - public static final String HIVE_TYPE_TABLE = "hive_table"; - public static final String HIVE_TYPE_STORAGEDESC = "hive_storagedesc"; - public static final String HIVE_TYPE_COLUMN = "hive_column"; - public static final String HIVE_TYPE_PROCESS = "hive_process"; - public static final String HIVE_TYPE_COLUMN_LINEAGE = "hive_column_lineage"; - public static final String HIVE_TYPE_SERDE = "hive_serde"; - public static final String HIVE_TYPE_ORDER = "hive_order"; - public static final String HIVE_TYPE_PROCESS_EXECUTION = "hive_process_execution"; - public static final String HIVE_DB_DDL = "hive_db_ddl"; - public static final String HIVE_TABLE_DDL = "hive_table_ddl"; - public static final String HBASE_TYPE_TABLE = "hbase_table"; - public static final String HBASE_TYPE_NAMESPACE = "hbase_namespace"; - public static final String ATTRIBUTE_QUALIFIED_NAME = "qualifiedName"; - public static final String ATTRIBUTE_NAME = "name"; - public static final String ATTRIBUTE_DESCRIPTION = "description"; - public static final String ATTRIBUTE_OWNER = "owner"; - public static final String ATTRIBUTE_CLUSTER_NAME = "clusterName"; - public static final String ATTRIBUTE_LOCATION = "location"; - public static final String ATTRIBUTE_LOCATION_PATH = "locationPath"; - public static final String ATTRIBUTE_PARAMETERS = "parameters"; - public static final String ATTRIBUTE_OWNER_TYPE = "ownerType"; - public static final String ATTRIBUTE_COMMENT = "comment"; - public static final String ATTRIBUTE_CREATE_TIME = "createTime"; - public static final String ATTRIBUTE_LAST_ACCESS_TIME = "lastAccessTime"; - public static final String ATTRIBUTE_VIEW_ORIGINAL_TEXT = "viewOriginalText"; - public static final String ATTRIBUTE_VIEW_EXPANDED_TEXT = "viewExpandedText"; - public static final String ATTRIBUTE_TABLE_TYPE = "tableType"; - public static final String ATTRIBUTE_TEMPORARY = "temporary"; - public static final String ATTRIBUTE_RETENTION = "retention"; - public static final String ATTRIBUTE_DB = "db"; - public static final String ATTRIBUTE_HIVE_DB = "hiveDb"; - public static final String ATTRIBUTE_STORAGEDESC = "sd"; - public static final String ATTRIBUTE_PARTITION_KEYS = "partitionKeys"; - public static final String ATTRIBUTE_COLUMNS = "columns"; - public static final String ATTRIBUTE_INPUT_FORMAT = "inputFormat"; - public static final String ATTRIBUTE_OUTPUT_FORMAT = "outputFormat"; - public static final String ATTRIBUTE_COMPRESSED = "compressed"; - public static final String ATTRIBUTE_BUCKET_COLS = "bucketCols"; - public static final String ATTRIBUTE_NUM_BUCKETS = "numBuckets"; - public static final String ATTRIBUTE_STORED_AS_SUB_DIRECTORIES = "storedAsSubDirectories"; - public static final String ATTRIBUTE_TABLE = "table"; - public static final String ATTRIBUTE_SERDE_INFO = "serdeInfo"; - public static final String ATTRIBUTE_SERIALIZATION_LIB = "serializationLib"; - public static final String ATTRIBUTE_SORT_COLS = "sortCols"; - public static final String ATTRIBUTE_COL_TYPE = "type"; - public static final String ATTRIBUTE_COL_POSITION = "position"; - public static final String ATTRIBUTE_PATH = "path"; - public static final String ATTRIBUTE_NAMESERVICE_ID = "nameServiceId"; - public static final String ATTRIBUTE_INPUTS = "inputs"; - public static final String ATTRIBUTE_OUTPUTS = "outputs"; - public static final String ATTRIBUTE_OPERATION_TYPE = "operationType"; - public static final String ATTRIBUTE_START_TIME = "startTime"; - public static final String ATTRIBUTE_USER_NAME = "userName"; - public static final String ATTRIBUTE_QUERY_TEXT = "queryText"; - public static final String ATTRIBUTE_PROCESS = "process"; - public static final String ATTRIBUTE_PROCESS_EXECUTIONS = "processExecutions"; - public static final String ATTRIBUTE_QUERY_ID = "queryId"; - public static final String ATTRIBUTE_QUERY_PLAN = "queryPlan"; - public static final String ATTRIBUTE_END_TIME = "endTime"; - public static final String ATTRIBUTE_RECENT_QUERIES = "recentQueries"; - public static final String ATTRIBUTE_QUERY = "query"; - public static final String ATTRIBUTE_DEPENDENCY_TYPE = "depenendencyType"; - public static final String ATTRIBUTE_EXPRESSION = "expression"; - public static final String ATTRIBUTE_ALIASES = "aliases"; - public static final String ATTRIBUTE_URI = "uri"; - public static final String ATTRIBUTE_STORAGE_HANDLER = "storage_handler"; - public static final String ATTRIBUTE_NAMESPACE = "namespace"; - public static final String ATTRIBUTE_HOSTNAME = "hostName"; - public static final String ATTRIBUTE_EXEC_TIME = "execTime"; - public static final String ATTRIBUTE_DDL_QUERIES = "ddlQueries"; - public static final String ATTRIBUTE_SERVICE_TYPE = "serviceType"; - public static final String ATTRIBUTE_GUID = "guid"; - public static final String ATTRIBUTE_UNIQUE_ATTRIBUTES = "uniqueAttributes"; - public static final String HBASE_STORAGE_HANDLER_CLASS = "org.apache.hadoop.hive.hbase.HBaseStorageHandler"; - public static final String HBASE_DEFAULT_NAMESPACE = "default"; - public static final String HBASE_NAMESPACE_TABLE_DELIMITER = ":"; - public static final String HBASE_PARAM_TABLE_NAME = "hbase.table.name"; - public static final long MILLIS_CONVERT_FACTOR = 1000; - public static final String HDFS_PATH_PREFIX = "hdfs://"; - public static final String EMPTY_ATTRIBUTE_VALUE = ""; - - public static final String RELATIONSHIP_DATASET_PROCESS_INPUTS = "dataset_process_inputs"; - public static final String RELATIONSHIP_PROCESS_DATASET_OUTPUTS = "process_dataset_outputs"; - public static final String RELATIONSHIP_HIVE_PROCESS_COLUMN_LINEAGE = "hive_process_column_lineage"; - public static final String RELATIONSHIP_HIVE_TABLE_DB = "hive_table_db"; - public static final String RELATIONSHIP_HIVE_TABLE_PART_KEYS = "hive_table_partitionkeys"; - public static final String RELATIONSHIP_HIVE_TABLE_COLUMNS = "hive_table_columns"; - public static final String RELATIONSHIP_HIVE_TABLE_STORAGE_DESC = "hive_table_storagedesc"; - public static final String RELATIONSHIP_HIVE_PROCESS_PROCESS_EXE = "hive_process_process_executions"; - public static final String RELATIONSHIP_HIVE_DB_DDL_QUERIES = "hive_db_ddl_queries"; - public static final String RELATIONSHIP_HIVE_DB_LOCATION = "hive_db_location"; - public static final String RELATIONSHIP_HIVE_TABLE_DDL_QUERIES = "hive_table_ddl_queries"; - public static final String RELATIONSHIP_HBASE_TABLE_NAMESPACE = "hbase_table_namespace"; - - - public static final Map OWNER_TYPE_TO_ENUM_VALUE = new HashMap<>(); - - protected final boolean skipTempTables; - - static { - OWNER_TYPE_TO_ENUM_VALUE.put(1, "USER"); - OWNER_TYPE_TO_ENUM_VALUE.put(2, "ROLE"); - OWNER_TYPE_TO_ENUM_VALUE.put(3, "GROUP"); - } - - protected final AtlasHiveHookContext context; - - - protected BaseHiveEvent(AtlasHiveHookContext context) { - this.context = context; - this.skipTempTables = context.isSkipTempTables(); - } - - public AtlasHiveHookContext getContext() { - return context; - } - - public List getNotificationMessages() throws Exception { - return null; - } - - public static long getTableCreateTime(Table table) { - return table.getTTable() != null ? (table.getTTable().getCreateTime() * MILLIS_CONVERT_FACTOR) : System.currentTimeMillis(); - } - - public static String getTableOwner(Table table) { - return table.getTTable() != null ? (table.getOwner()): ""; - } - - - public static List getObjectIds(List entities) { - final List ret; - - if (CollectionUtils.isNotEmpty(entities)) { - ret = new ArrayList<>(entities.size()); - - for (AtlasEntity entity : entities) { - ret.add(AtlasTypeUtil.getObjectId(entity)); - } - } else { - ret = Collections.emptyList(); - } - - return ret; - } - - - protected void addProcessedEntities(AtlasEntitiesWithExtInfo entitiesWithExtInfo) { - for (AtlasEntity entity : context.getEntities()) { - entitiesWithExtInfo.addReferredEntity(entity); - } - - entitiesWithExtInfo.compact(); - - context.addToKnownEntities(entitiesWithExtInfo.getEntities()); - - if (entitiesWithExtInfo.getReferredEntities() != null) { - context.addToKnownEntities(entitiesWithExtInfo.getReferredEntities().values()); - } - } - - protected AtlasEntity getInputOutputEntity(Entity entity, AtlasEntityExtInfo entityExtInfo, boolean skipTempTables) throws Exception { - AtlasEntity ret = null; - - switch(entity.getType()) { - case TABLE: - case PARTITION: - case DFS_DIR: - case LOCAL_DIR: { - ret = toAtlasEntity(entity, entityExtInfo, skipTempTables); - } - break; - } - - return ret; - } - - protected AtlasEntity toAtlasEntity(Entity entity, AtlasEntityExtInfo entityExtInfo, boolean skipTempTables) throws Exception { - AtlasEntity ret = null; - - switch (entity.getType()) { - case DATABASE: { - String dbName = getDatabaseName(entity.getDatabase()); - - if (!context.getIgnoreDummyDatabaseName().contains(dbName)) { - Database db = getHive().getDatabase(dbName); - - ret = toDbEntity(db); - } - } - break; - - case TABLE: - case PARTITION: { - String dbName = entity.getTable().getDbName(); - String tableName = entity.getTable().getTableName(); - boolean skipTable = StringUtils.isNotEmpty(context.getIgnoreValuesTmpTableNamePrefix()) && tableName.toLowerCase().startsWith(context.getIgnoreValuesTmpTableNamePrefix()); - - if (!skipTable) { - skipTable = context.getIgnoreDummyTableName().contains(tableName) && context.getIgnoreDummyDatabaseName().contains(dbName); - } - - if (!skipTable) { - skipTable = skipTempTables && entity.getTable().isTemporary(); - } - - if (!skipTable) { - Table table = getHive().getTable(dbName, tableName); - - ret = toTableEntity(table, entityExtInfo); - } else { - context.registerSkippedEntity(entity); - } - } - break; - - case DFS_DIR: - case LOCAL_DIR: { - URI location = entity.getLocation(); - - if (location != null) { - ret = getPathEntity(new Path(entity.getLocation()), entityExtInfo); - } - } - break; - - default: - break; - } - - return ret; - } - - protected AtlasEntity toDbEntity(Database db) throws Exception { - String dbName = getDatabaseName(db); - String dbQualifiedName = getQualifiedName(db); - boolean isKnownDatabase = context.isKnownDatabase(dbQualifiedName); - AtlasEntity ret = context.getEntity(dbQualifiedName); - - if (ret == null) { - ret = new AtlasEntity(HIVE_TYPE_DB); - - // if this DB was sent in an earlier notification, set 'guid' to null - which will: - // - result in this entity to be not included in 'referredEntities' - // - cause Atlas server to resolve the entity by its qualifiedName - if (isKnownDatabase) { - ret.setGuid(null); - } - - ret.setAttribute(ATTRIBUTE_QUALIFIED_NAME, dbQualifiedName); - ret.setAttribute(ATTRIBUTE_NAME, dbName); - - if (StringUtils.isNotEmpty(db.getDescription())) { - ret.setAttribute(ATTRIBUTE_DESCRIPTION, db.getDescription()); - } - - ret.setAttribute(ATTRIBUTE_OWNER, db.getOwnerName()); - - ret.setAttribute(ATTRIBUTE_CLUSTER_NAME, getMetadataNamespace()); - ret.setAttribute(ATTRIBUTE_LOCATION, HdfsNameServiceResolver.getPathWithNameServiceID(db.getLocationUri())); - ret.setAttribute(ATTRIBUTE_PARAMETERS, db.getParameters()); - - if (db.getOwnerType() != null) { - ret.setAttribute(ATTRIBUTE_OWNER_TYPE, OWNER_TYPE_TO_ENUM_VALUE.get(db.getOwnerType().getValue())); - } - - context.putEntity(dbQualifiedName, ret); - } - - return ret; - } - - protected AtlasEntityWithExtInfo toTableEntity(Table table) throws Exception { - AtlasEntityWithExtInfo ret = new AtlasEntityWithExtInfo(); - - AtlasEntity entity = toTableEntity(table, ret); - - if (entity != null) { - ret.setEntity(entity); - } else { - ret = null; - } - - return ret; - } - - protected AtlasEntity toTableEntity(Table table, AtlasEntitiesWithExtInfo entities) throws Exception { - AtlasEntity ret = toTableEntity(table, (AtlasEntityExtInfo) entities); - - if (ret != null) { - entities.addEntity(ret); - } - - return ret; - } - - protected AtlasEntity toTableEntity(Table table, AtlasEntityExtInfo entityExtInfo) throws Exception { - Database db = getDatabases(table.getDbName()); - AtlasEntity dbEntity = toDbEntity(db); - - if (entityExtInfo != null) { - if (dbEntity != null) { - entityExtInfo.addReferredEntity(dbEntity); - } - } - - AtlasEntity ret = toTableEntity(AtlasTypeUtil.getObjectId(dbEntity), table, entityExtInfo); - - return ret; - } - - protected AtlasEntity toTableEntity(AtlasObjectId dbId, Table table, AtlasEntityExtInfo entityExtInfo) throws Exception { - String tblQualifiedName = getQualifiedName(table); - boolean isKnownTable = context.isKnownTable(tblQualifiedName); - - AtlasEntity ret = context.getEntity(tblQualifiedName); - - if (ret == null) { - PreprocessAction action = context.getPreprocessActionForHiveTable(tblQualifiedName); - - if (action == PreprocessAction.IGNORE) { - LOG.info("ignoring table {}", tblQualifiedName); - } else { - ret = new AtlasEntity(HIVE_TYPE_TABLE); - - // if this table was sent in an earlier notification, set 'guid' to null - which will: - // - result in this entity to be not included in 'referredEntities' - // - cause Atlas server to resolve the entity by its qualifiedName - if (isKnownTable && !isAlterTableOperation()) { - ret.setGuid(null); - } - - long createTime = getTableCreateTime(table); - long lastAccessTime = table.getLastAccessTime() > 0 ? (table.getLastAccessTime() * MILLIS_CONVERT_FACTOR) : createTime; - - AtlasRelatedObjectId dbRelatedObject = new AtlasRelatedObjectId(dbId, RELATIONSHIP_HIVE_TABLE_DB); - - ret.setRelationshipAttribute(ATTRIBUTE_DB, dbRelatedObject ); - ret.setAttribute(ATTRIBUTE_QUALIFIED_NAME, tblQualifiedName); - ret.setAttribute(ATTRIBUTE_NAME, table.getTableName().toLowerCase()); - ret.setAttribute(ATTRIBUTE_OWNER, table.getOwner()); - ret.setAttribute(ATTRIBUTE_CREATE_TIME, createTime); - ret.setAttribute(ATTRIBUTE_LAST_ACCESS_TIME, lastAccessTime); - ret.setAttribute(ATTRIBUTE_RETENTION, table.getRetention()); - ret.setAttribute(ATTRIBUTE_PARAMETERS, table.getParameters()); - ret.setAttribute(ATTRIBUTE_COMMENT, table.getParameters().get(ATTRIBUTE_COMMENT)); - ret.setAttribute(ATTRIBUTE_TABLE_TYPE, table.getTableType().name()); - ret.setAttribute(ATTRIBUTE_TEMPORARY, table.isTemporary()); - - if (table.getViewOriginalText() != null) { - ret.setAttribute(ATTRIBUTE_VIEW_ORIGINAL_TEXT, table.getViewOriginalText()); - } - - if (table.getViewExpandedText() != null) { - ret.setAttribute(ATTRIBUTE_VIEW_EXPANDED_TEXT, table.getViewExpandedText()); - } - - boolean pruneTable = table.isTemporary() || action == PreprocessAction.PRUNE; - - if (pruneTable) { - LOG.info("ignoring details of table {}", tblQualifiedName); - } else { - AtlasObjectId tableId = AtlasTypeUtil.getObjectId(ret); - AtlasEntity sd = getStorageDescEntity(tableId, table); - List partitionKeys = getColumnEntities(tableId, table, table.getPartitionKeys(), RELATIONSHIP_HIVE_TABLE_PART_KEYS); - List columns = getColumnEntities(tableId, table, table.getCols(), RELATIONSHIP_HIVE_TABLE_COLUMNS); - - - - if (entityExtInfo != null) { - entityExtInfo.addReferredEntity(sd); - - if (partitionKeys != null) { - for (AtlasEntity partitionKey : partitionKeys) { - entityExtInfo.addReferredEntity(partitionKey); - } - } - - if (columns != null) { - for (AtlasEntity column : columns) { - entityExtInfo.addReferredEntity(column); - } - } - } - - - ret.setRelationshipAttribute(ATTRIBUTE_STORAGEDESC, AtlasTypeUtil.getAtlasRelatedObjectId(sd, RELATIONSHIP_HIVE_TABLE_STORAGE_DESC)); - ret.setRelationshipAttribute(ATTRIBUTE_PARTITION_KEYS, AtlasTypeUtil.getAtlasRelatedObjectIds(partitionKeys, RELATIONSHIP_HIVE_TABLE_PART_KEYS)); - ret.setRelationshipAttribute(ATTRIBUTE_COLUMNS, AtlasTypeUtil.getAtlasRelatedObjectIds(columns, RELATIONSHIP_HIVE_TABLE_COLUMNS)); - } - - context.putEntity(tblQualifiedName, ret); - } - } - - return ret; - } - - protected AtlasEntity getStorageDescEntity(AtlasObjectId tableId, Table table) { - String sdQualifiedName = getQualifiedName(table, table.getSd()); - boolean isKnownTable = tableId.getGuid() == null; - - AtlasEntity ret = context.getEntity(sdQualifiedName); - - if (ret == null) { - ret = new AtlasEntity(HIVE_TYPE_STORAGEDESC); - - // if sd's table was sent in an earlier notification, set 'guid' to null - which will: - // - result in this entity to be not included in 'referredEntities' - // - cause Atlas server to resolve the entity by its qualifiedName - if (isKnownTable) { - ret.setGuid(null); - } - - StorageDescriptor sd = table.getSd(); - - AtlasRelatedObjectId tableRelatedObject = new AtlasRelatedObjectId(tableId, RELATIONSHIP_HIVE_TABLE_STORAGE_DESC); - - ret.setRelationshipAttribute(ATTRIBUTE_TABLE, tableRelatedObject); - ret.setAttribute(ATTRIBUTE_QUALIFIED_NAME, sdQualifiedName); - ret.setAttribute(ATTRIBUTE_PARAMETERS, sd.getParameters()); - ret.setAttribute(ATTRIBUTE_LOCATION, HdfsNameServiceResolver.getPathWithNameServiceID(sd.getLocation())); - ret.setAttribute(ATTRIBUTE_INPUT_FORMAT, sd.getInputFormat()); - ret.setAttribute(ATTRIBUTE_OUTPUT_FORMAT, sd.getOutputFormat()); - ret.setAttribute(ATTRIBUTE_COMPRESSED, sd.isCompressed()); - ret.setAttribute(ATTRIBUTE_NUM_BUCKETS, sd.getNumBuckets()); - ret.setAttribute(ATTRIBUTE_STORED_AS_SUB_DIRECTORIES, sd.isStoredAsSubDirectories()); - - if (sd.getBucketCols() != null && sd.getBucketCols().size() > 0) { - ret.setAttribute(ATTRIBUTE_BUCKET_COLS, sd.getBucketCols()); - } - - if (sd.getSerdeInfo() != null) { - AtlasStruct serdeInfo = new AtlasStruct(HIVE_TYPE_SERDE); - SerDeInfo sdSerDeInfo = sd.getSerdeInfo(); - - serdeInfo.setAttribute(ATTRIBUTE_NAME, sdSerDeInfo.getName()); - serdeInfo.setAttribute(ATTRIBUTE_SERIALIZATION_LIB, sdSerDeInfo.getSerializationLib()); - serdeInfo.setAttribute(ATTRIBUTE_PARAMETERS, sdSerDeInfo.getParameters()); - - ret.setAttribute(ATTRIBUTE_SERDE_INFO, serdeInfo); - } - - if (CollectionUtils.isNotEmpty(sd.getSortCols())) { - List sortCols = new ArrayList<>(sd.getSortCols().size()); - - for (Order sdSortCol : sd.getSortCols()) { - AtlasStruct sortcol = new AtlasStruct(HIVE_TYPE_ORDER); - - sortcol.setAttribute("col", sdSortCol.getCol()); - sortcol.setAttribute("order", sdSortCol.getOrder()); - - sortCols.add(sortcol); - } - - ret.setAttribute(ATTRIBUTE_SORT_COLS, sortCols); - } - - context.putEntity(sdQualifiedName, ret); - } - - return ret; - } - - protected List getColumnEntities(AtlasObjectId tableId, Table table, List fieldSchemas, String relationshipType) { - List ret = new ArrayList<>(); - boolean isKnownTable = tableId.getGuid() == null; - int columnPosition = 0; - - if (CollectionUtils.isNotEmpty(fieldSchemas)) { - for (FieldSchema fieldSchema : fieldSchemas) { - String colQualifiedName = getQualifiedName(table, fieldSchema); - AtlasEntity column = context.getEntity(colQualifiedName); - - if (column == null) { - column = new AtlasEntity(HIVE_TYPE_COLUMN); - - // if column's table was sent in an earlier notification, set 'guid' to null - which will: - // - result in this entity to be not included in 'referredEntities' - // - cause Atlas server to resolve the entity by its qualifiedName - if (isKnownTable) { - column.setGuid(null); - } - AtlasRelatedObjectId relatedObjectId = new AtlasRelatedObjectId(tableId, relationshipType); - column.setRelationshipAttribute(ATTRIBUTE_TABLE, (relatedObjectId)); - column.setAttribute(ATTRIBUTE_QUALIFIED_NAME, colQualifiedName); - column.setAttribute(ATTRIBUTE_NAME, fieldSchema.getName()); - column.setAttribute(ATTRIBUTE_OWNER, table.getOwner()); - column.setAttribute(ATTRIBUTE_COL_TYPE, fieldSchema.getType()); - column.setAttribute(ATTRIBUTE_COL_POSITION, columnPosition++); - column.setAttribute(ATTRIBUTE_COMMENT, fieldSchema.getComment()); - - context.putEntity(colQualifiedName, column); - } - - ret.add(column); - } - } - - return ret; - } - - protected AtlasEntity getPathEntity(Path path, AtlasEntityExtInfo extInfo) { - String strPath = path.toString(); - String metadataNamespace = getMetadataNamespace(); - boolean isConvertPathToLowerCase = strPath.startsWith(HDFS_PATH_PREFIX) && context.isConvertHdfsPathToLowerCase(); - PathExtractorContext pathExtractorContext = new PathExtractorContext(metadataNamespace, context.getQNameToEntityMap(), - isConvertPathToLowerCase, context.getAwsS3AtlasModelVersion()); - - AtlasEntityWithExtInfo entityWithExtInfo = AtlasPathExtractorUtil.getPathEntity(path, pathExtractorContext); - - if (entityWithExtInfo.getReferredEntities() != null){ - for (AtlasEntity entity : entityWithExtInfo.getReferredEntities().values()) { - extInfo.addReferredEntity(entity); - } - } - - return entityWithExtInfo.getEntity(); - } - - protected AtlasEntity getHiveProcessEntity(List inputs, List outputs) throws Exception { - AtlasEntity ret = new AtlasEntity(HIVE_TYPE_PROCESS); - String queryStr = getQueryString(); - String qualifiedName = getQualifiedName(inputs, outputs); - - if (queryStr != null) { - queryStr = queryStr.toLowerCase().trim(); - } - - ret.setAttribute(ATTRIBUTE_OPERATION_TYPE, getOperationName()); - - if (context.isMetastoreHook()) { - HiveOperation operation = context.getHiveOperation(); - - if (operation == HiveOperation.CREATETABLE || operation == HiveOperation.CREATETABLE_AS_SELECT) { - AtlasEntity table = outputs.get(0); - long createTime = Long.valueOf((Long)table.getAttribute(ATTRIBUTE_CREATE_TIME)); - qualifiedName = (String) table.getAttribute(ATTRIBUTE_QUALIFIED_NAME) + QNAME_SEP_PROCESS + createTime; - - ret.setAttribute(ATTRIBUTE_NAME, "dummyProcess:" + UUID.randomUUID()); - ret.setAttribute(ATTRIBUTE_OPERATION_TYPE, operation.getOperationName()); - } - } - - ret.setAttribute(ATTRIBUTE_QUALIFIED_NAME, qualifiedName); - ret.setAttribute(ATTRIBUTE_NAME, qualifiedName); - ret.setRelationshipAttribute(ATTRIBUTE_INPUTS, AtlasTypeUtil.getAtlasRelatedObjectIds(inputs, RELATIONSHIP_DATASET_PROCESS_INPUTS)); - ret.setRelationshipAttribute(ATTRIBUTE_OUTPUTS, AtlasTypeUtil.getAtlasRelatedObjectIds(outputs, RELATIONSHIP_PROCESS_DATASET_OUTPUTS)); - - // We are setting an empty value to these attributes, since now we have a new entity type called hive process - // execution which captures these values. We have to set empty values here because these attributes are - // mandatory attributes for hive process entity type. - ret.setAttribute(ATTRIBUTE_START_TIME, System.currentTimeMillis()); - ret.setAttribute(ATTRIBUTE_END_TIME, System.currentTimeMillis()); - - if (context.isHiveProcessPopulateDeprecatedAttributes()) { - ret.setAttribute(ATTRIBUTE_USER_NAME, getUserName()); - ret.setAttribute(ATTRIBUTE_QUERY_TEXT, queryStr); - ret.setAttribute(ATTRIBUTE_QUERY_ID, getQueryId()); - } else { - ret.setAttribute(ATTRIBUTE_USER_NAME, EMPTY_ATTRIBUTE_VALUE); - ret.setAttribute(ATTRIBUTE_QUERY_TEXT, EMPTY_ATTRIBUTE_VALUE); - ret.setAttribute(ATTRIBUTE_QUERY_ID, EMPTY_ATTRIBUTE_VALUE); - } - - ret.setAttribute(ATTRIBUTE_QUERY_PLAN, "Not Supported"); - ret.setAttribute(ATTRIBUTE_RECENT_QUERIES, Collections.singletonList(queryStr)); - ret.setAttribute(ATTRIBUTE_CLUSTER_NAME, getMetadataNamespace()); - - return ret; - } - - protected AtlasEntity getHiveProcessExecutionEntity(AtlasEntity hiveProcess) throws Exception { - AtlasEntity ret = new AtlasEntity(HIVE_TYPE_PROCESS_EXECUTION); - String queryStr = getQueryString(); - - if (queryStr != null) { - queryStr = queryStr.toLowerCase().trim(); - } - - Long endTime = System.currentTimeMillis(); - ret.setAttribute(ATTRIBUTE_QUALIFIED_NAME, hiveProcess.getAttribute(ATTRIBUTE_QUALIFIED_NAME).toString() + - QNAME_SEP_PROCESS + getQueryStartTime().toString() + - QNAME_SEP_PROCESS + endTime.toString()); - ret.setAttribute(ATTRIBUTE_NAME, ret.getAttribute(ATTRIBUTE_QUALIFIED_NAME)); - ret.setAttribute(ATTRIBUTE_START_TIME, getQueryStartTime()); - ret.setAttribute(ATTRIBUTE_END_TIME, endTime); - ret.setAttribute(ATTRIBUTE_USER_NAME, getUserName()); - ret.setAttribute(ATTRIBUTE_QUERY_TEXT, queryStr); - ret.setAttribute(ATTRIBUTE_QUERY_ID, getQueryId()); - ret.setAttribute(ATTRIBUTE_QUERY_PLAN, "Not Supported"); - ret.setAttribute(ATTRIBUTE_HOSTNAME, getContext().getHostName()); // - AtlasRelatedObjectId hiveProcessRelationObjectId = AtlasTypeUtil.toAtlasRelatedObjectId(hiveProcess, RELATIONSHIP_HIVE_PROCESS_PROCESS_EXE); - ret.setRelationshipAttribute(ATTRIBUTE_PROCESS, hiveProcessRelationObjectId); - return ret; - } - - protected AtlasEntity createHiveDDLEntity(AtlasEntity dbOrTable) { - return createHiveDDLEntity(dbOrTable, false); - } - - protected AtlasEntity createHiveDDLEntity(AtlasEntity dbOrTable, boolean excludeEntityGuid) { - AtlasObjectId objId = AtlasTypeUtil.getObjectId(dbOrTable); - AtlasEntity hiveDDL = null; - - if (excludeEntityGuid) { - objId.setGuid(null); - } - AtlasRelatedObjectId objIdRelatedObject = new AtlasRelatedObjectId(objId); - - if (StringUtils.equals(objId.getTypeName(), HIVE_TYPE_DB)) { - hiveDDL = new AtlasEntity(HIVE_DB_DDL); - objIdRelatedObject.setRelationshipType(RELATIONSHIP_HIVE_DB_DDL_QUERIES); - hiveDDL.setRelationshipAttribute(ATTRIBUTE_DB, objIdRelatedObject); - } else if (StringUtils.equals(objId.getTypeName(), HIVE_TYPE_TABLE)) { - hiveDDL = new AtlasEntity(HIVE_TABLE_DDL); - objIdRelatedObject.setRelationshipType(RELATIONSHIP_HIVE_TABLE_DDL_QUERIES); - hiveDDL.setRelationshipAttribute( ATTRIBUTE_TABLE, objIdRelatedObject); - } - - if (hiveDDL != null) { - hiveDDL.setAttribute(ATTRIBUTE_SERVICE_TYPE, "hive"); - hiveDDL.setAttribute(ATTRIBUTE_EXEC_TIME, getQueryStartTime()); - hiveDDL.setAttribute(ATTRIBUTE_QUERY_TEXT, getQueryString()); - hiveDDL.setAttribute(ATTRIBUTE_USER_NAME, getUserName()); - hiveDDL.setAttribute(ATTRIBUTE_NAME, getQueryString()); - hiveDDL.setAttribute(ATTRIBUTE_QUALIFIED_NAME, dbOrTable.getAttribute(ATTRIBUTE_QUALIFIED_NAME).toString() - + QNAME_SEP_PROCESS + getQueryStartTime().toString()); - } - - return hiveDDL; - } - - protected AtlasEntity createHiveLocationEntity(AtlasEntity dbEntity, AtlasEntitiesWithExtInfo extInfoEntity) { - AtlasEntity ret = null; - String locationUri = (String)dbEntity.getAttribute(ATTRIBUTE_LOCATION); - - if (StringUtils.isNotEmpty(locationUri)) { - Path path = null; - - try { - path = new Path(locationUri); - } catch (IllegalArgumentException excp) { - LOG.warn("failed to create Path from locationUri {}", locationUri, excp); - } - - if (path != null) { - ret = getPathEntity(path, extInfoEntity); - - if (ret != null) { - AtlasRelatedObjectId dbRelatedObjectId = AtlasTypeUtil.getAtlasRelatedObjectId(dbEntity, RELATIONSHIP_HIVE_DB_LOCATION); - - ret.setRelationshipAttribute(ATTRIBUTE_HIVE_DB, dbRelatedObjectId); - } - } - } - - return ret; - } - - protected String getMetadataNamespace() { - return context.getMetadataNamespace(); - } - - protected Database getDatabases(String dbName) throws Exception { - return context.isMetastoreHook() ? context.getMetastoreHandler().get_database(dbName) : - context.getHive().getDatabase(dbName); - } - - protected Hive getHive() { - return context.getHive(); - } - - protected Set getInputs() { - return context != null ? context.getInputs() : Collections.emptySet(); - } - - protected Set getOutputs() { - return context != null ? context.getOutputs() : Collections.emptySet(); - } - - protected LineageInfo getLineageInfo() { - return context != null ? context.getLineageInfo() : null; - } - - protected String getQueryString() { - return isHiveContextValid() ? context.getHiveContext().getQueryPlan().getQueryStr() : null; - } - - protected String getOperationName() { - return isHiveContextValid() ? context.getHiveContext().getOperationName() : null; - } - - protected String getHiveUserName() { - return isHiveContextValid() ? context.getHiveContext().getUserName() : null; - } - - protected UserGroupInformation getUgi() { - return isHiveContextValid() ? context.getHiveContext().getUgi() : null; - } - - protected Long getQueryStartTime() { - return isHiveContextValid() ? context.getHiveContext().getQueryPlan().getQueryStartTime() : System.currentTimeMillis(); - } - - protected String getQueryId() { - return isHiveContextValid() ? context.getHiveContext().getQueryPlan().getQueryId() : null; - } - - private boolean isHiveContextValid() { - return context != null && context.getHiveContext() != null; - } - - protected String getUserName() { - String ret = null; - UserGroupInformation ugi = null; - - if (context.isMetastoreHook()) { - try { - ugi = SecurityUtils.getUGI(); - } catch (Exception e) { - //do nothing - } - } else { - ret = getHiveUserName(); - - if (StringUtils.isEmpty(ret)) { - ugi = getUgi(); - } - } - - if (ugi != null) { - ret = ugi.getShortUserName(); - } - - if (StringUtils.isEmpty(ret)) { - try { - ret = UserGroupInformation.getCurrentUser().getShortUserName(); - } catch (IOException e) { - LOG.warn("Failed for UserGroupInformation.getCurrentUser() ", e); - - ret = System.getProperty("user.name"); - } - } - - return ret; - } - - protected String getQualifiedName(Entity entity) throws Exception { - switch (entity.getType()) { - case DATABASE: - return getQualifiedName(entity.getDatabase()); - - case TABLE: - case PARTITION: - return getQualifiedName(entity.getTable()); - - case DFS_DIR: - case LOCAL_DIR: - return getQualifiedName(entity.getLocation()); - } - - return null; - } - - protected String getQualifiedName(Database db) { - return context.getQualifiedName(db); - } - - protected String getQualifiedName(Table table) { - return context.getQualifiedName(table); - } - - protected String getQualifiedName(Table table, StorageDescriptor sd) { - return getQualifiedName(table) + "_storage"; - } - - protected String getQualifiedName(Table table, FieldSchema column) { - String tblQualifiedName = getQualifiedName(table); - - int sepPos = tblQualifiedName.lastIndexOf(QNAME_SEP_METADATA_NAMESPACE); - - if (sepPos == -1) { - return tblQualifiedName + QNAME_SEP_ENTITY_NAME + column.getName().toLowerCase(); - } else { - return tblQualifiedName.substring(0, sepPos) + QNAME_SEP_ENTITY_NAME + column.getName().toLowerCase() + tblQualifiedName.substring(sepPos); - } - } - - protected String getQualifiedName(DependencyKey column) { - String dbName = column.getDataContainer().getTable().getDbName(); - String tableName = column.getDataContainer().getTable().getTableName(); - String colName = column.getFieldSchema().getName(); - - return getQualifiedName(dbName, tableName, colName); - } - - protected String getQualifiedName(BaseColumnInfo column) { - String dbName = column.getTabAlias().getTable().getDbName(); - String tableName = column.getTabAlias().getTable().getTableName(); - String colName = column.getColumn() != null ? column.getColumn().getName() : null; - String metadataNamespace = getMetadataNamespace(); - - if (colName == null) { - return (dbName + QNAME_SEP_ENTITY_NAME + tableName + QNAME_SEP_METADATA_NAMESPACE).toLowerCase() + metadataNamespace; - } else { - return (dbName + QNAME_SEP_ENTITY_NAME + tableName + QNAME_SEP_ENTITY_NAME + colName + QNAME_SEP_METADATA_NAMESPACE).toLowerCase() + metadataNamespace; - } - } - - protected String getQualifiedName(String dbName, String tableName, String colName) { - return (dbName + QNAME_SEP_ENTITY_NAME + tableName + QNAME_SEP_ENTITY_NAME + colName + QNAME_SEP_METADATA_NAMESPACE).toLowerCase() + getMetadataNamespace(); - } - - protected String getQualifiedName(URI location) { - String strPath = new Path(location).toString(); - - if (strPath.startsWith(HDFS_PATH_PREFIX) && context.isConvertHdfsPathToLowerCase()) { - strPath = strPath.toLowerCase(); - } - - String nameServiceID = HdfsNameServiceResolver.getNameServiceIDForPath(strPath); - String attrPath = StringUtils.isEmpty(nameServiceID) ? strPath : HdfsNameServiceResolver.getPathWithNameServiceID(strPath); - - return getQualifiedName(attrPath); - } - - protected String getQualifiedName(String path) { - if (path.startsWith(HdfsNameServiceResolver.HDFS_SCHEME)) { - return path + QNAME_SEP_METADATA_NAMESPACE + getMetadataNamespace(); - } - - return path.toLowerCase(); - } - - protected String getColumnQualifiedName(String tblQualifiedName, String columnName) { - int sepPos = tblQualifiedName.lastIndexOf(QNAME_SEP_METADATA_NAMESPACE); - - if (sepPos == -1) { - return tblQualifiedName + QNAME_SEP_ENTITY_NAME + columnName.toLowerCase(); - } else { - return tblQualifiedName.substring(0, sepPos) + QNAME_SEP_ENTITY_NAME + columnName.toLowerCase() + tblQualifiedName.substring(sepPos); - } - - } - - protected String getQualifiedName(List inputs, List outputs) throws Exception { - HiveOperation operation = context.getHiveOperation(); - - if (operation == HiveOperation.CREATETABLE || - operation == HiveOperation.CREATETABLE_AS_SELECT || - operation == HiveOperation.CREATEVIEW || - operation == HiveOperation.ALTERVIEW_AS || - operation == HiveOperation.ALTERTABLE_LOCATION) { - List sortedEntities = new ArrayList<>(getOutputs()); - - Collections.sort(sortedEntities, entityComparator); - - for (Entity entity : sortedEntities) { - if (entity.getType() == Entity.Type.TABLE) { - Table table = entity.getTable(); - - table = getHive().getTable(table.getDbName(), table.getTableName()); - - long createTime = getTableCreateTime(table); - - return getQualifiedName(table) + QNAME_SEP_PROCESS + createTime; - } - } - } - - String qualifiedName = null; - String operationName = getOperationName(); - - if (operationName != null) { - StringBuilder sb = new StringBuilder(operationName); - - boolean ignoreHDFSPaths = ignoreHDFSPathsinProcessQualifiedName(); - - addToProcessQualifiedName(sb, getInputs(), ignoreHDFSPaths); - sb.append("->"); - addToProcessQualifiedName(sb, getOutputs(), ignoreHDFSPaths); - - qualifiedName = sb.toString(); - } - - - return qualifiedName; - } - - protected AtlasEntity toReferencedHBaseTable(Table table, AtlasEntitiesWithExtInfo entities) { - AtlasEntity ret = null; - HBaseTableInfo hBaseTableInfo = new HBaseTableInfo(table); - String hbaseNameSpace = hBaseTableInfo.getHbaseNameSpace(); - String hbaseTableName = hBaseTableInfo.getHbaseTableName(); - String metadataNamespace = getMetadataNamespace(); - - if (hbaseTableName != null) { - AtlasEntity nsEntity = new AtlasEntity(HBASE_TYPE_NAMESPACE); - nsEntity.setAttribute(ATTRIBUTE_NAME, hbaseNameSpace); - nsEntity.setAttribute(ATTRIBUTE_CLUSTER_NAME, metadataNamespace); - nsEntity.setAttribute(ATTRIBUTE_QUALIFIED_NAME, getHBaseNameSpaceQualifiedName(metadataNamespace, hbaseNameSpace)); - - ret = new AtlasEntity(HBASE_TYPE_TABLE); - - ret.setAttribute(ATTRIBUTE_NAME, hbaseTableName); - ret.setAttribute(ATTRIBUTE_URI, hbaseTableName); - - AtlasRelatedObjectId objIdRelatedObject = new AtlasRelatedObjectId(AtlasTypeUtil.getObjectId(nsEntity), RELATIONSHIP_HBASE_TABLE_NAMESPACE); - - ret.setRelationshipAttribute(ATTRIBUTE_NAMESPACE, objIdRelatedObject); - ret.setAttribute(ATTRIBUTE_QUALIFIED_NAME, getHBaseTableQualifiedName(metadataNamespace, hbaseNameSpace, hbaseTableName)); - - entities.addReferredEntity(nsEntity); - entities.addEntity(ret); - } - - return ret; - } - - protected boolean isHBaseStore(Table table) { - boolean ret = false; - Map parameters = table.getParameters(); - - if (MapUtils.isNotEmpty(parameters)) { - String storageHandler = parameters.get(ATTRIBUTE_STORAGE_HANDLER); - - ret = (storageHandler != null && storageHandler.equals(HBASE_STORAGE_HANDLER_CLASS)); - } - - return ret; - } - - private static String getHBaseTableQualifiedName(String metadataNamespace, String nameSpace, String tableName) { - return String.format("%s:%s@%s", nameSpace.toLowerCase(), tableName.toLowerCase(), metadataNamespace); - } - - private static String getHBaseNameSpaceQualifiedName(String metadataNamespace, String nameSpace) { - return String.format("%s@%s", nameSpace.toLowerCase(), metadataNamespace); - } - - private boolean ignoreHDFSPathsinProcessQualifiedName() { - switch (context.getHiveOperation()) { - case LOAD: - case IMPORT: - return hasPartitionEntity(getOutputs()); - case EXPORT: - return hasPartitionEntity(getInputs()); - case QUERY: - return true; - } - - return false; - } - - private boolean hasPartitionEntity(Collection entities) { - if (entities != null) { - for (Entity entity : entities) { - if (entity.getType() == Entity.Type.PARTITION) { - return true; - } - } - } - - return false; - } - - private void addToProcessQualifiedName(StringBuilder processQualifiedName, Collection entities, boolean ignoreHDFSPaths) { - if (entities == null) { - return; - } - - List sortedEntities = new ArrayList<>(entities); - - Collections.sort(sortedEntities, entityComparator); - - Set dataSetsProcessed = new HashSet<>(); - Map tableMap = new HashMap<>(); - - for (Entity entity : sortedEntities) { - if (ignoreHDFSPaths && (Entity.Type.DFS_DIR.equals(entity.getType()) || Entity.Type.LOCAL_DIR.equals(entity.getType()))) { - continue; - } - - String qualifiedName = null; - long createTime = 0; - - try { - if (entity.getType() == Entity.Type.PARTITION || entity.getType() == Entity.Type.TABLE) { - String tableKey = entity.getTable().getDbName() + "." + entity.getTable().getTableName(); - Table table = tableMap.get(tableKey); - - if (table == null) { - table = getHive().getTable(entity.getTable().getDbName(), entity.getTable().getTableName()); - - tableMap.put(tableKey, table); //since there could be several partitions in a table, store it to avoid hive calls. - } - if (table != null) { - createTime = getTableCreateTime(table); - qualifiedName = getQualifiedName(table); - } - } else { - qualifiedName = getQualifiedName(entity); - } - } catch (Exception excp) { - LOG.error("error while computing qualifiedName for process", excp); - } - - if (qualifiedName == null || !dataSetsProcessed.add(qualifiedName)) { - continue; - } - - if (entity instanceof WriteEntity) { // output entity - WriteEntity writeEntity = (WriteEntity) entity; - - if (writeEntity.getWriteType() != null && HiveOperation.QUERY.equals(context.getHiveOperation())) { - boolean addWriteType = false; - - switch (((WriteEntity) entity).getWriteType()) { - case INSERT: - case INSERT_OVERWRITE: - case UPDATE: - case DELETE: - addWriteType = true; - break; - - case PATH_WRITE: - addWriteType = !Entity.Type.LOCAL_DIR.equals(entity.getType()); - break; - } - - if (addWriteType) { - processQualifiedName.append(QNAME_SEP_PROCESS).append(writeEntity.getWriteType().name()); - } - } - } - - processQualifiedName.append(QNAME_SEP_PROCESS).append(qualifiedName.toLowerCase().replaceAll("/", "")); - - if (createTime != 0) { - processQualifiedName.append(QNAME_SEP_PROCESS).append(createTime); - } - } - } - - private boolean isAlterTableOperation() { - switch (context.getHiveOperation()) { - case ALTERTABLE_FILEFORMAT: - case ALTERTABLE_CLUSTER_SORT: - case ALTERTABLE_BUCKETNUM: - case ALTERTABLE_PROPERTIES: - case ALTERTABLE_SERDEPROPERTIES: - case ALTERTABLE_SERIALIZER: - case ALTERTABLE_ADDCOLS: - case ALTERTABLE_REPLACECOLS: - case ALTERTABLE_PARTCOLTYPE: - case ALTERTABLE_LOCATION: - case ALTERTABLE_RENAME: - case ALTERTABLE_RENAMECOL: - case ALTERVIEW_PROPERTIES: - case ALTERVIEW_RENAME: - case ALTERVIEW_AS: - return true; - } - - return false; - } - - static final class EntityComparator implements Comparator { - @Override - public int compare(Entity entity1, Entity entity2) { - String name1 = entity1.getName(); - String name2 = entity2.getName(); - - if (name1 == null || name2 == null) { - name1 = entity1.getD().toString(); - name2 = entity2.getD().toString(); - } - - return name1.toLowerCase().compareTo(name2.toLowerCase()); - } - } - - static final Comparator entityComparator = new EntityComparator(); - - static final class HBaseTableInfo { - String hbaseNameSpace = null; - String hbaseTableName = null; - - HBaseTableInfo(Table table) { - Map parameters = table.getParameters(); - - if (MapUtils.isNotEmpty(parameters)) { - hbaseNameSpace = HBASE_DEFAULT_NAMESPACE; - hbaseTableName = parameters.get(HBASE_PARAM_TABLE_NAME); - - if (hbaseTableName != null) { - if (hbaseTableName.contains(HBASE_NAMESPACE_TABLE_DELIMITER)) { - String[] hbaseTableInfo = hbaseTableName.split(HBASE_NAMESPACE_TABLE_DELIMITER); - - if (hbaseTableInfo.length > 1) { - hbaseNameSpace = hbaseTableInfo[0]; - hbaseTableName = hbaseTableInfo[1]; - } - } - } - } - } - - public String getHbaseNameSpace() { - return hbaseNameSpace; - } - - public String getHbaseTableName() { - return hbaseTableName; - } - } - - public static Table toTable(org.apache.hadoop.hive.metastore.api.Table table) { - return new Table(table); - } -} diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/CreateDatabase.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/CreateDatabase.java deleted file mode 100644 index bf5f5620e76..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/CreateDatabase.java +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.events; - -import org.apache.atlas.hive.hook.AtlasHiveHookContext; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.model.notification.HookNotification.EntityCreateRequestV2; -import org.apache.commons.collections.CollectionUtils; -import org.apache.hadoop.hive.metastore.api.Database; -import org.apache.hadoop.hive.metastore.events.CreateDatabaseEvent; -import org.apache.hadoop.hive.ql.hooks.Entity; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.List; - -import static org.apache.atlas.hive.bridge.HiveMetaStoreBridge.getDatabaseName; -import static org.apache.hadoop.hive.ql.hooks.Entity.Type.DATABASE; - -public class CreateDatabase extends BaseHiveEvent { - private static final Logger LOG = LoggerFactory.getLogger(CreateDatabase.class); - - public CreateDatabase(AtlasHiveHookContext context) { - super(context); - } - - @Override - public List getNotificationMessages() throws Exception { - List ret = null; - AtlasEntitiesWithExtInfo entities = context.isMetastoreHook() ? getHiveMetastoreEntities() : getHiveEntities(); - - if (entities != null && CollectionUtils.isNotEmpty(entities.getEntities())) { - ret = Collections.singletonList(new EntityCreateRequestV2(getUserName(), entities)); - } - - return ret; - } - - public AtlasEntitiesWithExtInfo getHiveMetastoreEntities() throws Exception { - AtlasEntitiesWithExtInfo ret = new AtlasEntitiesWithExtInfo(); - CreateDatabaseEvent dbEvent = (CreateDatabaseEvent) context.getMetastoreEvent(); - Database db = dbEvent.getDatabase(); - - if (db != null) { - db = context.getMetastoreHandler().get_database(db.getName()); - } - - if (db != null) { - AtlasEntity dbEntity = toDbEntity(db); - - ret.addEntity(dbEntity); - - addLocationEntities(dbEntity, ret); - } else { - LOG.error("CreateDatabase.getEntities(): failed to retrieve db"); - } - - addProcessedEntities(ret); - - return ret; - } - - public AtlasEntitiesWithExtInfo getHiveEntities() throws Exception { - AtlasEntitiesWithExtInfo ret = new AtlasEntitiesWithExtInfo(); - - for (Entity entity : getOutputs()) { - if (entity.getType() == DATABASE) { - Database db = entity.getDatabase(); - - if (db != null) { - db = getHive().getDatabase(getDatabaseName(db)); - } - - if (db != null) { - AtlasEntity dbEntity = toDbEntity(db); - AtlasEntity dbDDLEntity = createHiveDDLEntity(dbEntity); - - ret.addEntity(dbEntity); - - if (dbDDLEntity != null) { - ret.addEntity(dbDDLEntity); - } - - addLocationEntities(dbEntity, ret); - } else { - LOG.error("CreateDatabase.getEntities(): failed to retrieve db"); - } - } - } - - addProcessedEntities(ret); - - return ret; - } - - public void addLocationEntities(AtlasEntity dbEntity, AtlasEntitiesWithExtInfo ret) { - AtlasEntity dbLocationEntity = createHiveLocationEntity(dbEntity, ret); - - if (dbLocationEntity != null) { - ret.addEntity(dbLocationEntity); - } - } -} \ No newline at end of file diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/CreateHiveProcess.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/CreateHiveProcess.java deleted file mode 100644 index 5787c9365ac..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/CreateHiveProcess.java +++ /dev/null @@ -1,295 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.events; - -import org.apache.atlas.type.AtlasTypeUtil; -import org.apache.atlas.hive.hook.AtlasHiveHookContext; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.model.notification.HookNotification.EntityCreateRequestV2; -import org.apache.commons.collections.CollectionUtils; -import org.apache.hadoop.hive.ql.hooks.Entity; -import org.apache.hadoop.hive.ql.hooks.LineageInfo; -import org.apache.hadoop.hive.ql.hooks.LineageInfo.BaseColumnInfo; -import org.apache.hadoop.hive.ql.hooks.LineageInfo.Dependency; -import org.apache.hadoop.hive.ql.hooks.LineageInfo.DependencyKey; -import org.apache.hadoop.hive.ql.hooks.ReadEntity; -import org.apache.hadoop.hive.ql.hooks.WriteEntity; -import org.apache.hadoop.hive.ql.plan.HiveOperation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - - -public class CreateHiveProcess extends BaseHiveEvent { - private static final Logger LOG = LoggerFactory.getLogger(CreateHiveProcess.class); - - public CreateHiveProcess(AtlasHiveHookContext context) { - super(context); - } - - @Override - public List getNotificationMessages() throws Exception { - List ret = null; - AtlasEntitiesWithExtInfo entities = getEntities(); - - if (entities != null && CollectionUtils.isNotEmpty(entities.getEntities())) { - ret = Collections.singletonList(new EntityCreateRequestV2(getUserName(), entities)); - } - - return ret; - } - - public AtlasEntitiesWithExtInfo getEntities() throws Exception { - AtlasEntitiesWithExtInfo ret = null; - - if (!skipProcess()) { - List inputs = new ArrayList<>(); - List outputs = new ArrayList<>(); - Set processedNames = new HashSet<>(); - - ret = new AtlasEntitiesWithExtInfo(); - - if (getInputs() != null) { - for (ReadEntity input : getInputs()) { - String qualifiedName = getQualifiedName(input); - - if (qualifiedName == null || !processedNames.add(qualifiedName)) { - continue; - } - - AtlasEntity entity = getInputOutputEntity(input, ret, skipTempTables); - - if (!input.isDirect()) { - continue; - } - - if (entity != null) { - inputs.add(entity); - } - } - } - - if (getOutputs() != null) { - for (WriteEntity output : getOutputs()) { - String qualifiedName = getQualifiedName(output); - - if (qualifiedName == null || !processedNames.add(qualifiedName)) { - continue; - } - - AtlasEntity entity = getInputOutputEntity(output, ret, skipTempTables); - - if (entity != null) { - outputs.add(entity); - } - - if (isDdlOperation(entity)) { - - AtlasEntity ddlEntity = createHiveDDLEntity(entity); - - if (ddlEntity != null) { - ret.addEntity(ddlEntity); - } - } - } - } - - boolean skipProcess = inputs.isEmpty() && outputs.isEmpty(); - - if (!skipProcess) { - if (inputs.isEmpty() && context.isSkippedInputEntity()) { - skipProcess = true; - } else if (outputs.isEmpty() && context.isSkippedOutputEntity()) { - skipProcess = true; - } - } - - if (!skipProcess && !context.isMetastoreHook()) { - AtlasEntity process = getHiveProcessEntity(inputs, outputs); - - ret.addEntity(process); - - AtlasEntity processExecution = getHiveProcessExecutionEntity(process); - ret.addEntity(processExecution); - - processColumnLineage(process, ret); - - addProcessedEntities(ret); - } else { - ret = null; - } - } - - return ret; - } - - private void processColumnLineage(AtlasEntity hiveProcess, AtlasEntitiesWithExtInfo entities) { - LineageInfo lineageInfo = getLineageInfo(); - - if (lineageInfo == null || CollectionUtils.isEmpty(lineageInfo.entrySet())) { - return; - } - - final List columnLineages = new ArrayList<>(); - int lineageInputsCount = 0; - final Set processedOutputCols = new HashSet<>(); - - for (Map.Entry entry : lineageInfo.entrySet()) { - String outputColName = getQualifiedName(entry.getKey()); - AtlasEntity outputColumn = context.getEntity(outputColName); - - if (LOG.isDebugEnabled()) { - LOG.debug("processColumnLineage(): DependencyKey={}; Dependency={}", entry.getKey(), entry.getValue()); - } - - if (outputColumn == null) { - LOG.warn("column-lineage: non-existing output-column {}", outputColName); - - continue; - } - - if (processedOutputCols.contains(outputColName)) { - LOG.warn("column-lineage: duplicate for output-column {}", outputColName); - - continue; - } else { - processedOutputCols.add(outputColName); - } - - List inputColumns = new ArrayList<>(); - - for (BaseColumnInfo baseColumn : getBaseCols(entry.getValue())) { - String inputColName = getQualifiedName(baseColumn); - AtlasEntity inputColumn = context.getEntity(inputColName); - - if (inputColumn == null) { - LOG.warn("column-lineage: non-existing input-column {} for output-column={}", inputColName, outputColName); - - continue; - } - - inputColumns.add(inputColumn); - } - - if (inputColumns.isEmpty()) { - continue; - } - - lineageInputsCount += inputColumns.size(); - - AtlasEntity columnLineageProcess = new AtlasEntity(HIVE_TYPE_COLUMN_LINEAGE); - - columnLineageProcess.setAttribute(ATTRIBUTE_NAME, hiveProcess.getAttribute(ATTRIBUTE_QUALIFIED_NAME) + ":" + outputColumn.getAttribute(ATTRIBUTE_NAME)); - columnLineageProcess.setAttribute(ATTRIBUTE_QUALIFIED_NAME, hiveProcess.getAttribute(ATTRIBUTE_QUALIFIED_NAME) + ":" + outputColumn.getAttribute(ATTRIBUTE_NAME)); - columnLineageProcess.setRelationshipAttribute(ATTRIBUTE_INPUTS, AtlasTypeUtil.getAtlasRelatedObjectIds(inputColumns, BaseHiveEvent.RELATIONSHIP_DATASET_PROCESS_INPUTS)); - columnLineageProcess.setRelationshipAttribute(ATTRIBUTE_OUTPUTS, Collections.singletonList(AtlasTypeUtil.getAtlasRelatedObjectId(outputColumn, BaseHiveEvent.RELATIONSHIP_PROCESS_DATASET_OUTPUTS))); - columnLineageProcess.setRelationshipAttribute(ATTRIBUTE_QUERY, AtlasTypeUtil.getAtlasRelatedObjectId(hiveProcess, BaseHiveEvent.RELATIONSHIP_HIVE_PROCESS_COLUMN_LINEAGE)); - columnLineageProcess.setAttribute(ATTRIBUTE_DEPENDENCY_TYPE, entry.getValue().getType()); - columnLineageProcess.setAttribute(ATTRIBUTE_EXPRESSION, entry.getValue().getExpr()); - - columnLineages.add(columnLineageProcess); - } - - float avgInputsCount = columnLineages.size() > 0 ? (((float) lineageInputsCount) / columnLineages.size()) : 0; - boolean skipColumnLineage = context.getSkipHiveColumnLineageHive20633() && avgInputsCount > context.getSkipHiveColumnLineageHive20633InputsThreshold(); - - if (!skipColumnLineage) { - for (AtlasEntity columnLineage : columnLineages) { - entities.addEntity(columnLineage); - } - } else { - LOG.warn("skipped {} hive_column_lineage entities. Average # of inputs={}, threshold={}, total # of inputs={}", columnLineages.size(), avgInputsCount, context.getSkipHiveColumnLineageHive20633InputsThreshold(), lineageInputsCount); - } - } - - private Collection getBaseCols(Dependency lInfoDep) { - Collection ret = Collections.emptyList(); - - if (lInfoDep != null) { - try { - Method getBaseColsMethod = lInfoDep.getClass().getMethod("getBaseCols"); - - Object retGetBaseCols = getBaseColsMethod.invoke(lInfoDep); - - if (retGetBaseCols != null) { - if (retGetBaseCols instanceof Collection) { - ret = (Collection) retGetBaseCols; - } else { - LOG.warn("{}: unexpected return type from LineageInfo.Dependency.getBaseCols(), expected type {}", - retGetBaseCols.getClass().getName(), "Collection"); - } - } - } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) { - LOG.warn("getBaseCols()", ex); - } - } - - return ret; - } - - - private boolean skipProcess() { - Set inputs = getInputs(); - Set outputs = getOutputs(); - - boolean ret = CollectionUtils.isEmpty(inputs) && CollectionUtils.isEmpty(outputs); - - if (!ret) { - if (getContext().getHiveOperation() == HiveOperation.QUERY) { - // Select query has only one output - if (outputs.size() == 1) { - WriteEntity output = outputs.iterator().next(); - - if (output.getType() == Entity.Type.DFS_DIR || output.getType() == Entity.Type.LOCAL_DIR) { - if (output.getWriteType() == WriteEntity.WriteType.PATH_WRITE && output.isTempURI()) { - ret = true; - } - } - // DELETE and UPDATE initially have one input and one output. - // Since they do not support sub-query, they won't create a lineage that have one input and one output. (One input only) - // It's safe to filter them out here. - if (output.getWriteType() == WriteEntity.WriteType.DELETE || output.getWriteType() == WriteEntity.WriteType.UPDATE) { - ret = true; - } - } - } - } - - return ret; - } - - private boolean isDdlOperation(AtlasEntity entity) { - return entity != null && !context.isMetastoreHook() - && (context.getHiveOperation().equals(HiveOperation.CREATETABLE_AS_SELECT) - || context.getHiveOperation().equals(HiveOperation.CREATEVIEW) - || context.getHiveOperation().equals(HiveOperation.ALTERVIEW_AS) - || context.getHiveOperation().equals(HiveOperation.CREATE_MATERIALIZED_VIEW)); - } -} diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/CreateTable.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/CreateTable.java deleted file mode 100644 index 91611de88eb..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/CreateTable.java +++ /dev/null @@ -1,202 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.events; - -import org.apache.atlas.hive.hook.AtlasHiveHookContext; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.model.notification.HookNotification.EntityCreateRequestV2; -import org.apache.commons.collections.CollectionUtils; -import org.apache.hadoop.hive.metastore.TableType; -import org.apache.hadoop.hive.metastore.events.AlterTableEvent; -import org.apache.hadoop.hive.metastore.events.CreateTableEvent; -import org.apache.hadoop.hive.metastore.events.ListenerEvent; -import org.apache.hadoop.hive.ql.hooks.Entity; -import org.apache.hadoop.hive.ql.metadata.Table; -import org.apache.hadoop.hive.ql.plan.HiveOperation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.List; - -import static org.apache.hadoop.hive.metastore.TableType.EXTERNAL_TABLE; -import static org.apache.hadoop.hive.ql.plan.HiveOperation.*; - -public class CreateTable extends BaseHiveEvent { - private static final Logger LOG = LoggerFactory.getLogger(CreateTable.class); - - public CreateTable(AtlasHiveHookContext context) { - super(context); - } - - @Override - public List getNotificationMessages() throws Exception { - List ret = null; - AtlasEntitiesWithExtInfo entities = context.isMetastoreHook() ? getHiveMetastoreEntities() : getHiveEntities(); - - if (entities != null && CollectionUtils.isNotEmpty(entities.getEntities())) { - ret = Collections.singletonList(new EntityCreateRequestV2(getUserName(), entities)); - } - - return ret; - } - - public AtlasEntitiesWithExtInfo getHiveMetastoreEntities() throws Exception { - AtlasEntitiesWithExtInfo ret = new AtlasEntitiesWithExtInfo(); - ListenerEvent event = context.getMetastoreEvent(); - HiveOperation oper = context.getHiveOperation(); - Table table; - - if (isAlterTable(oper)) { - table = toTable(((AlterTableEvent) event).getNewTable()); - } else { - table = toTable(((CreateTableEvent) event).getTable()); - } - - if (skipTemporaryTable(table)) { - table = null; - } - - processTable(table, ret); - - addProcessedEntities(ret); - - return ret; - } - - public AtlasEntitiesWithExtInfo getHiveEntities() throws Exception { - AtlasEntitiesWithExtInfo ret = new AtlasEntitiesWithExtInfo(); - Table table = null; - - if (CollectionUtils.isNotEmpty(getOutputs())) { - for (Entity entity : getOutputs()) { - if (entity.getType() == Entity.Type.TABLE) { - table = entity.getTable(); - - if (table != null) { - table = getHive().getTable(table.getDbName(), table.getTableName()); - - if (table != null) { - if (skipTemporaryTable(table)) { - table = null; - } else { - break; - } - } - } - } - } - } - - processTable(table, ret); - - addProcessedEntities(ret); - - return ret; - } - - // create process entities for lineages from HBase/HDFS to hive table - private void processTable(Table table, AtlasEntitiesWithExtInfo ret) throws Exception { - if (table != null) { - AtlasEntity tblEntity = toTableEntity(table, ret); - - if (tblEntity != null) { - if (isHBaseStore(table)) { - if (context.isMetastoreHook()) { - //do nothing - } else { - // This create lineage to HBase table in case of Hive on HBase - AtlasEntity hbaseTableEntity = toReferencedHBaseTable(table, ret); - - //not a hive metastore hook - //it is running in the context of Hbase. - if (hbaseTableEntity != null) { - final AtlasEntity processEntity; - - if (EXTERNAL_TABLE.equals(table.getTableType())) { - processEntity = getHiveProcessEntity(Collections.singletonList(hbaseTableEntity), Collections.singletonList(tblEntity)); - } else { - processEntity = getHiveProcessEntity(Collections.singletonList(tblEntity), Collections.singletonList(hbaseTableEntity)); - } - ret.addEntity(processEntity); - - AtlasEntity processExecution = getHiveProcessExecutionEntity(processEntity); - ret.addEntity(processExecution); - } - } - - } else { - if (context.isMetastoreHook()) { - //it is running in the context of HiveMetastore - //not a hive metastore hook - if (isCreateExtTableOperation(table)) { - if (LOG.isDebugEnabled()) { - LOG.debug("Creating a dummy process with lineage from hdfs path to hive table"); - } - AtlasEntity hdfsPathEntity = getPathEntity(table.getDataLocation(), ret); - AtlasEntity processEntity = getHiveProcessEntity(Collections.singletonList(hdfsPathEntity), Collections.singletonList(tblEntity)); - - ret.addEntity(processEntity); - ret.addReferredEntity(hdfsPathEntity); - } - } else { - //not a hive metastore hook - //it is running in the context of HiveServer2 - if (EXTERNAL_TABLE.equals(table.getTableType())) { - AtlasEntity hdfsPathEntity = getPathEntity(table.getDataLocation(), ret); - AtlasEntity processEntity = getHiveProcessEntity(Collections.singletonList(hdfsPathEntity), Collections.singletonList(tblEntity)); - - ret.addEntity(processEntity); - ret.addReferredEntity(hdfsPathEntity); - - AtlasEntity processExecution = getHiveProcessExecutionEntity(processEntity); - ret.addEntity(processExecution); - } - } - } - - if (!context.isMetastoreHook()) { - AtlasEntity tableDDLEntity = createHiveDDLEntity(tblEntity); - - if (tableDDLEntity != null) { - ret.addEntity(tableDDLEntity); - } - } - } - } - } - - private static boolean isAlterTable(HiveOperation oper) { - return (oper == ALTERTABLE_PROPERTIES || oper == ALTERTABLE_RENAME || oper == ALTERTABLE_RENAMECOL); - } - - private boolean skipTemporaryTable(Table table) { - // If its an external table, even though the temp table skip flag is on, we create the table since we need the HDFS path to temp table lineage. - return table != null && skipTempTables && table.isTemporary() && !EXTERNAL_TABLE.equals(table.getTableType()); - } - - private boolean isCreateExtTableOperation(Table table) { - HiveOperation oper = context.getHiveOperation(); - TableType tableType = table.getTableType(); - - return EXTERNAL_TABLE.equals(tableType) && (oper == CREATETABLE || oper == CREATETABLE_AS_SELECT); - } -} diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/DropDatabase.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/DropDatabase.java deleted file mode 100644 index 20019d2ef48..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/DropDatabase.java +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.events; - -import org.apache.atlas.hive.hook.AtlasHiveHookContext; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.model.notification.HookNotification.EntityDeleteRequestV2; -import org.apache.commons.collections.CollectionUtils; -import org.apache.hadoop.hive.metastore.events.DropDatabaseEvent; -import org.apache.hadoop.hive.ql.hooks.Entity; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static org.apache.hadoop.hive.ql.hooks.Entity.Type.DATABASE; -import static org.apache.hadoop.hive.ql.hooks.Entity.Type.TABLE; - -public class DropDatabase extends BaseHiveEvent { - public DropDatabase(AtlasHiveHookContext context) { - super(context); - } - - @Override - public List getNotificationMessages() { - List ret = null; - List entities = context.isMetastoreHook() ? getHiveMetastoreEntities() : getHiveEntities(); - - if (CollectionUtils.isNotEmpty(entities)) { - ret = new ArrayList<>(entities.size()); - - for (AtlasObjectId entity : entities) { - ret.add(new EntityDeleteRequestV2(getUserName(), Collections.singletonList(entity))); - } - } - - return ret; - } - - private List getHiveMetastoreEntities() { - List ret = new ArrayList<>(); - DropDatabaseEvent dbEvent = (DropDatabaseEvent) context.getMetastoreEvent(); - String dbQName = getQualifiedName(dbEvent.getDatabase()); - AtlasObjectId dbId = new AtlasObjectId(HIVE_TYPE_DB, ATTRIBUTE_QUALIFIED_NAME, dbQName); - - context.removeFromKnownDatabase(dbQName); - - ret.add(dbId); - - return ret; - } - - private List getHiveEntities() { - List ret = new ArrayList<>(); - - for (Entity entity : getOutputs()) { - if (entity.getType() == DATABASE) { - String dbQName = getQualifiedName(entity.getDatabase()); - AtlasObjectId dbId = new AtlasObjectId(HIVE_TYPE_DB, ATTRIBUTE_QUALIFIED_NAME, dbQName); - - context.removeFromKnownDatabase(dbQName); - - ret.add(dbId); - } else if (entity.getType() == TABLE) { - String tblQName = getQualifiedName(entity.getTable()); - AtlasObjectId tblId = new AtlasObjectId(HIVE_TYPE_TABLE, ATTRIBUTE_QUALIFIED_NAME, tblQName); - - context.removeFromKnownTable(tblQName); - - ret.add(tblId); - } - } - - return ret; - } -} \ No newline at end of file diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/DropTable.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/DropTable.java deleted file mode 100644 index 440c08affab..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/events/DropTable.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.events; - -import org.apache.atlas.hive.hook.AtlasHiveHookContext; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.model.notification.HookNotification.EntityDeleteRequestV2; -import org.apache.commons.collections.CollectionUtils; -import org.apache.hadoop.hive.metastore.events.DropTableEvent; -import org.apache.hadoop.hive.ql.hooks.Entity; -import org.apache.hadoop.hive.ql.metadata.Table; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class DropTable extends BaseHiveEvent { - public DropTable(AtlasHiveHookContext context) { - super(context); - } - - @Override - public List getNotificationMessages() { - List ret = null; - List entities = context.isMetastoreHook() ? getHiveMetastoreEntities() : getHiveEntities(); - - if (CollectionUtils.isNotEmpty(entities)) { - ret = new ArrayList<>(entities.size()); - - for (AtlasObjectId entity : entities) { - ret.add(new EntityDeleteRequestV2(getUserName(), Collections.singletonList(entity))); - } - } - - return ret; - } - - public List getHiveMetastoreEntities() { - List ret = new ArrayList<>(); - DropTableEvent tblEvent = (DropTableEvent) context.getMetastoreEvent(); - Table table = new Table(tblEvent.getTable()); - String tblQName = getQualifiedName(table); - AtlasObjectId tblId = new AtlasObjectId(HIVE_TYPE_TABLE, ATTRIBUTE_QUALIFIED_NAME, tblQName); - - context.removeFromKnownTable(tblQName); - - ret.add(tblId); - - return ret; - } - - public List getHiveEntities() { - List ret = new ArrayList<>(); - - for (Entity entity : getOutputs()) { - if (entity.getType() == Entity.Type.TABLE) { - String tblQName = getQualifiedName(entity.getTable()); - AtlasObjectId tblId = new AtlasObjectId(HIVE_TYPE_TABLE, ATTRIBUTE_QUALIFIED_NAME, tblQName); - - context.removeFromKnownTable(tblQName); - - ret.add(tblId); - } - } - - return ret; - } -} \ No newline at end of file diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/ActiveEntityFilter.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/ActiveEntityFilter.java deleted file mode 100644 index 0b0d4d6b265..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/ActiveEntityFilter.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.utils; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.atlas.hive.hook.HiveHook; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.commons.configuration.Configuration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Arrays; -import java.util.List; - -import static org.apache.atlas.hive.hook.HiveHook.HOOK_HIVE_IGNORE_DDL_OPERATIONS; - -public class ActiveEntityFilter { - private static final Logger LOG = LoggerFactory.getLogger(ActiveEntityFilter.class); - - private static EntityFilter entityFilter; - - public static void init(Configuration configuration) { - boolean skipDdlOperations = configuration.getBoolean(HOOK_HIVE_IGNORE_DDL_OPERATIONS, false); - List additionalTypesToRetain = getConfiguredTypesToRetainForDDLEntityFilter(configuration); - - init(skipDdlOperations, additionalTypesToRetain); - LOG.info("atlas.hook.hive.ignore.ddl.operations={} - {}", skipDdlOperations, entityFilter.getClass().getSimpleName()); - } - - @VisibleForTesting - static void init(boolean lineageOnlyFilter, List additionalTypesToRetain) { - entityFilter = lineageOnlyFilter ? new HiveDDLEntityFilter(additionalTypesToRetain) : new PassthroughFilter(); - } - - public static List apply(List incoming) { - return entityFilter.apply(incoming); - } - - private static List getConfiguredTypesToRetainForDDLEntityFilter(Configuration configuration) { - try { - if (configuration.containsKey(HiveHook.HOOK_HIVE_FILTER_ENTITY_ADDITIONAL_TYPES_TO_RETAIN)) { - String[] configuredTypes = configuration.getStringArray(HiveHook.HOOK_HIVE_FILTER_ENTITY_ADDITIONAL_TYPES_TO_RETAIN); - - return Arrays.asList(configuredTypes); - } - } catch (Exception e) { - LOG.error("Failed to load application properties", e); - } - - return null; - } -} diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/EntityFilter.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/EntityFilter.java deleted file mode 100644 index f02ee52dac4..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/EntityFilter.java +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.utils; - -import org.apache.atlas.model.notification.HookNotification; - -import java.util.List; - -public interface EntityFilter { - List apply(List incoming); -} diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/HiveDDLEntityFilter.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/HiveDDLEntityFilter.java deleted file mode 100644 index 0f9aa458ccb..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/HiveDDLEntityFilter.java +++ /dev/null @@ -1,286 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.utils; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.atlas.hive.hook.events.BaseHiveEvent; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.utils.AtlasPathExtractorUtil; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections.MapUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class HiveDDLEntityFilter implements EntityFilter { - private static final Logger LOG = LoggerFactory.getLogger(HiveDDLEntityFilter.class); - - private static final Set defaultPathTypesToRetain = new HashSet() {{ - add(AtlasPathExtractorUtil.HDFS_TYPE_PATH); - add(AtlasPathExtractorUtil.ADLS_GEN2_ACCOUNT); - add(AtlasPathExtractorUtil.ADLS_GEN2_CONTAINER); - add(AtlasPathExtractorUtil.ADLS_GEN2_DIRECTORY); - add(AtlasPathExtractorUtil.GCS_VIRTUAL_DIR); - add(AtlasPathExtractorUtil.AWS_S3_BUCKET); - add(AtlasPathExtractorUtil.AWS_S3_V2_BUCKET); - add(AtlasPathExtractorUtil.AWS_S3_V2_PSEUDO_DIR); - add(AtlasPathExtractorUtil.AWS_S3_PSEUDO_DIR); - add(AtlasPathExtractorUtil.OZONE_KEY); - add(AtlasPathExtractorUtil.OZONE_BUCKET); - add(AtlasPathExtractorUtil.OZONE_VOLUME); - }}; - - private static final Set typesToRetain = new HashSet() {{ - add(BaseHiveEvent.HIVE_TYPE_PROCESS); - add(BaseHiveEvent.HIVE_TYPE_PROCESS_EXECUTION); - add(BaseHiveEvent.HIVE_TYPE_COLUMN_LINEAGE); - add(BaseHiveEvent.HIVE_DB_DDL); - add(BaseHiveEvent.HIVE_TABLE_DDL); - addAll(defaultPathTypesToRetain); - }}; - - public HiveDDLEntityFilter(List additionalTypesToRetain) { - if (CollectionUtils.isEmpty(additionalTypesToRetain)) { - return; - } - - typesToRetain.addAll(additionalTypesToRetain); - LOG.info("Types retained: {}", typesToRetain.toArray()); - } - - public List apply(List incoming) { - if (CollectionUtils.isEmpty(incoming)) { - return incoming; - } - - List ret = new ArrayList<>(); - for (HookNotification notification : incoming) { - HookNotification filteredNotification = apply(notification); - if (filteredNotification == null) { - continue; - } - - ret.add(filteredNotification); - } - - return ret; - } - - @VisibleForTesting - AtlasEntity.AtlasEntityWithExtInfo apply(AtlasEntity.AtlasEntityWithExtInfo incoming) { - AtlasEntity.AtlasEntityWithExtInfo ret = new AtlasEntity.AtlasEntityWithExtInfo(); - - AtlasEntity entity = filter(incoming.getEntity()); - if (entity == null) { - return null; - } - - ret.setEntity(entity); - - Map refEntities = filter(incoming.getReferredEntities()); - if (!MapUtils.isEmpty(refEntities)) { - ret.setReferredEntities(refEntities); - } - - return ret; - } - - @VisibleForTesting - public AtlasEntity.AtlasEntitiesWithExtInfo apply(AtlasEntity.AtlasEntitiesWithExtInfo incoming) { - if (incoming == null) { - return incoming; - } - - AtlasEntity.AtlasEntitiesWithExtInfo ret = new AtlasEntity.AtlasEntitiesWithExtInfo(); - - filterEntities(incoming, ret); - filterReferences(incoming, ret); - - return ret; - } - - @VisibleForTesting - List applyForObjectIds(List incoming) { - if (incoming == null || CollectionUtils.isEmpty(incoming)) { - return null; - } - - List ret = new ArrayList<>(); - for (AtlasObjectId o : incoming) { - if (filterObjectId(o) != null) { - ret.add(o); - } - } - - return ret; - } - - private AtlasObjectId filterObjectId(AtlasObjectId o) { - if (o != null && typesToRetain.contains(o.getTypeName())) { - return o; - } - - return null; - } - - private static void filterEntities(AtlasEntity.AtlasEntitiesWithExtInfo incoming, AtlasEntity.AtlasEntitiesWithExtInfo ret) { - ret.setEntities(filter(incoming.getEntities())); - } - - private static void filterReferences(AtlasEntity.AtlasEntitiesWithExtInfo incoming, AtlasEntity.AtlasEntitiesWithExtInfo ret) { - ret.setReferredEntities(filter(incoming.getReferredEntities())); - } - - private static Map filter(Map incoming) { - if (incoming == null || MapUtils.isEmpty(incoming)) { - return null; - } - - return incoming.values() - .stream() - .filter(x -> typesToRetain.contains(x.getTypeName())) - .collect(Collectors.toMap(AtlasEntity::getGuid, Function.identity())); - } - - private static List filter(List incoming) { - if (incoming == null) { - return null; - } - - List ret = incoming.stream() - .filter(x -> typesToRetain.contains(x.getTypeName())) - .collect(Collectors.toList()); - - for (AtlasEntity e : ret) { - for (Object o : e.getRelationshipAttributes().values()) { - if (o instanceof List) { - List list = (List) o; - for (Object ox : list) { - inferObjectTypeResetGuid(ox); - } - } else { - inferObjectTypeResetGuid(o); - } - } - } - - return ret; - } - - private static void inferObjectTypeResetGuid(Object o) { - if (o instanceof AtlasObjectId) { - AtlasObjectId oid = (AtlasObjectId) o; - String typeName = oid.getTypeName(); - - if (oid.getUniqueAttributes() != null && !typesToRetain.contains(typeName)) { - oid.setGuid(null); - } - } else { - LinkedHashMap hm = (LinkedHashMap) o; - if (!hm.containsKey(BaseHiveEvent.ATTRIBUTE_GUID)) { - return; - } - - String typeName = hm.containsKey(AtlasObjectId.KEY_TYPENAME) ? (String) hm.get(AtlasObjectId.KEY_TYPENAME) : null; - - if (hm.containsKey(BaseHiveEvent.ATTRIBUTE_UNIQUE_ATTRIBUTES) && !typesToRetain.contains(typeName)) { - hm.remove(BaseHiveEvent.ATTRIBUTE_GUID); - } - } - } - - private static AtlasEntity filter(AtlasEntity incoming) { - if (incoming == null) { - return null; - } - - return typesToRetain.contains(incoming.getTypeName()) ? incoming : null; - } - - private HookNotification apply(HookNotification notification) { - if (notification instanceof HookNotification.EntityCreateRequestV2) { - return apply((HookNotification.EntityCreateRequestV2) notification); - } - - if (notification instanceof HookNotification.EntityUpdateRequestV2) { - return apply((HookNotification.EntityUpdateRequestV2) notification); - } - - if (notification instanceof HookNotification.EntityPartialUpdateRequestV2) { - return apply((HookNotification.EntityPartialUpdateRequestV2) notification); - } - - if (notification instanceof HookNotification.EntityDeleteRequestV2) { - return apply((HookNotification.EntityDeleteRequestV2) notification); - } - - return null; - } - - private HookNotification.EntityCreateRequestV2 apply(HookNotification.EntityCreateRequestV2 notification) { - AtlasEntity.AtlasEntitiesWithExtInfo entities = apply(notification.getEntities()); - if (entities == null || CollectionUtils.isEmpty(entities.getEntities())) { - return null; - } - - return new HookNotification.EntityCreateRequestV2(notification.getUser(), entities); - } - - private HookNotification.EntityUpdateRequestV2 apply(HookNotification.EntityUpdateRequestV2 notification) { - AtlasEntity.AtlasEntitiesWithExtInfo entities = apply(notification.getEntities()); - if (entities == null || CollectionUtils.isEmpty(entities.getEntities())) { - return null; - } - - return new HookNotification.EntityUpdateRequestV2(notification.getUser(), entities); - } - - private HookNotification.EntityPartialUpdateRequestV2 apply(HookNotification.EntityPartialUpdateRequestV2 notification) { - AtlasObjectId objectId = filterObjectId(notification.getEntityId()); - if (objectId == null) { - return null; - } - - AtlasEntity.AtlasEntityWithExtInfo entityWithExtInfo = apply(notification.getEntity()); - if (entityWithExtInfo == null) { - return null; - } - - return new HookNotification.EntityPartialUpdateRequestV2(notification.getUser(), objectId, entityWithExtInfo); - } - - private HookNotification.EntityDeleteRequestV2 apply(HookNotification.EntityDeleteRequestV2 notification) { - List objectIds = applyForObjectIds(notification.getEntities()); - if (CollectionUtils.isEmpty(objectIds)) { - return null; - } - - return new HookNotification.EntityDeleteRequestV2(notification.getUser(), objectIds); - } -} diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/PassthroughFilter.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/PassthroughFilter.java deleted file mode 100644 index f61c120ea2a..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/hook/utils/PassthroughFilter.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.utils; - -import org.apache.atlas.model.notification.HookNotification; - -import java.util.List; - -class PassthroughFilter implements EntityFilter { - @Override - public List apply(List incoming) { - return incoming; - } -} diff --git a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/model/HiveDataTypes.java b/addons/hive-bridge/src/main/java/org/apache/atlas/hive/model/HiveDataTypes.java deleted file mode 100755 index f3691e62599..00000000000 --- a/addons/hive-bridge/src/main/java/org/apache/atlas/hive/model/HiveDataTypes.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.model; - -/** - * Hive Data Types for model and bridge. - */ -public enum HiveDataTypes { - - // Enums - HIVE_OBJECT_TYPE, - HIVE_PRINCIPAL_TYPE, - HIVE_RESOURCE_TYPE, - - // Structs - HIVE_SERDE, - HIVE_ORDER, - HIVE_RESOURCEURI, - - // Classes - HIVE_DB, - HIVE_STORAGEDESC, - HIVE_TABLE, - HIVE_COLUMN, - HIVE_PARTITION, - HIVE_INDEX, - HIVE_ROLE, - HIVE_TYPE, - HIVE_PROCESS, - HIVE_COLUMN_LINEAGE, - HIVE_PROCESS_EXECUTION, - // HIVE_VIEW, - ; - - public String getName() { - return name().toLowerCase(); - } -} diff --git a/addons/hive-bridge/src/main/resources/atlas-hive-import-log4j.xml b/addons/hive-bridge/src/main/resources/atlas-hive-import-log4j.xml deleted file mode 100644 index 22a8cc9d43e..00000000000 --- a/addons/hive-bridge/src/main/resources/atlas-hive-import-log4j.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/hive-bridge/src/patches/001-hive_column_add_position.json b/addons/hive-bridge/src/patches/001-hive_column_add_position.json deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/HiveITBase.java b/addons/hive-bridge/src/test/java/org/apache/atlas/hive/HiveITBase.java deleted file mode 100644 index 0875afa392f..00000000000 --- a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/HiveITBase.java +++ /dev/null @@ -1,796 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasClient; -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.AtlasServiceException; -import org.apache.atlas.hive.bridge.ColumnLineageUtils; -import org.apache.atlas.hive.bridge.HiveMetaStoreBridge; -import org.apache.atlas.hive.hook.HiveHookIT; -import org.apache.atlas.hive.model.HiveDataTypes; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.model.instance.AtlasStruct; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.utils.AuthenticationUtil; -import org.apache.atlas.utils.ParamChecker; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.lang.RandomStringUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.hive.conf.HiveConf; -import org.apache.hadoop.hive.ql.Driver; -import org.apache.hadoop.hive.ql.hooks.Entity; -import org.apache.hadoop.hive.ql.hooks.HookContext; -import org.apache.hadoop.hive.ql.hooks.LineageInfo; -import org.apache.hadoop.hive.ql.hooks.ReadEntity; -import org.apache.hadoop.hive.ql.hooks.WriteEntity; -import org.apache.hadoop.hive.ql.metadata.HiveException; -import org.apache.hadoop.hive.ql.metadata.Table; -import org.apache.hadoop.hive.ql.plan.HiveOperation; -import org.apache.hadoop.hive.ql.processors.CommandProcessorResponse; -import org.apache.hadoop.hive.ql.session.SessionState; -import org.apache.hadoop.security.UserGroupInformation; -import org.json.JSONObject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.annotations.BeforeClass; - -import java.io.File; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.SortedMap; -import java.util.SortedSet; - -import static com.sun.jersey.api.client.ClientResponse.Status.NOT_FOUND; -import static org.apache.atlas.hive.bridge.HiveMetaStoreBridge.HDFS_PATH; -import static org.apache.atlas.hive.hook.events.BaseHiveEvent.ATTRIBUTE_QUALIFIED_NAME; -import static org.apache.atlas.hive.model.HiveDataTypes.HIVE_DB; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -public class HiveITBase { - private static final Logger LOG = LoggerFactory.getLogger(HiveITBase.class); - - public static final String DEFAULT_DB = "default"; - public static final String SEP = ":".intern(); - public static final String IO_SEP = "->".intern(); - protected static final String DGI_URL = "http://localhost:21000/"; - protected static final String CLUSTER_NAME = "primary"; - protected static final String PART_FILE = "2015-01-01"; - protected static final String INPUTS = "inputs"; - protected static final String OUTPUTS = "outputs"; - - - protected Driver driver; - protected AtlasClient atlasClient; - protected AtlasClientV2 atlasClientV2; - protected HiveMetaStoreBridge hiveMetaStoreBridge; - protected SessionState ss; - protected HiveConf conf; - protected Driver driverWithoutContext; - - private static final String REFERENCEABLE_ATTRIBUTE_NAME = "qualifiedName"; - private static final String ATTR_NAME = "name"; - - - @BeforeClass - public void setUp() throws Exception { - //Set-up hive session - conf = new HiveConf(); - conf.setClassLoader(Thread.currentThread().getContextClassLoader()); - conf.set("hive.metastore.event.listeners", ""); - - // 'driver' using this configuration will be used for tests in HiveHookIT - // HiveHookIT will use this driver to test post-execution hooks in HiveServer2. - // initialize 'driver' with HMS hook disabled. - driver = new Driver(conf); - ss = new SessionState(conf); - ss = SessionState.start(ss); - - SessionState.setCurrentSessionState(ss); - - Configuration configuration = ApplicationProperties.get(); - - String[] atlasEndPoint = configuration.getStringArray(HiveMetaStoreBridge.ATLAS_ENDPOINT); - - if (atlasEndPoint == null || atlasEndPoint.length == 0) { - atlasEndPoint = new String[] { DGI_URL }; - } - - if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { - atlasClientV2 = new AtlasClientV2(atlasEndPoint, new String[]{"admin", "admin"}); - atlasClient = new AtlasClient(atlasEndPoint, new String[]{"admin", "admin"}); - } else { - atlasClientV2 = new AtlasClientV2(atlasEndPoint); - atlasClient = new AtlasClient(atlasEndPoint); - } - - hiveMetaStoreBridge = new HiveMetaStoreBridge(configuration, conf, atlasClientV2); - - HiveConf conf = new HiveConf(); - - conf.set("hive.exec.post.hooks", ""); - - SessionState ss = new SessionState(conf); - ss = SessionState.start(ss); - SessionState.setCurrentSessionState(ss); - - // 'driverWithoutContext' using this configuration will be used for tests in HiveMetastoreHookIT - // HiveMetastoreHookIT will use this driver to test event listeners in HiveMetastore. - // initialize 'driverWithoutContext' with HiveServer2 post execution hook disabled. - driverWithoutContext = new Driver(conf); - } - - protected void runCommand(String cmd) throws Exception { - runCommandWithDelay(cmd, 0); - } - - protected void runCommand(Driver driver, String cmd) throws Exception { - runCommandWithDelay(driver, cmd, 0); - } - - protected void runCommandWithDelay(String cmd, int sleepMs) throws Exception { - runCommandWithDelay(driver, cmd, sleepMs); - } - - protected void runCommandWithDelay(Driver driver, String cmd, int sleepMs) throws Exception { - LOG.debug("Running command '{}'", cmd); - - CommandProcessorResponse response = driver.run(cmd); - - assertEquals(response.getResponseCode(), 0); - - if (sleepMs != 0) { - Thread.sleep(sleepMs); - } - } - - protected String createTestDFSPath(String path) throws Exception { - return "file://" + mkdir(path); - } - - protected String file(String tag) throws Exception { - String filename = System.getProperty("user.dir") + "/target/" + tag + "-data-" + random(); - File file = new File(filename); - file.createNewFile(); - return file.getAbsolutePath(); - } - - protected String mkdir(String tag) throws Exception { - String filename = "./target/" + tag + "-data-" + random(); - File file = new File(filename); - file.mkdirs(); - return file.getAbsolutePath(); - } - - public static String lower(String str) { - if (StringUtils.isEmpty(str)) { - return null; - } - return str.toLowerCase().trim(); - } - - protected String random() { - return RandomStringUtils.randomAlphanumeric(10).toLowerCase(); - } - - protected String tableName() { - return "table_" + random(); - } - - protected String dbName() { - return "db_" + random(); - } - - protected String assertTableIsRegistered(String dbName, String tableName) throws Exception { - return assertTableIsRegistered(dbName, tableName, null, false); - } - - protected String assertTableIsRegistered(String dbName, String tableName, HiveHookIT.AssertPredicate assertPredicate, boolean isTemporary) throws Exception { - LOG.debug("Searching for table {}.{}", dbName, tableName); - String tableQualifiedName = HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, dbName, tableName, isTemporary); - return assertEntityIsRegistered(HiveDataTypes.HIVE_TABLE.getName(), REFERENCEABLE_ATTRIBUTE_NAME, tableQualifiedName, - assertPredicate); - } - - protected String assertEntityIsRegistered(final String typeName, final String property, final String value, - final HiveHookIT.AssertPredicate assertPredicate) throws Exception { - waitFor(100000, new HiveHookIT.Predicate() { - @Override - public void evaluate() throws Exception { - AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfo = atlasClientV2.getEntityByAttribute(typeName, Collections.singletonMap(property,value)); - AtlasEntity entity = atlasEntityWithExtInfo.getEntity(); - assertNotNull(entity); - if (assertPredicate != null) { - assertPredicate.assertOnEntity(entity); - } - } - }); - AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfo = atlasClientV2.getEntityByAttribute(typeName, Collections.singletonMap(property,value)); - AtlasEntity entity = atlasEntityWithExtInfo.getEntity(); - return (String) entity.getGuid(); - } - - protected String assertEntityIsRegisteredViaGuid(String guid, - final HiveHookIT.AssertPredicate assertPredicate) throws Exception { - waitFor(100000, new HiveHookIT.Predicate() { - @Override - public void evaluate() throws Exception { - AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfo = atlasClientV2.getEntityByGuid(guid); - AtlasEntity entity = atlasEntityWithExtInfo.getEntity(); - assertNotNull(entity); - if (assertPredicate != null) { - assertPredicate.assertOnEntity(entity); - } - - } - }); - AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfo = atlasClientV2.getEntityByGuid(guid); - AtlasEntity entity = atlasEntityWithExtInfo.getEntity(); - return (String) entity.getGuid(); - } - - protected AtlasEntity assertEntityIsRegistedViaEntity(final String typeName, final String property, final String value, - final HiveHookIT.AssertPredicate assertPredicate) throws Exception { - waitFor(80000, new HiveHookIT.Predicate() { - @Override - public void evaluate() throws Exception { - AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfo = atlasClientV2.getEntityByAttribute(typeName, Collections.singletonMap(property,value)); - AtlasEntity entity = atlasEntityWithExtInfo.getEntity(); - assertNotNull(entity); - if (assertPredicate != null) { - assertPredicate.assertOnEntity(entity); - } - } - }); - AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfo = atlasClientV2.getEntityByAttribute(typeName, Collections.singletonMap(property,value)); - AtlasEntity entity = atlasEntityWithExtInfo.getEntity(); - return entity; - } - - public interface AssertPredicate { - void assertOnEntity(AtlasEntity entity) throws Exception; - } - - public interface Predicate { - /** - * Perform a predicate evaluation. - * - * @return the boolean result of the evaluation. - * @throws Exception thrown if the predicate evaluation could not evaluate. - */ - void evaluate() throws Exception; - } - - /** - * Wait for a condition, expressed via a {@link Predicate} to become true. - * - * @param timeout maximum time in milliseconds to wait for the predicate to become true. - * @param predicate predicate waiting on. - */ - protected void waitFor(int timeout, Predicate predicate) throws Exception { - ParamChecker.notNull(predicate, "predicate"); - long mustEnd = System.currentTimeMillis() + timeout; - - while (true) { - try { - predicate.evaluate(); - return; - } catch(Error | Exception e) { - if (System.currentTimeMillis() >= mustEnd) { - fail("Assertions failed. Failing after waiting for timeout " + timeout + " msecs", e); - } - LOG.debug("Waiting up to {} msec as assertion failed", mustEnd - System.currentTimeMillis(), e); - Thread.sleep(5000); - } - } - } - - protected String getTableProcessQualifiedName(String dbName, String tableName) throws Exception { - return HiveMetaStoreBridge.getTableProcessQualifiedName(CLUSTER_NAME, - hiveMetaStoreBridge.getHiveClient().getTable(dbName, tableName)); - } - - protected void validateHDFSPaths(AtlasEntity processEntity, String attributeName, String... testPaths) throws Exception { - List hdfsPathIds = toAtlasObjectIdList(processEntity.getAttribute(attributeName)); - - for (String testPath : testPaths) { - Path path = new Path(testPath); - String testPathNormed = lower(path.toString()); - String hdfsPathId = assertHDFSPathIsRegistered(testPathNormed); - - assertHDFSPathIdsContain(hdfsPathIds, hdfsPathId); - } - } - - private void assertHDFSPathIdsContain(List hdfsPathObjectIds, String hdfsPathId) { - Set hdfsPathGuids = new HashSet<>(); - - for (AtlasObjectId hdfsPathObjectId : hdfsPathObjectIds) { - hdfsPathGuids.add(hdfsPathObjectId.getGuid()); - } - - assertTrue(hdfsPathGuids.contains(hdfsPathId)); - } - - protected String assertHDFSPathIsRegistered(String path) throws Exception { - LOG.debug("Searching for hdfs path {}", path); - // ATLAS-2444 HDFS name node federation adds the cluster name to the qualifiedName - if (path.startsWith("hdfs://")) { - String pathWithCluster = path + "@" + CLUSTER_NAME; - return assertEntityIsRegistered(HDFS_PATH, REFERENCEABLE_ATTRIBUTE_NAME, pathWithCluster, null); - } else { - return assertEntityIsRegistered(HDFS_PATH, REFERENCEABLE_ATTRIBUTE_NAME, path, null); - } - } - - protected String assertDatabaseIsRegistered(String dbName) throws Exception { - return assertDatabaseIsRegistered(dbName, null); - } - - protected String assertDatabaseIsRegistered(String dbName, AssertPredicate assertPredicate) throws Exception { - LOG.debug("Searching for database: {}", dbName); - - String dbQualifiedName = HiveMetaStoreBridge.getDBQualifiedName(CLUSTER_NAME, dbName); - - return assertEntityIsRegistered(HIVE_DB.getName(), REFERENCEABLE_ATTRIBUTE_NAME, dbQualifiedName, assertPredicate); - } - - public void assertDatabaseIsNotRegistered(String dbName) throws Exception { - LOG.debug("Searching for database {}", dbName); - String dbQualifiedName = HiveMetaStoreBridge.getDBQualifiedName(CLUSTER_NAME, dbName); - assertEntityIsNotRegistered(HIVE_DB.getName(), ATTRIBUTE_QUALIFIED_NAME, dbQualifiedName); - } - - protected void assertEntityIsNotRegistered(final String typeName, final String property, final String value) throws Exception { - // wait for sufficient time before checking if entity is not available. - long waitTime = 10000; - LOG.debug("Waiting for {} msecs, before asserting entity is not registered.", waitTime); - Thread.sleep(waitTime); - - try { - atlasClientV2.getEntityByAttribute(typeName, Collections.singletonMap(property, value)); - - fail(String.format("Entity was not supposed to exist for typeName = %s, attributeName = %s, attributeValue = %s", typeName, property, value)); - } catch (AtlasServiceException e) { - if (e.getStatus() == NOT_FOUND) { - return; - } - } - } - - protected AtlasEntity getAtlasEntityByType(String type, String id) throws Exception { - AtlasEntity atlasEntity = null; - AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfoForProcess = atlasClientV2.getEntityByAttribute(type, - Collections.singletonMap(AtlasClient.GUID, id)); - atlasEntity = atlasEntityWithExtInfoForProcess.getEntity(); - return atlasEntity; - } - - - public static class HiveEventContext { - private Set inputs; - private Set outputs; - - private String user; - private UserGroupInformation ugi; - private HiveOperation operation; - private HookContext.HookType hookType; - private JSONObject jsonPlan; - private String queryId; - private String queryStr; - private Long queryStartTime; - - public Map> lineageInfo; - - private List messages = new ArrayList<>(); - - public void setInputs(Set inputs) { - this.inputs = inputs; - } - - public void setOutputs(Set outputs) { - this.outputs = outputs; - } - - public void setUser(String user) { - this.user = user; - } - - public void setUgi(UserGroupInformation ugi) { - this.ugi = ugi; - } - - public void setOperation(HiveOperation operation) { - this.operation = operation; - } - - public void setHookType(HookContext.HookType hookType) { - this.hookType = hookType; - } - - public void setQueryId(String queryId) { - this.queryId = queryId; - } - - public void setQueryStr(String queryStr) { - this.queryStr = queryStr; - } - - public void setQueryStartTime(Long queryStartTime) { - this.queryStartTime = queryStartTime; - } - - public void setLineageInfo(LineageInfo lineageInfo){ - try { - this.lineageInfo = ColumnLineageUtils.buildLineageMap(lineageInfo); - LOG.debug("Column Lineage Map => {} ", this.lineageInfo.entrySet()); - }catch (Throwable e){ - LOG.warn("Column Lineage Map build failed with exception {}", e); - } - } - - public Set getInputs() { - return inputs; - } - - public Set getOutputs() { - return outputs; - } - - public String getUser() { - return user; - } - - public UserGroupInformation getUgi() { - return ugi; - } - - public HiveOperation getOperation() { - return operation; - } - - public HookContext.HookType getHookType() { - return hookType; - } - - public String getQueryId() { - return queryId; - } - - public String getQueryStr() { - return queryStr; - } - - public Long getQueryStartTime() { - return queryStartTime; - } - - public void addMessage(HookNotification message) { - messages.add(message); - } - - public List getMessages() { - return messages; - } - } - - - @VisibleForTesting - protected static String getProcessQualifiedName(HiveMetaStoreBridge dgiBridge, HiveEventContext eventContext, - final SortedSet sortedHiveInputs, - final SortedSet sortedHiveOutputs, - SortedMap hiveInputsMap, - SortedMap hiveOutputsMap) throws HiveException { - HiveOperation op = eventContext.getOperation(); - if (isCreateOp(eventContext)) { - Entity entity = getEntityByType(sortedHiveOutputs, Entity.Type.TABLE); - - if (entity != null) { - Table outTable = entity.getTable(); - //refresh table - outTable = dgiBridge.getHiveClient().getTable(outTable.getDbName(), outTable.getTableName()); - return HiveMetaStoreBridge.getTableProcessQualifiedName(dgiBridge.getMetadataNamespace(), outTable); - } - } - - StringBuilder buffer = new StringBuilder(op.getOperationName()); - - boolean ignoreHDFSPathsinQFName = ignoreHDFSPathsinQFName(op, sortedHiveInputs, sortedHiveOutputs); - if ( ignoreHDFSPathsinQFName && LOG.isDebugEnabled()) { - LOG.debug("Ignoring HDFS paths in qualifiedName for {} {} ", op, eventContext.getQueryStr()); - } - - addInputs(dgiBridge, op, sortedHiveInputs, buffer, hiveInputsMap, ignoreHDFSPathsinQFName); - buffer.append(IO_SEP); - addOutputs(dgiBridge, op, sortedHiveOutputs, buffer, hiveOutputsMap, ignoreHDFSPathsinQFName); - LOG.info("Setting process qualified name to {}", buffer); - return buffer.toString(); - } - - protected static Entity getEntityByType(Set entities, Entity.Type entityType) { - for (Entity entity : entities) { - if (entity.getType() == entityType) { - return entity; - } - } - return null; - } - - - protected static boolean ignoreHDFSPathsinQFName(final HiveOperation op, final Set inputs, final Set outputs) { - switch (op) { - case LOAD: - case IMPORT: - return isPartitionBasedQuery(outputs); - case EXPORT: - return isPartitionBasedQuery(inputs); - case QUERY: - return true; - } - return false; - } - - protected static boolean isPartitionBasedQuery(Set entities) { - for (Entity entity : entities) { - if (Entity.Type.PARTITION.equals(entity.getType())) { - return true; - } - } - return false; - } - - protected static boolean isCreateOp(HiveEventContext hiveEvent) { - return HiveOperation.CREATETABLE.equals(hiveEvent.getOperation()) - || HiveOperation.CREATEVIEW.equals(hiveEvent.getOperation()) - || HiveOperation.ALTERVIEW_AS.equals(hiveEvent.getOperation()) - || HiveOperation.ALTERTABLE_LOCATION.equals(hiveEvent.getOperation()) - || HiveOperation.CREATETABLE_AS_SELECT.equals(hiveEvent.getOperation()); - } - - protected static void addInputs(HiveMetaStoreBridge hiveBridge, HiveOperation op, SortedSet sortedInputs, StringBuilder buffer, final Map refs, final boolean ignoreHDFSPathsInQFName) throws HiveException { - if (refs != null) { - if (sortedInputs != null) { - Set dataSetsProcessed = new LinkedHashSet<>(); - for (Entity input : sortedInputs) { - - if (!dataSetsProcessed.contains(input.getName().toLowerCase())) { - //HiveOperation.QUERY type encompasses INSERT, INSERT_OVERWRITE, UPDATE, DELETE, PATH_WRITE operations - if (ignoreHDFSPathsInQFName && - (Entity.Type.DFS_DIR.equals(input.getType()) || Entity.Type.LOCAL_DIR.equals(input.getType()))) { - LOG.debug("Skipping dfs dir input addition to process qualified name {} ", input.getName()); - } else if (refs.containsKey(input)) { - if ( input.getType() == Entity.Type.PARTITION || input.getType() == Entity.Type.TABLE) { - Table inputTable = refreshTable(hiveBridge, input.getTable().getDbName(), input.getTable().getTableName()); - - if (inputTable != null) { - addDataset(buffer, refs.get(input), HiveMetaStoreBridge.getTableCreatedTime(inputTable)); - } - } else { - addDataset(buffer, refs.get(input)); - } - } - - dataSetsProcessed.add(input.getName().toLowerCase()); - } - } - - } - } - } - - protected static void addDataset(StringBuilder buffer, AtlasEntity ref, final long createTime) { - addDataset(buffer, ref); - buffer.append(SEP); - buffer.append(createTime); - } - - protected static void addDataset(StringBuilder buffer, AtlasEntity ref) { - buffer.append(SEP); - String dataSetQlfdName = (String) ref.getAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME); - // '/' breaks query parsing on ATLAS - buffer.append(dataSetQlfdName.toLowerCase().replaceAll("/", "")); - } - - protected static void addOutputs(HiveMetaStoreBridge hiveBridge, HiveOperation op, SortedSet sortedOutputs, StringBuilder buffer, final Map refs, final boolean ignoreHDFSPathsInQFName) throws HiveException { - if (refs != null) { - Set dataSetsProcessed = new LinkedHashSet<>(); - if (sortedOutputs != null) { - for (WriteEntity output : sortedOutputs) { - final Entity entity = output; - if (!dataSetsProcessed.contains(output.getName().toLowerCase())) { - if (ignoreHDFSPathsInQFName && - (Entity.Type.DFS_DIR.equals(output.getType()) || Entity.Type.LOCAL_DIR.equals(output.getType()))) { - LOG.debug("Skipping dfs dir output addition to process qualified name {} ", output.getName()); - } else if (refs.containsKey(output)) { - //HiveOperation.QUERY type encompasses INSERT, INSERT_OVERWRITE, UPDATE, DELETE, PATH_WRITE operations - if (addQueryType(op, (WriteEntity) entity)) { - buffer.append(SEP); - buffer.append(((WriteEntity) entity).getWriteType().name()); - } - - if ( output.getType() == Entity.Type.PARTITION || output.getType() == Entity.Type.TABLE) { - Table outputTable = refreshTable(hiveBridge, output.getTable().getDbName(), output.getTable().getTableName()); - - if (outputTable != null) { - addDataset(buffer, refs.get(output), HiveMetaStoreBridge.getTableCreatedTime(outputTable)); - } - } else { - addDataset(buffer, refs.get(output)); - } - } - - dataSetsProcessed.add(output.getName().toLowerCase()); - } - } - } - } - } - - protected static Table refreshTable(HiveMetaStoreBridge dgiBridge, String dbName, String tableName) { - try { - return dgiBridge.getHiveClient().getTable(dbName, tableName); - } catch (HiveException excp) { // this might be the case for temp tables - LOG.warn("failed to get details for table {}.{}. Ignoring. {}: {}", dbName, tableName, excp.getClass().getCanonicalName(), excp.getMessage()); - } - - return null; - } - - protected static boolean addQueryType(HiveOperation op, WriteEntity entity) { - if (entity.getWriteType() != null && HiveOperation.QUERY.equals(op)) { - switch (entity.getWriteType()) { - case INSERT: - case INSERT_OVERWRITE: - case UPDATE: - case DELETE: - return true; - case PATH_WRITE: - //Add query type only for DFS paths and ignore local paths since they are not added as outputs - if ( !Entity.Type.LOCAL_DIR.equals(entity.getType())) { - return true; - } - break; - default: - } - } - return false; - } - - - @VisibleForTesting - protected static final class EntityComparator implements Comparator { - @Override - public int compare(Entity o1, Entity o2) { - String s1 = o1.getName(); - String s2 = o2.getName(); - if (s1 == null || s2 == null){ - s1 = o1.getD().toString(); - s2 = o2.getD().toString(); - } - return s1.toLowerCase().compareTo(s2.toLowerCase()); - } - } - - @VisibleForTesting - protected static final Comparator entityComparator = new EntityComparator(); - - protected AtlasObjectId toAtlasObjectId(Object obj) { - final AtlasObjectId ret; - - if (obj instanceof AtlasObjectId) { - ret = (AtlasObjectId) obj; - } else if (obj instanceof Map) { - ret = new AtlasObjectId((Map) obj); - } else if (obj != null) { - ret = new AtlasObjectId(obj.toString()); // guid - } else { - ret = null; - } - - return ret; - } - - protected List toAtlasObjectIdList(Object obj) { - final List ret; - - if (obj instanceof Collection) { - Collection coll = (Collection) obj; - - ret = new ArrayList<>(coll.size()); - - for (Object item : coll) { - AtlasObjectId objId = toAtlasObjectId(item); - - if (objId != null) { - ret.add(objId); - } - } - } else { - AtlasObjectId objId = toAtlasObjectId(obj); - - if (objId != null) { - ret = new ArrayList<>(1); - - ret.add(objId); - } else { - ret = null; - } - } - - return ret; - } - - protected AtlasStruct toAtlasStruct(Object obj) { - final AtlasStruct ret; - - if (obj instanceof AtlasStruct) { - ret = (AtlasStruct) obj; - } else if (obj instanceof Map) { - ret = new AtlasStruct((Map) obj); - } else { - ret = null; - } - - return ret; - } - - protected List toAtlasStructList(Object obj) { - final List ret; - - if (obj instanceof Collection) { - Collection coll = (Collection) obj; - - ret = new ArrayList<>(coll.size()); - - for (Object item : coll) { - AtlasStruct struct = toAtlasStruct(item); - - if (struct != null) { - ret.add(struct); - } - } - } else { - AtlasStruct struct = toAtlasStruct(obj); - - if (struct != null) { - ret = new ArrayList<>(1); - - ret.add(struct); - } else { - ret = null; - } - } - - return ret; - } -} diff --git a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/bridge/ColumnLineageUtils.java b/addons/hive-bridge/src/test/java/org/apache/atlas/hive/bridge/ColumnLineageUtils.java deleted file mode 100644 index 22397f1e1a9..00000000000 --- a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/bridge/ColumnLineageUtils.java +++ /dev/null @@ -1,161 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.bridge; - -import org.apache.atlas.hive.model.HiveDataTypes; -import org.apache.atlas.v1.model.instance.Referenceable; -import org.apache.hadoop.hive.ql.hooks.LineageInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.apache.atlas.hive.hook.events.BaseHiveEvent.ATTRIBUTE_COLUMNS; -import static org.apache.atlas.hive.hook.events.BaseHiveEvent.ATTRIBUTE_QUALIFIED_NAME; - - -public class ColumnLineageUtils { - public static final Logger LOG = LoggerFactory.getLogger(ColumnLineageUtils.class); - public static class HiveColumnLineageInfo { - public final String depenendencyType; - public final String expr; - public final String inputColumn; - - HiveColumnLineageInfo(LineageInfo.Dependency d, String inputCol) { - depenendencyType = d.getType().name(); - expr = d.getExpr(); - inputColumn = inputCol; - } - - @Override - public String toString(){ - return inputColumn; - } - } - - public static String getQualifiedName(LineageInfo.DependencyKey key){ - String db = key.getDataContainer().getTable().getDbName(); - String table = key.getDataContainer().getTable().getTableName(); - String col = key.getFieldSchema().getName(); - return db + "." + table + "." + col; - } - - public static Map> buildLineageMap(LineageInfo lInfo) { - Map> m = new HashMap<>(); - - for (Map.Entry e : lInfo.entrySet()) { - List l = new ArrayList<>(); - String k = getQualifiedName(e.getKey()); - - if (LOG.isDebugEnabled()) { - LOG.debug("buildLineageMap(): key={}; value={}", e.getKey(), e.getValue()); - } - - Collection baseCols = getBaseCols(e.getValue()); - - if (baseCols != null) { - for (LineageInfo.BaseColumnInfo iCol : baseCols) { - String db = iCol.getTabAlias().getTable().getDbName(); - String table = iCol.getTabAlias().getTable().getTableName(); - String colQualifiedName = iCol.getColumn() == null ? db + "." + table : db + "." + table + "." + iCol.getColumn().getName(); - l.add(new HiveColumnLineageInfo(e.getValue(), colQualifiedName)); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("Setting lineage --> Input: {} ==> Output : {}", l, k); - } - m.put(k, l); - } - } - return m; - } - - static Collection getBaseCols(LineageInfo.Dependency lInfoDep) { - Collection ret = null; - - if (lInfoDep != null) { - try { - Method getBaseColsMethod = lInfoDep.getClass().getMethod("getBaseCols"); - - Object retGetBaseCols = getBaseColsMethod.invoke(lInfoDep); - - if (retGetBaseCols != null) { - if (retGetBaseCols instanceof Collection) { - ret = (Collection) retGetBaseCols; - } else { - LOG.warn("{}: unexpected return type from LineageInfo.Dependency.getBaseCols(), expected type {}", - retGetBaseCols.getClass().getName(), "Collection"); - } - } - } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException ex) { - LOG.warn("getBaseCols()", ex); - } - } - - return ret; - } - - static String[] extractComponents(String qualifiedName) { - String[] comps = qualifiedName.split("\\."); - int lastIdx = comps.length - 1; - int atLoc = comps[lastIdx].indexOf('@'); - if (atLoc > 0) { - comps[lastIdx] = comps[lastIdx].substring(0, atLoc); - } - return comps; - } - - static void populateColumnReferenceableMap(Map m, - Referenceable r) { - if (r.getTypeName().equals(HiveDataTypes.HIVE_TABLE.getName())) { - String qName = (String) r.get(ATTRIBUTE_QUALIFIED_NAME); - String[] qNameComps = extractComponents(qName); - for (Referenceable col : (List) r.get(ATTRIBUTE_COLUMNS)) { - String cName = (String) col.get(ATTRIBUTE_QUALIFIED_NAME); - String[] colQNameComps = extractComponents(cName); - String colQName = colQNameComps[0] + "." + colQNameComps[1] + "." + colQNameComps[2]; - m.put(colQName, col); - } - String tableQName = qNameComps[0] + "." + qNameComps[1]; - m.put(tableQName, r); - } - } - - - public static Map buildColumnReferenceableMap(List inputs, - List outputs) { - Map m = new HashMap<>(); - - for (Referenceable r : inputs) { - populateColumnReferenceableMap(m, r); - } - - for (Referenceable r : outputs) { - populateColumnReferenceableMap(m, r); - } - - return m; - } -} diff --git a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridgeTest.java b/addons/hive-bridge/src/test/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridgeTest.java deleted file mode 100644 index ae7ab1a2201..00000000000 --- a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/bridge/HiveMetaStoreBridgeTest.java +++ /dev/null @@ -1,327 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.bridge; - -import org.apache.atlas.AtlasClient; -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.AtlasServiceException; -import org.apache.atlas.hive.model.HiveDataTypes; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.EntityMutationResponse; -import org.apache.atlas.type.AtlasTypeUtil; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.hive.metastore.TableType; -import org.apache.hadoop.hive.metastore.api.Database; -import org.apache.hadoop.hive.metastore.api.FieldSchema; -import org.apache.hadoop.hive.ql.metadata.Hive; -import org.apache.hadoop.hive.ql.metadata.HiveException; -import org.apache.hadoop.hive.ql.metadata.Partition; -import org.apache.hadoop.hive.ql.metadata.Table; -import org.apache.hadoop.mapred.TextInputFormat; -import org.mockito.ArgumentMatcher; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.testng.Assert; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import java.util.Arrays; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static org.apache.atlas.hive.hook.events.BaseHiveEvent.*; -import static org.mockito.Matchers.anyObject; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class HiveMetaStoreBridgeTest { - private static final String TEST_DB_NAME = "default"; - public static final String METADATA_NAMESPACE = "primary"; - public static final String TEST_TABLE_NAME = "test_table"; - - @Mock - private Hive hiveClient; - - @Mock - private AtlasClient atlasClient; - - @Mock - private AtlasClientV2 atlasClientV2; - - @Mock - private AtlasEntity atlasEntity; - - @Mock - private AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfo; - - @Mock - EntityMutationResponse entityMutationResponse; - - @BeforeMethod - public void initializeMocks() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void testImportThatUpdatesRegisteredDatabase() throws Exception { - // setup database - when(hiveClient.getAllDatabases()).thenReturn(Arrays.asList(new String[]{TEST_DB_NAME})); - String description = "This is a default database"; - Database db = new Database(TEST_DB_NAME, description, "/user/hive/default", null); - when(hiveClient.getDatabase(TEST_DB_NAME)).thenReturn(db); - when(hiveClient.getAllTables(TEST_DB_NAME)).thenReturn(Arrays.asList(new String[]{})); - - returnExistingDatabase(TEST_DB_NAME, atlasClientV2, METADATA_NAMESPACE); - - when(atlasEntityWithExtInfo.getEntity("72e06b34-9151-4023-aa9d-b82103a50e76")) - .thenReturn((new AtlasEntity.AtlasEntityWithExtInfo( - getEntity(HiveDataTypes.HIVE_DB.getName(), AtlasClient.GUID, "72e06b34-9151-4023-aa9d-b82103a50e76"))).getEntity()); - - HiveMetaStoreBridge bridge = new HiveMetaStoreBridge(METADATA_NAMESPACE, hiveClient, atlasClientV2); - bridge.importHiveMetadata(null, null, true); - - // verify update is called - verify(atlasClientV2).updateEntity(anyObject()); - } - - @Test - public void testImportThatUpdatesRegisteredTable() throws Exception { - setupDB(hiveClient, TEST_DB_NAME); - - List

hiveTables = setupTables(hiveClient, TEST_DB_NAME, TEST_TABLE_NAME); - - returnExistingDatabase(TEST_DB_NAME, atlasClientV2, METADATA_NAMESPACE); - - // return existing table - - when(atlasEntityWithExtInfo.getEntity("82e06b34-9151-4023-aa9d-b82103a50e77")) - .thenReturn((new AtlasEntity.AtlasEntityWithExtInfo( - getEntity(HiveDataTypes.HIVE_TABLE.getName(), AtlasClient.GUID, "82e06b34-9151-4023-aa9d-b82103a50e77"))).getEntity()); - - when(atlasClientV2.getEntityByAttribute(HiveDataTypes.HIVE_TABLE.getName(), - Collections.singletonMap(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - HiveMetaStoreBridge.getTableQualifiedName(METADATA_NAMESPACE, TEST_DB_NAME, TEST_TABLE_NAME)), true, true )) - .thenReturn(new AtlasEntity.AtlasEntityWithExtInfo( - getEntity(HiveDataTypes.HIVE_TABLE.getName(), AtlasClient.GUID, "82e06b34-9151-4023-aa9d-b82103a50e77"))); - - when(atlasEntityWithExtInfo.getEntity("82e06b34-9151-4023-aa9d-b82103a50e77")) - .thenReturn(createTableReference()); - - Table testTable = hiveTables.get(0); - String processQualifiedName = HiveMetaStoreBridge.getTableProcessQualifiedName(METADATA_NAMESPACE, testTable); - - when(atlasClientV2.getEntityByAttribute(HiveDataTypes.HIVE_PROCESS.getName(), - Collections.singletonMap(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - processQualifiedName), true ,true)) - .thenReturn(new AtlasEntity.AtlasEntityWithExtInfo( - getEntity(HiveDataTypes.HIVE_PROCESS.getName(), AtlasClient.GUID, "82e06b34-9151-4023-aa9d-b82103a50e77"))); - - - HiveMetaStoreBridge bridge = new HiveMetaStoreBridge(METADATA_NAMESPACE, hiveClient, atlasClientV2); - bridge.importHiveMetadata(null, null, true); - - // verify update is called on table - verify(atlasClientV2, times(2)).updateEntity(anyObject()); - - } - - private void returnExistingDatabase(String databaseName, AtlasClientV2 atlasClientV2, String metadataNamespace) - throws AtlasServiceException { - //getEntity(HiveDataTypes.HIVE_DB.getName(), AtlasClient.GUID, "72e06b34-9151-4023-aa9d-b82103a50e76"); - - when(atlasClientV2.getEntityByAttribute(HiveDataTypes.HIVE_DB.getName(), - Collections.singletonMap(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - HiveMetaStoreBridge.getDBQualifiedName(METADATA_NAMESPACE, TEST_DB_NAME)), true, true)) - .thenReturn((new AtlasEntity.AtlasEntityWithExtInfo( - getEntity(HiveDataTypes.HIVE_DB.getName(), AtlasClient.GUID, "72e06b34-9151-4023-aa9d-b82103a50e76")))); - - } - - private List
setupTables(Hive hiveClient, String databaseName, String... tableNames) throws HiveException { - List
tables = new ArrayList<>(); - when(hiveClient.getAllTables(databaseName)).thenReturn(Arrays.asList(tableNames)); - for(String tableName : tableNames) { - Table testTable = createTestTable(databaseName, tableName); - when(hiveClient.getTable(databaseName, tableName)).thenReturn(testTable); - tables.add(testTable); - } - return tables; - } - - private void setupDB(Hive hiveClient, String databaseName) throws HiveException { - when(hiveClient.getAllDatabases()).thenReturn(Arrays.asList(new String[]{databaseName})); - when(hiveClient.getDatabase(databaseName)).thenReturn( - new Database(databaseName, "Default database", "/user/hive/default", null)); - } - - @Test - public void testImportWhenPartitionKeysAreNull() throws Exception { - setupDB(hiveClient, TEST_DB_NAME); - List
hiveTables = setupTables(hiveClient, TEST_DB_NAME, TEST_TABLE_NAME); - Table hiveTable = hiveTables.get(0); - - returnExistingDatabase(TEST_DB_NAME, atlasClientV2, METADATA_NAMESPACE); - - - when(atlasClientV2.getEntityByAttribute(HiveDataTypes.HIVE_TABLE.getName(), - Collections.singletonMap(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - HiveMetaStoreBridge.getTableQualifiedName(METADATA_NAMESPACE, TEST_DB_NAME, TEST_TABLE_NAME)), true, true)) - .thenReturn(new AtlasEntity.AtlasEntityWithExtInfo( - getEntity(HiveDataTypes.HIVE_TABLE.getName(), AtlasClient.GUID, "82e06b34-9151-4023-aa9d-b82103a50e77"))); - - String processQualifiedName = HiveMetaStoreBridge.getTableProcessQualifiedName(METADATA_NAMESPACE, hiveTable); - - when(atlasClientV2.getEntityByAttribute(HiveDataTypes.HIVE_PROCESS.getName(), - Collections.singletonMap(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - processQualifiedName), true, true)) - .thenReturn(new AtlasEntity.AtlasEntityWithExtInfo( - getEntity(HiveDataTypes.HIVE_PROCESS.getName(), AtlasClient.GUID, "82e06b34-9151-4023-aa9d-b82103a50e77"))); - - when(atlasEntityWithExtInfo.getEntity("82e06b34-9151-4023-aa9d-b82103a50e77")) - .thenReturn(createTableReference()); - - Partition partition = mock(Partition.class); - when(partition.getTable()).thenReturn(hiveTable); - List partitionValues = Arrays.asList(new String[]{}); - when(partition.getValues()).thenReturn(partitionValues); - - when(hiveClient.getPartitions(hiveTable)).thenReturn(Arrays.asList(new Partition[]{partition})); - - HiveMetaStoreBridge bridge = new HiveMetaStoreBridge(METADATA_NAMESPACE, hiveClient, atlasClientV2); - try { - bridge.importHiveMetadata(null, null, true); - } catch (Exception e) { - Assert.fail("Partition with null key caused import to fail with exception ", e); - } - } - - @Test - public void testImportContinuesWhenTableRegistrationFails() throws Exception { - setupDB(hiveClient, TEST_DB_NAME); - final String table2Name = TEST_TABLE_NAME + "_1"; - List
hiveTables = setupTables(hiveClient, TEST_DB_NAME, TEST_TABLE_NAME, table2Name); - - returnExistingDatabase(TEST_DB_NAME, atlasClientV2, METADATA_NAMESPACE); - when(hiveClient.getTable(TEST_DB_NAME, TEST_TABLE_NAME)).thenThrow(new RuntimeException("Timeout while reading data from hive metastore")); - - when(atlasClientV2.getEntityByAttribute(HiveDataTypes.HIVE_TABLE.getName(), - Collections.singletonMap(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - HiveMetaStoreBridge.getTableQualifiedName(METADATA_NAMESPACE, TEST_DB_NAME, TEST_TABLE_NAME)))) - .thenReturn(new AtlasEntity.AtlasEntityWithExtInfo( - getEntity(HiveDataTypes.HIVE_TABLE.getName(), AtlasClient.GUID, "82e06b34-9151-4023-aa9d-b82103a50e77"))); - - when(atlasEntityWithExtInfo.getEntity("82e06b34-9151-4023-aa9d-b82103a50e77")) - .thenReturn(createTableReference()); - - Table testTable = hiveTables.get(1); - String processQualifiedName = HiveMetaStoreBridge.getTableProcessQualifiedName(METADATA_NAMESPACE, testTable); - - when(atlasClientV2.getEntityByAttribute(HiveDataTypes.HIVE_PROCESS.getName(), - Collections.singletonMap(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - processQualifiedName))) - .thenReturn(new AtlasEntity.AtlasEntityWithExtInfo( - getEntity(HiveDataTypes.HIVE_PROCESS.getName(), AtlasClient.GUID, "82e06b34-9151-4023-aa9d-b82103a50e77"))); - - HiveMetaStoreBridge bridge = new HiveMetaStoreBridge(METADATA_NAMESPACE, hiveClient, atlasClientV2); - try { - bridge.importHiveMetadata(null, null, false); - } catch (Exception e) { - Assert.fail("Table registration failed with exception", e); - } - } - - @Test - public void testImportFailsWhenTableRegistrationFails() throws Exception { - setupDB(hiveClient, TEST_DB_NAME); - final String table2Name = TEST_TABLE_NAME + "_1"; - List
hiveTables = setupTables(hiveClient, TEST_DB_NAME, TEST_TABLE_NAME, table2Name); - - returnExistingDatabase(TEST_DB_NAME, atlasClientV2, METADATA_NAMESPACE); - when(hiveClient.getTable(TEST_DB_NAME, TEST_TABLE_NAME)).thenThrow(new RuntimeException("Timeout while reading data from hive metastore")); - - - when(atlasClientV2.getEntityByAttribute(HiveDataTypes.HIVE_TABLE.getName(), - Collections.singletonMap(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - HiveMetaStoreBridge.getTableQualifiedName(METADATA_NAMESPACE, TEST_DB_NAME, TEST_TABLE_NAME)))) - .thenReturn(new AtlasEntity.AtlasEntityWithExtInfo( - getEntity(HiveDataTypes.HIVE_TABLE.getName(), AtlasClient.GUID, "82e06b34-9151-4023-aa9d-b82103a50e77"))); - - - when(atlasEntityWithExtInfo.getEntity("82e06b34-9151-4023-aa9d-b82103a50e77")) - .thenReturn(createTableReference()); - - Table testTable = hiveTables.get(1); - String processQualifiedName = HiveMetaStoreBridge.getTableProcessQualifiedName(METADATA_NAMESPACE, testTable); - - when(atlasClientV2.getEntityByAttribute(HiveDataTypes.HIVE_PROCESS.getName(), - Collections.singletonMap(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, - processQualifiedName))) - .thenReturn(new AtlasEntity.AtlasEntityWithExtInfo( - getEntity(HiveDataTypes.HIVE_PROCESS.getName(), AtlasClient.GUID, "82e06b34-9151-4023-aa9d-b82103a50e77"))); - - HiveMetaStoreBridge bridge = new HiveMetaStoreBridge(METADATA_NAMESPACE, hiveClient, atlasClientV2); - try { - bridge.importHiveMetadata(null, null, true); - Assert.fail("Table registration is supposed to fail"); - } catch (Exception e) { - //Expected - } - } - - private AtlasEntity getEntity(String typeName, String attr, String value) { - return new AtlasEntity(typeName, attr, value); - } - - private AtlasEntity createTableReference() { - AtlasEntity tableEntity = new AtlasEntity(HiveDataTypes.HIVE_TABLE.getName()); - AtlasEntity sdEntity = new AtlasEntity(HiveDataTypes.HIVE_STORAGEDESC.getName()); - tableEntity.setAttribute(ATTRIBUTE_STORAGEDESC, AtlasTypeUtil.getObjectId(sdEntity)); - return tableEntity; - } - - private Table createTestTable(String databaseName, String tableName) throws HiveException { - Table table = new Table(databaseName, tableName); - table.setInputFormatClass(TextInputFormat.class); - table.setFields(new ArrayList() {{ - add(new FieldSchema("col1", "string", "comment1")); - } - }); - table.setTableType(TableType.EXTERNAL_TABLE); - table.setDataLocation(new Path("somehdfspath")); - return table; - } - - private class MatchesReferenceableProperty implements ArgumentMatcher { - private final String attrName; - private final Object attrValue; - - public MatchesReferenceableProperty(String attrName, Object attrValue) { - this.attrName = attrName; - this.attrValue = attrValue; - } - - @Override - public boolean matches(Object o) { - return attrValue.equals(((AtlasEntity) o).getAttribute(attrName)); - } - } -} diff --git a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/bridge/HiveMetastoreBridgeIT.java b/addons/hive-bridge/src/test/java/org/apache/atlas/hive/bridge/HiveMetastoreBridgeIT.java deleted file mode 100644 index 981600c4e10..00000000000 --- a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/bridge/HiveMetastoreBridgeIT.java +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.bridge; - -import org.apache.atlas.AtlasClient; -import org.apache.atlas.hive.HiveITBase; -import org.apache.atlas.hive.model.HiveDataTypes; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.testng.annotations.Test; - -import java.util.List; - -import static org.testng.Assert.assertEquals; - -public class HiveMetastoreBridgeIT extends HiveITBase { - - @Test - public void testCreateTableAndImport() throws Exception { - String tableName = tableName(); - String pFile = createTestDFSPath("parentPath"); - String query = String.format("create EXTERNAL table %s(id string, cnt int) location '%s'", tableName, pFile); - - runCommand(query); - - String dbId = assertDatabaseIsRegistered(DEFAULT_DB); - String tableId = assertTableIsRegistered(DEFAULT_DB, tableName); - - //verify lineage is created - String processId = assertEntityIsRegistered(HiveDataTypes.HIVE_PROCESS.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, getTableProcessQualifiedName(DEFAULT_DB, tableName), null); - AtlasEntity processsEntity = atlasClientV2.getEntityByGuid(processId).getEntity(); - - validateHDFSPaths(processsEntity, INPUTS, pFile); - - List outputs = toAtlasObjectIdList(processsEntity.getAttribute(OUTPUTS)); - - assertEquals(outputs.size(), 1); - assertEquals(outputs.get(0).getGuid(), tableId); - - int tableCount = atlasClient.listEntities(HiveDataTypes.HIVE_TABLE.getName()).size(); - - //Now import using import tool - should be no-op. This also tests update since table exists - AtlasEntity dbEntity = atlasClientV2.getEntityByGuid(dbId).getEntity(); - - hiveMetaStoreBridge.importTable(dbEntity, DEFAULT_DB, tableName, true); - - String tableId2 = assertTableIsRegistered(DEFAULT_DB, tableName); - assertEquals(tableId2, tableId); - - String processId2 = assertEntityIsRegistered(HiveDataTypes.HIVE_PROCESS.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, getTableProcessQualifiedName(DEFAULT_DB, tableName), null); - assertEquals(processId2, processId); - - //assert that table is de-duped and no new entity is created - int newTableCount = atlasClient.listEntities(HiveDataTypes.HIVE_TABLE.getName()).size(); - assertEquals(newTableCount, tableCount); - } - - @Test - public void testImportCreatedTable() throws Exception { - String tableName = tableName(); - String pFile = createTestDFSPath("parentPath"); - - runCommandWithDelay(driverWithoutContext, String.format("create EXTERNAL table %s(id string) location '%s'", tableName, pFile), 3000); - - String dbId = assertDatabaseIsRegistered(DEFAULT_DB); - - AtlasEntity dbEntity = atlasClientV2.getEntityByGuid(dbId).getEntity(); - - hiveMetaStoreBridge.importTable(dbEntity, DEFAULT_DB, tableName, true); - - String tableId = assertTableIsRegistered(DEFAULT_DB, tableName); - - String processId = assertEntityIsRegistered(HiveDataTypes.HIVE_PROCESS.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, getTableProcessQualifiedName(DEFAULT_DB, tableName), null); - AtlasEntity processEntity = atlasClientV2.getEntityByGuid(processId).getEntity(); - List outputs = toAtlasObjectIdList(processEntity.getAttribute(OUTPUTS)); - - assertEquals(outputs.size(), 1); - assertEquals(outputs.get(0).getGuid(), tableId); - } - - //TODO enable this test - //@Test - public void testCreateTableHiveProcessNameAttribute() throws Exception { - //test if \n is trimmed from name attribute of the process entity - String tableName = tableName(); - String processNameQuery = String.format("create table %s (id string)", tableName); - //add \n at the beginning of the query - String query = String.format("%n%n%s", processNameQuery); - - runCommand(query); - - String dbId = assertDatabaseIsRegistered(DEFAULT_DB); - String tableId = assertTableIsRegistered(DEFAULT_DB, tableName); - - //verify lineage is created and the name attribute is the query without \n - String processId = assertEntityIsRegistered(HiveDataTypes.HIVE_PROCESS.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, getTableProcessQualifiedName(DEFAULT_DB, tableName), null); - AtlasEntity processsEntity = atlasClientV2.getEntityByGuid(processId).getEntity(); - - assertEquals(processsEntity.getAttribute("name"), processNameQuery); - } -} diff --git a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/hook/HiveHookIT.java b/addons/hive-bridge/src/test/java/org/apache/atlas/hive/hook/HiveHookIT.java deleted file mode 100755 index 1db73e5a7c1..00000000000 --- a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/hook/HiveHookIT.java +++ /dev/null @@ -1,2554 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.base.Joiner; -import com.sun.jersey.api.client.ClientResponse; -import org.apache.atlas.AtlasClient; -import org.apache.atlas.AtlasServiceException; -import org.apache.atlas.hive.HiveITBase; -import org.apache.atlas.hive.bridge.HiveMetaStoreBridge; -import org.apache.atlas.hive.hook.events.BaseHiveEvent; -import org.apache.atlas.hive.model.HiveDataTypes; -import org.apache.atlas.model.instance.*; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; -import org.apache.atlas.model.lineage.AtlasLineageInfo; -import org.apache.atlas.model.typedef.AtlasClassificationDef; -import org.apache.atlas.model.typedef.AtlasEntityDef; -import org.apache.atlas.model.typedef.AtlasTypesDef; -import org.apache.atlas.type.AtlasTypeUtil; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.hive.conf.HiveConf; -import org.apache.hadoop.hive.metastore.TableType; -import org.apache.hadoop.hive.metastore.api.hive_metastoreConstants; -import org.apache.hadoop.hive.ql.Driver; -import org.apache.hadoop.hive.ql.hooks.Entity; -import org.apache.hadoop.hive.ql.hooks.ReadEntity; -import org.apache.hadoop.hive.ql.hooks.WriteEntity; -import org.apache.hadoop.hive.ql.metadata.HiveException; -import org.apache.hadoop.hive.ql.metadata.Table; -import org.apache.hadoop.hive.ql.plan.HiveOperation; -import org.apache.hadoop.hive.ql.session.SessionState; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import java.text.ParseException; -import java.util.*; - -import static org.apache.atlas.AtlasClient.NAME; -import static org.apache.atlas.hive.hook.events.BaseHiveEvent.*; -import static org.testng.Assert.*; -import static org.testng.AssertJUnit.assertEquals; - -public class HiveHookIT extends HiveITBase { - private static final Logger LOG = LoggerFactory.getLogger(HiveHookIT.class); - - private static final String PART_FILE = "2015-01-01"; - private static final String PATH_TYPE_NAME = "Path"; - - private Driver driverWithNoHook; - - @BeforeClass - public void setUp() throws Exception { - // initialize 'driverWithNoHook' with HiveServer2 hook and HiveMetastore hook disabled - HiveConf conf = new HiveConf(); - conf.set("hive.exec.post.hooks", ""); - conf.set("hive.metastore.event.listeners", ""); - - SessionState ss = new SessionState(conf); - ss = SessionState.start(ss); - SessionState.setCurrentSessionState(ss); - - // Initialize 'driverWithNoHook' with HS2 hook disabled and HMS hook disabled. - driverWithNoHook = new Driver(conf); - - super.setUp(); - } - - @Test - public void testCreateDatabase() throws Exception { - String dbName = "db" + random(); - - runCommand("create database " + dbName + " WITH DBPROPERTIES ('p1'='v1', 'p2'='v2')"); - - String dbId = assertDatabaseIsRegistered(dbName); - AtlasEntity dbEntity = atlasClientV2.getEntityByGuid(dbId).getEntity(); - Map params = (Map) dbEntity.getAttribute(ATTRIBUTE_PARAMETERS); - List ddlQueries = (List) dbEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(),1); - - Assert.assertNotNull(params); - Assert.assertEquals(params.size(), 2); - Assert.assertEquals(params.get("p1"), "v1"); - - //There should be just one entity per dbname - runCommandWithDelay("drop database " + dbName, 3000); - assertDatabaseIsNotRegistered(dbName); - - runCommandWithDelay("create database " + dbName, 3000); - dbId = assertDatabaseIsRegistered(dbName); - - //assert on qualified name - dbEntity = atlasClientV2.getEntityByGuid(dbId).getEntity(); - - Assert.assertEquals(dbEntity.getAttribute(ATTRIBUTE_QUALIFIED_NAME) , dbName.toLowerCase() + "@" + CLUSTER_NAME); - } - - @Test - public void testPathEntityDefAvailable() throws Exception { - //Check if Path entity definition created or not - AtlasEntityDef pathEntityDef = atlasClientV2.getEntityDefByName("Path"); - assertNotNull(pathEntityDef); - } - - @Test - public void testCreateDatabaseWithLocation() throws Exception { - String dbName = dbName(); - String query = "CREATE DATABASE " + dbName; - - runCommand(query); - String dbId = assertDatabaseIsRegistered(dbName); - - //HDFS Location - String hdfsLocation = "hdfs://localhost:8020/warehouse/tablespace/external/hive/reports.db"; - alterDatabaseLocation(dbName, hdfsLocation); - assertDatabaseLocationRelationship(dbId); - } - - //alter database location - public void alterDatabaseLocation(String dbName, String location) throws Exception { - int timeDelay = 5000; - String query = String.format("ALTER DATABASE %s SET LOCATION \"%s\"", dbName, location); - runCommandWithDelay(query, timeDelay); - } - - public void assertDatabaseLocationRelationship(String dbId) throws Exception { - AtlasEntity dbEntity = atlasClientV2.getEntityByGuid(dbId).getEntity(); - AtlasEntityDef pathEntityDef = getPathEntityDefWithAllSubTypes(); - - assertTrue(dbEntity.hasAttribute(ATTRIBUTE_LOCATION)); - - assertNotNull(dbEntity.getAttribute(ATTRIBUTE_LOCATION)); - - assertNotNull(dbEntity.getRelationshipAttribute(ATTRIBUTE_LOCATION_PATH)); - - AtlasObjectId locationEntityObject = toAtlasObjectId(dbEntity.getRelationshipAttribute(ATTRIBUTE_LOCATION_PATH)); - assertTrue(pathEntityDef.getSubTypes().contains(locationEntityObject.getTypeName())); - } - - public AtlasEntityDef getPathEntityDefWithAllSubTypes() throws Exception { - Set possiblePathSubTypes = new HashSet<>(Arrays.asList("fs_path", "hdfs_path", "aws_s3_pseudo_dir", "aws_s3_v2_directory", "adls_gen2_directory")); - AtlasEntityDef pathEntityDef = atlasClientV2.getEntityDefByName(PATH_TYPE_NAME); - - if(pathEntityDef == null) { - pathEntityDef = new AtlasEntityDef(PATH_TYPE_NAME); - } - - pathEntityDef.setSubTypes(possiblePathSubTypes); - - return pathEntityDef; - } - - @Test - public void testCreateTable() throws Exception { - String tableName = tableName(); - String dbName = createDatabase(); - String colName = columnName(); - - runCommand("create table " + dbName + "." + tableName + "(" + colName + " int, name string)"); - - String tableId = assertTableIsRegistered(dbName, tableName); - String colId = assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, dbName, tableName), colName)); //there is only one instance of column registered - AtlasEntity colEntity = atlasClientV2.getEntityByGuid(colId).getEntity(); - AtlasEntity tblEntity = atlasClientV2.getEntityByGuid(tableId).getEntity(); - - Assert.assertEquals(colEntity.getAttribute(ATTRIBUTE_QUALIFIED_NAME), String.format("%s.%s.%s@%s", dbName.toLowerCase(), tableName.toLowerCase(), colName.toLowerCase(), CLUSTER_NAME)); - Assert.assertNotNull(colEntity.getAttribute(ATTRIBUTE_TABLE)); - - Assert.assertNotNull(tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES)); - Assert.assertEquals(((List)tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES)).size(), 1); - - AtlasObjectId tblObjId = toAtlasObjectId(colEntity.getAttribute(ATTRIBUTE_TABLE)); - - Assert.assertEquals(tblObjId.getGuid(), tableId); - - //assert that column.owner = table.owner - AtlasEntity tblEntity1 = atlasClientV2.getEntityByGuid(tableId).getEntity(); - AtlasEntity colEntity1 = atlasClientV2.getEntityByGuid(colId).getEntity(); - - assertEquals(tblEntity1.getAttribute(ATTRIBUTE_OWNER), colEntity1.getAttribute(ATTRIBUTE_OWNER)); - - //create table where db is not registered - tableName = createTable(); - tableId = assertTableIsRegistered(DEFAULT_DB, tableName); - - AtlasEntity tblEntity2 = atlasClientV2.getEntityByGuid(tableId).getEntity(); - - Assert.assertEquals(tblEntity2.getAttribute(ATTRIBUTE_TABLE_TYPE), TableType.MANAGED_TABLE.name()); - Assert.assertEquals(tblEntity2.getAttribute(ATTRIBUTE_COMMENT), "table comment"); - - String entityName = HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName); - - Assert.assertEquals(tblEntity2.getAttribute(AtlasClient.NAME), tableName.toLowerCase()); - Assert.assertEquals(tblEntity2.getAttribute(ATTRIBUTE_QUALIFIED_NAME), entityName); - - Table t = hiveMetaStoreBridge.getHiveClient().getTable(DEFAULT_DB, tableName); - long createTime = Long.parseLong(t.getMetadata().getProperty(hive_metastoreConstants.DDL_TIME)) * MILLIS_CONVERT_FACTOR; - - verifyTimestamps(tblEntity2, ATTRIBUTE_CREATE_TIME, createTime); - verifyTimestamps(tblEntity2, ATTRIBUTE_LAST_ACCESS_TIME, createTime); - - final AtlasObjectId sdEntity = toAtlasObjectId(tblEntity2.getAttribute(ATTRIBUTE_STORAGEDESC)); - - Assert.assertNotNull(sdEntity); - - // Assert.assertEquals(((Id) sdRef.getAttribute(HiveMetaStoreBridge.TABLE))._getId(), tableId); - - //Create table where database doesn't exist, will create database instance as well - assertDatabaseIsRegistered(DEFAULT_DB); - } - - - private void verifyTimestamps(AtlasEntity ref, String property, long expectedTime) throws ParseException { - //Verify timestamps. - Object createTime = ref.getAttribute(property); - - Assert.assertNotNull(createTime); - - if (expectedTime > 0) { - Assert.assertEquals(expectedTime, createTime); - } - } - - private void verifyTimestamps(AtlasEntity ref, String property) throws ParseException { - verifyTimestamps(ref, property, 0); - } - - //ATLAS-1321: Disable problematic tests. Need to revisit and fix them later - @Test(enabled = false) - public void testCreateExternalTable() throws Exception { - String tableName = tableName(); - String colName = columnName(); - String pFile = createTestDFSPath("parentPath"); - String query = String.format("create EXTERNAL table %s.%s(%s, %s) location '%s'", DEFAULT_DB , tableName , colName + " int", "name string", pFile); - - runCommand(query); - - String tblId = assertTableIsRegistered(DEFAULT_DB, tableName, null, true); - AtlasEntity tblEnity = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlList = (List) tblEnity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - assertNotNull(ddlList); - assertEquals(ddlList.size(), 1); - - String processId = assertEntityIsRegistered(HiveDataTypes.HIVE_PROCESS.getName(), ATTRIBUTE_QUALIFIED_NAME, getTableProcessQualifiedName(DEFAULT_DB, tableName), null); - - AtlasEntity processsEntity = atlasClientV2.getEntityByGuid(processId).getEntity(); - - assertEquals(processsEntity.getAttribute("userName"), UserGroupInformation.getCurrentUser().getShortUserName()); - - verifyTimestamps(processsEntity, "startTime"); - verifyTimestamps(processsEntity, "endTime"); - - validateHDFSPaths(processsEntity, INPUTS, pFile); - } - - private Set getInputs(String inputName, Entity.Type entityType) throws HiveException { - final ReadEntity entity; - - if (Entity.Type.DFS_DIR.equals(entityType) || Entity.Type.LOCAL_DIR.equals(entityType)) { - entity = new TestReadEntity(lower(new Path(inputName).toString()), entityType); - } else { - entity = new TestReadEntity(getQualifiedTblName(inputName), entityType); - } - - if (entityType == Entity.Type.TABLE) { - entity.setT(hiveMetaStoreBridge.getHiveClient().getTable(DEFAULT_DB, inputName)); - } - - return new LinkedHashSet() {{ add(entity); }}; - } - - private Set getOutputs(String inputName, Entity.Type entityType) throws HiveException { - final WriteEntity entity; - - if (Entity.Type.DFS_DIR.equals(entityType) || Entity.Type.LOCAL_DIR.equals(entityType)) { - entity = new TestWriteEntity(lower(new Path(inputName).toString()), entityType); - } else { - entity = new TestWriteEntity(getQualifiedTblName(inputName), entityType); - } - - if (entityType == Entity.Type.TABLE) { - entity.setT(hiveMetaStoreBridge.getHiveClient().getTable(DEFAULT_DB, inputName)); - } - - return new LinkedHashSet() {{ add(entity); }}; - } - - private void validateOutputTables(AtlasEntity processEntity, Set expectedTables) throws Exception { - validateTables(toAtlasObjectIdList(processEntity.getAttribute(ATTRIBUTE_OUTPUTS)), expectedTables); - } - - private void validateInputTables(AtlasEntity processEntity, Set expectedTables) throws Exception { - validateTables(toAtlasObjectIdList(processEntity.getAttribute(ATTRIBUTE_INPUTS)), expectedTables); - } - - private void validateTables(List tableIds, Set expectedTables) throws Exception { - if (tableIds == null) { - Assert.assertTrue(CollectionUtils.isEmpty(expectedTables)); - } else if (expectedTables == null) { - Assert.assertTrue(CollectionUtils.isEmpty(tableIds)); - } else { - Assert.assertEquals(tableIds.size(), expectedTables.size()); - - List entityQualifiedNames = new ArrayList<>(tableIds.size()); - List expectedTableNames = new ArrayList<>(expectedTables.size()); - - for (AtlasObjectId tableId : tableIds) { - AtlasEntity atlasEntity = atlasClientV2.getEntityByGuid(tableId.getGuid()).getEntity(); - - entityQualifiedNames.add((String) atlasEntity.getAttribute(ATTRIBUTE_QUALIFIED_NAME)); - } - - for (Iterator iterator = expectedTables.iterator(); iterator.hasNext(); ) { - Entity hiveEntity = iterator.next(); - - expectedTableNames.add(hiveEntity.getName()); - } - - for (String entityQualifiedName : entityQualifiedNames) { - boolean found = false; - - for (String expectedTableName : expectedTableNames) { - if (entityQualifiedName.startsWith(expectedTableName)) { - found = true; - - break; - } - } - - assertTrue(found, "Table name '" + entityQualifiedName + "' does not start with any name in the expected list " + expectedTableNames); - } - } - } - - private String assertColumnIsRegistered(String colName) throws Exception { - return assertColumnIsRegistered(colName, null); - } - - private String assertColumnIsRegistered(String colName, AssertPredicate assertPredicate) throws Exception { - LOG.debug("Searching for column {}", colName); - - return assertEntityIsRegistered(HiveDataTypes.HIVE_COLUMN.getName(), ATTRIBUTE_QUALIFIED_NAME, colName, assertPredicate); - } - - private String assertSDIsRegistered(String sdQFName, AssertPredicate assertPredicate) throws Exception { - LOG.debug("Searching for sd {}", sdQFName.toLowerCase()); - - return assertEntityIsRegistered(HiveDataTypes.HIVE_STORAGEDESC.getName(), ATTRIBUTE_QUALIFIED_NAME, sdQFName.toLowerCase(), assertPredicate); - } - - private void assertColumnIsNotRegistered(String colName) throws Exception { - LOG.debug("Searching for column {}", colName); - - assertEntityIsNotRegistered(HiveDataTypes.HIVE_COLUMN.getName(), ATTRIBUTE_QUALIFIED_NAME, colName); - } - - @Test - public void testCTAS() throws Exception { - String tableName = createTable(); - String ctasTableName = "table" + random(); - String query = "create table " + ctasTableName + " as select * from " + tableName; - - runCommand(query); - - final Set readEntities = getInputs(tableName, Entity.Type.TABLE); - final Set writeEntities = getOutputs(ctasTableName, Entity.Type.TABLE); - - HiveEventContext hiveEventContext = constructEvent(query, HiveOperation.CREATETABLE_AS_SELECT, readEntities, - writeEntities); - AtlasEntity processEntity1 = validateProcess(hiveEventContext); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, hiveEventContext); - AtlasObjectId process = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process.getGuid(), processEntity1.getGuid()); - - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - assertTableIsRegistered(DEFAULT_DB, ctasTableName); - } - - private HiveEventContext constructEvent(String query, HiveOperation op, Set inputs, Set outputs) { - HiveEventContext event = new HiveEventContext(); - - event.setQueryStr(query); - event.setOperation(op); - event.setInputs(inputs); - event.setOutputs(outputs); - - return event; - } - - @Test - public void testEmptyStringAsValue() throws Exception{ - String tableName = tableName(); - String command = "create table " + tableName + "(id int, name string) row format delimited lines terminated by '\n' null defined as ''"; - - runCommandWithDelay(command, 3000); - - assertTableIsRegistered(DEFAULT_DB, tableName); - } - - @Test - public void testDropAndRecreateCTASOutput() throws Exception { - String tableName = createTable(); - String ctasTableName = "table" + random(); - String query = "create table " + ctasTableName + " as select * from " + tableName; - - runCommand(query); - - assertTableIsRegistered(DEFAULT_DB, ctasTableName); - - Set inputs = getInputs(tableName, Entity.Type.TABLE); - Set outputs = getOutputs(ctasTableName, Entity.Type.TABLE); - - HiveEventContext hiveEventContext = constructEvent(query, HiveOperation.CREATETABLE_AS_SELECT, inputs, outputs); - AtlasEntity processEntity1 = validateProcess(hiveEventContext); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, hiveEventContext); - AtlasObjectId process = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process.getGuid(), processEntity1.getGuid()); - - String dropQuery = String.format("drop table %s ", ctasTableName); - - runCommandWithDelay(dropQuery, 5000); - - assertTableIsNotRegistered(DEFAULT_DB, ctasTableName); - - runCommand(query); - - String tblId = assertTableIsRegistered(DEFAULT_DB, ctasTableName); - AtlasEntity tblEntity = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlList = (List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - assertNotNull(ddlList); - assertEquals(ddlList.size(), 1); - - outputs = getOutputs(ctasTableName, Entity.Type.TABLE); - - AtlasEntity processEntity2 = validateProcess(hiveEventContext); - AtlasEntity processExecutionEntity2 = validateProcessExecution(processEntity2, hiveEventContext); - AtlasObjectId process2 = toAtlasObjectId(processExecutionEntity2.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process2.getGuid(), processEntity2.getGuid()); - - assertNotEquals(processEntity1.getGuid(), processEntity2.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - Assert.assertEquals(numberOfProcessExecutions(processEntity2), 1); - - validateOutputTables(processEntity1, outputs); - } - - @Test - public void testCreateView() throws Exception { - String tableName = createTable(); - String viewName = tableName(); - String query = "create view " + viewName + " as select * from " + tableName; - - runCommand(query); - - HiveEventContext hiveEventContext = constructEvent(query, HiveOperation.CREATEVIEW, getInputs(tableName, - Entity.Type.TABLE), getOutputs(viewName, Entity.Type.TABLE)); - AtlasEntity processEntity1 = validateProcess(hiveEventContext); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, hiveEventContext); - AtlasObjectId process1 = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process1.getGuid(), processEntity1.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - assertTableIsRegistered(DEFAULT_DB, viewName); - - String viewId = assertTableIsRegistered(DEFAULT_DB, viewName); - AtlasEntity viewEntity = atlasClientV2.getEntityByGuid(viewId).getEntity(); - List ddlQueries = (List) viewEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 1); - } - - @Test - public void testAlterViewAsSelect() throws Exception { - //Create the view from table1 - String table1Name = createTable(); - String viewName = tableName(); - String query = "create view " + viewName + " as select * from " + table1Name; - - runCommand(query); - - String table1Id = assertTableIsRegistered(DEFAULT_DB, table1Name); - - HiveEventContext hiveEventContext = constructEvent(query, HiveOperation.CREATEVIEW, getInputs(table1Name, - Entity.Type.TABLE), getOutputs(viewName, Entity.Type.TABLE)); - String processId1 = assertProcessIsRegistered(hiveEventContext); - AtlasEntity processEntity1 = atlasClientV2.getEntityByGuid(processId1).getEntity(); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, hiveEventContext); - AtlasObjectId process1 = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process1.getGuid(), processEntity1.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - - String viewId = assertTableIsRegistered(DEFAULT_DB, viewName); - - //Check lineage which includes table1 - String datasetName = HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, viewName); - String tableId = assertTableIsRegistered(DEFAULT_DB, viewName); - AtlasLineageInfo inputLineageInfo = atlasClientV2.getLineageInfo(tableId, AtlasLineageInfo.LineageDirection.INPUT, 0); - Map entityMap = inputLineageInfo.getGuidEntityMap(); - - assertTrue(entityMap.containsKey(viewId)); - assertTrue(entityMap.containsKey(table1Id)); - - //Alter the view from table2 - String table2Name = createTable(); - - query = "alter view " + viewName + " as select * from " + table2Name; - - runCommand(query); - - HiveEventContext hiveEventContext2 = constructEvent(query, HiveOperation.CREATEVIEW, getInputs(table2Name, - Entity.Type.TABLE), getOutputs(viewName, Entity.Type.TABLE)); - String processId2 = assertProcessIsRegistered(hiveEventContext2); - AtlasEntity processEntity2 = atlasClientV2.getEntityByGuid(processId2).getEntity(); - AtlasEntity processExecutionEntity2 = validateProcessExecution(processEntity2, hiveEventContext2); - AtlasObjectId process2 = toAtlasObjectId(processExecutionEntity2.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process2.getGuid(), processEntity2.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity2), 2); - Assert.assertEquals(processEntity1.getGuid(), processEntity2.getGuid()); - - String table2Id = assertTableIsRegistered(DEFAULT_DB, table2Name); - String viewId2 = assertTableIsRegistered(DEFAULT_DB, viewName); - - Assert.assertEquals(viewId2, viewId); - - AtlasEntity viewEntity = atlasClientV2.getEntityByGuid(viewId2).getEntity(); - List ddlQueries = (List) viewEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 2); - - datasetName = HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, viewName); - - String tableId1 = assertTableIsRegistered(DEFAULT_DB, viewName); - AtlasLineageInfo inputLineageInfo1 = atlasClientV2.getLineageInfo(tableId1, AtlasLineageInfo.LineageDirection.INPUT, 0); - Map entityMap1 = inputLineageInfo1.getGuidEntityMap(); - - assertTrue(entityMap1.containsKey(viewId)); - - //This is through the alter view process - assertTrue(entityMap1.containsKey(table2Id)); - - //This is through the Create view process - assertTrue(entityMap1.containsKey(table1Id)); - - //Outputs dont exist - AtlasLineageInfo outputLineageInfo = atlasClientV2.getLineageInfo(tableId1, AtlasLineageInfo.LineageDirection.OUTPUT, 0); - Map entityMap2 = outputLineageInfo.getGuidEntityMap(); - - assertEquals(entityMap2.size(),0); - } - - private String createTestDFSFile(String path) throws Exception { - return "pfile://" + file(path); - } - - @Test - public void testLoadLocalPath() throws Exception { - String tableName = createTable(false); - String loadFile = file("load"); - String query = "load data local inpath 'file://" + loadFile + "' into table " + tableName; - - String tblId = assertTableIsRegistered(DEFAULT_DB, tableName); - - runCommand(query); - - AtlasEntity tblEntity = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries = (List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 1); - - assertProcessIsRegistered(constructEvent(query, HiveOperation.LOAD, getInputs("file://" + loadFile, Entity.Type.LOCAL_DIR), getOutputs(tableName, Entity.Type.TABLE))); - } - - @Test - public void testLoadLocalPathIntoPartition() throws Exception { - String tableName = createTable(true); - String loadFile = file("load"); - String query = "load data local inpath 'file://" + loadFile + "' into table " + tableName + " partition(dt = '"+ PART_FILE + "')"; - - String tblId = assertTableIsRegistered(DEFAULT_DB, tableName); - - runCommand(query); - - AtlasEntity tblEntity = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries = (List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 1); - - assertProcessIsRegistered(constructEvent(query, HiveOperation.LOAD, null, getOutputs(tableName, Entity.Type.TABLE))); - } - - @Test - public void testLoadDFSPathPartitioned() throws Exception { - String tableName = createTable(true, true, false); - - assertTableIsRegistered(DEFAULT_DB, tableName); - - String loadFile = createTestDFSFile("loadDFSFile"); - String query = "load data inpath '" + loadFile + "' into table " + tableName + " partition(dt = '"+ PART_FILE + "')"; - - runCommand(query); - - Set outputs = getOutputs(tableName, Entity.Type.TABLE); - Set inputs = getInputs(loadFile, Entity.Type.DFS_DIR); - Set partitionOps = new LinkedHashSet<>(outputs); - - partitionOps.addAll(getOutputs(DEFAULT_DB + "@" + tableName + "@dt=" + PART_FILE, Entity.Type.PARTITION)); - - AtlasEntity processReference = validateProcess(constructEvent(query, HiveOperation.LOAD, inputs, partitionOps), inputs, outputs); - - validateHDFSPaths(processReference, INPUTS, loadFile); - validateOutputTables(processReference, outputs); - - String loadFile2 = createTestDFSFile("loadDFSFile1"); - - query = "load data inpath '" + loadFile2 + "' into table " + tableName + " partition(dt = '"+ PART_FILE + "')"; - - runCommand(query); - - Set process2Inputs = getInputs(loadFile2, Entity.Type.DFS_DIR); - Set expectedInputs = new LinkedHashSet<>(); - - expectedInputs.addAll(process2Inputs); - expectedInputs.addAll(inputs); - - validateProcess(constructEvent(query, HiveOperation.LOAD, expectedInputs, partitionOps), expectedInputs, outputs); - } - - private String getQualifiedTblName(String inputTable) { - String inputtblQlfdName = inputTable; - - if (inputTable != null && !inputTable.contains("@")) { - inputtblQlfdName = HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, inputTable); - } - return inputtblQlfdName; - } - - private AtlasEntity validateProcess(HiveEventContext event, Set inputTables, Set outputTables) throws Exception { - String processId = assertProcessIsRegistered(event, inputTables, outputTables); - AtlasEntity processEntity = atlasClientV2.getEntityByGuid(processId).getEntity(); - - validateInputTables(processEntity, inputTables); - validateOutputTables(processEntity, outputTables); - - return processEntity; - } - - private AtlasEntity validateProcess(HiveEventContext event) throws Exception { - return validateProcess(event, event.getInputs(), event.getOutputs()); - } - - private AtlasEntity validateProcessExecution(AtlasEntity hiveProcess, HiveEventContext event) throws Exception { - String processExecutionId = assertProcessExecutionIsRegistered(hiveProcess, event); - AtlasEntity processExecutionEntity = atlasClientV2.getEntityByGuid(processExecutionId).getEntity(); - return processExecutionEntity; - } - - @Test - public void testInsertIntoTable() throws Exception { - String inputTable1Name = createTable(); - String inputTable2Name = createTable(); - String insertTableName = createTable(); - - assertTableIsRegistered(DEFAULT_DB, inputTable1Name); - assertTableIsRegistered(DEFAULT_DB, insertTableName); - - String query = "insert into " + insertTableName + " select t1.id, t1.name from " + inputTable2Name + " as t2, " + inputTable1Name + " as t1 where t1.id=t2.id"; - - runCommand(query); - - Set inputs = getInputs(inputTable1Name, Entity.Type.TABLE); - - inputs.addAll(getInputs(inputTable2Name, Entity.Type.TABLE)); - - Set outputs = getOutputs(insertTableName, Entity.Type.TABLE); - - (outputs.iterator().next()).setWriteType(WriteEntity.WriteType.INSERT); - - HiveEventContext event = constructEvent(query, HiveOperation.QUERY, inputs, outputs); - - Set expectedInputs = new TreeSet(entityComparator) {{ - addAll(inputs); - }}; - - String tblId = assertTableIsRegistered(DEFAULT_DB, insertTableName); - AtlasEntity tblEntity = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries = (List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 1); - - AtlasEntity processEntity1 = validateProcess(event, expectedInputs, outputs); - - //Test sorting of tbl names - SortedSet sortedTblNames = new TreeSet<>(); - - sortedTblNames.add(inputTable1Name.toLowerCase()); - sortedTblNames.add(inputTable2Name.toLowerCase()); - - //Verify sorted order of inputs in qualified name - Assert.assertEquals(processEntity1.getAttribute(ATTRIBUTE_QUALIFIED_NAME), - Joiner.on(SEP).join("QUERY", - getQualifiedTblName(sortedTblNames.first()), - HiveMetaStoreBridge.getTableCreatedTime(hiveMetaStoreBridge.getHiveClient().getTable(DEFAULT_DB, sortedTblNames.first())), - getQualifiedTblName(sortedTblNames.last()), - HiveMetaStoreBridge.getTableCreatedTime(hiveMetaStoreBridge.getHiveClient().getTable(DEFAULT_DB, sortedTblNames.last()))) - + IO_SEP + SEP - + Joiner.on(SEP). - join(WriteEntity.WriteType.INSERT.name(), - getQualifiedTblName(insertTableName), - HiveMetaStoreBridge.getTableCreatedTime(hiveMetaStoreBridge.getHiveClient().getTable(DEFAULT_DB, insertTableName))) - ); - - //Rerun same query. Should result in same process - runCommandWithDelay(query, 3000); - - AtlasEntity processEntity2 = validateProcess(event, expectedInputs, outputs); - Assert.assertEquals(numberOfProcessExecutions(processEntity2), 2); - Assert.assertEquals(processEntity1.getGuid(), processEntity2.getGuid()); - } - - @Test - public void testInsertIntoTableProcessExecution() throws Exception { - String inputTable1Name = createTable(); - String inputTable2Name = createTable(); - String insertTableName = createTable(); - - assertTableIsRegistered(DEFAULT_DB, inputTable1Name); - assertTableIsRegistered(DEFAULT_DB, insertTableName); - - String query = "insert into " + insertTableName + " select t1.id, t1.name from " + inputTable2Name + " as t2, " + inputTable1Name + " as t1 where t1.id=t2.id"; - - runCommand(query); - - Set inputs = getInputs(inputTable1Name, Entity.Type.TABLE); - - inputs.addAll(getInputs(inputTable2Name, Entity.Type.TABLE)); - - Set outputs = getOutputs(insertTableName, Entity.Type.TABLE); - - (outputs.iterator().next()).setWriteType(WriteEntity.WriteType.INSERT); - - HiveEventContext event = constructEvent(query, HiveOperation.QUERY, inputs, outputs); - - Set expectedInputs = new TreeSet(entityComparator) {{ - addAll(inputs); - }}; - - assertTableIsRegistered(DEFAULT_DB, insertTableName); - - AtlasEntity processEntity1 = validateProcess(event, expectedInputs, outputs); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, event); - AtlasObjectId process = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process.getGuid(), processEntity1.getGuid()); - - //Test sorting of tbl names - SortedSet sortedTblNames = new TreeSet<>(); - - sortedTblNames.add(inputTable1Name.toLowerCase()); - sortedTblNames.add(inputTable2Name.toLowerCase()); - - //Verify sorted order of inputs in qualified name - Assert.assertEquals(processEntity1.getAttribute(ATTRIBUTE_QUALIFIED_NAME), - Joiner.on(SEP).join("QUERY", - getQualifiedTblName(sortedTblNames.first()), - HiveMetaStoreBridge.getTableCreatedTime(hiveMetaStoreBridge.getHiveClient().getTable(DEFAULT_DB, sortedTblNames.first())), - getQualifiedTblName(sortedTblNames.last()), - HiveMetaStoreBridge.getTableCreatedTime(hiveMetaStoreBridge.getHiveClient().getTable(DEFAULT_DB, sortedTblNames.last()))) - + IO_SEP + SEP - + Joiner.on(SEP). - join(WriteEntity.WriteType.INSERT.name(), - getQualifiedTblName(insertTableName), - HiveMetaStoreBridge.getTableCreatedTime(hiveMetaStoreBridge.getHiveClient().getTable(DEFAULT_DB, insertTableName))) - ); - - //Rerun same query. Should result in same process - runCommandWithDelay(query, 3000); - - AtlasEntity processEntity2 = validateProcess(event, expectedInputs, outputs); - AtlasEntity processExecutionEntity2 = validateProcessExecution(processEntity2, event); - process = toAtlasObjectId(processExecutionEntity2.getRelationshipAttribute(BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process.getGuid(), processEntity2.getGuid()); - Assert.assertEquals(processEntity1.getGuid(), processEntity2.getGuid()); - - String queryWithDifferentPredicate = "insert into " + insertTableName + " select t1.id, t1.name from " + - inputTable2Name + " as t2, " + inputTable1Name + " as t1 where t1.id=100"; - runCommandWithDelay(queryWithDifferentPredicate, 1000); - - HiveEventContext event3 = constructEvent(queryWithDifferentPredicate, HiveOperation.QUERY, inputs, outputs); - AtlasEntity processEntity3 = validateProcess(event3, expectedInputs, outputs); - AtlasEntity processExecutionEntity3 = validateProcessExecution(processEntity3, event3); - process = toAtlasObjectId(processExecutionEntity3.getRelationshipAttribute(BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process.getGuid(), processEntity3.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity3), 3); - Assert.assertEquals(processEntity2.getGuid(), processEntity3.getGuid()); - } - - @Test - public void testInsertIntoLocalDir() throws Exception { - String tableName = createTable(); - String randomLocalPath = mkdir("hiverandom.tmp"); - String query = "insert overwrite LOCAL DIRECTORY '" + randomLocalPath + "' select id, name from " + tableName; - - runCommand(query); - - HiveEventContext event = constructEvent(query, HiveOperation.QUERY, - getInputs(tableName, Entity.Type.TABLE), getOutputs(randomLocalPath, Entity.Type.LOCAL_DIR)); - AtlasEntity hiveProcess = validateProcess(event); - AtlasEntity hiveProcessExecution = validateProcessExecution(hiveProcess, event); - AtlasObjectId process = toAtlasObjectId(hiveProcessExecution.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process.getGuid(), hiveProcess.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(hiveProcess), 1); - - String tblId = assertTableIsRegistered(DEFAULT_DB, tableName); - - AtlasEntity tblEntity = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries = (List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 1); - } - - @Test - public void testUpdateProcess() throws Exception { - String tableName = createTable(); - String pFile1 = createTestDFSPath("somedfspath1"); - String query = "insert overwrite DIRECTORY '" + pFile1 + "' select id, name from " + tableName; - - runCommand(query); - - Set inputs = getInputs(tableName, Entity.Type.TABLE); - Set outputs = getOutputs(pFile1, Entity.Type.DFS_DIR); - - outputs.iterator().next().setWriteType(WriteEntity.WriteType.PATH_WRITE); - - HiveEventContext hiveEventContext = constructEvent(query, HiveOperation.QUERY, inputs, outputs); - AtlasEntity processEntity = validateProcess(hiveEventContext); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity, hiveEventContext); - AtlasObjectId process = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process.getGuid(), processEntity.getGuid()); - - validateHDFSPaths(processEntity, OUTPUTS, pFile1); - - assertTableIsRegistered(DEFAULT_DB, tableName); - - validateInputTables(processEntity, inputs); - - //Rerun same query with same HDFS path - runCommandWithDelay(query, 3000); - - assertTableIsRegistered(DEFAULT_DB, tableName); - - AtlasEntity process2Entity = validateProcess(hiveEventContext); - AtlasEntity processExecutionEntity2 = validateProcessExecution(processEntity, hiveEventContext); - AtlasObjectId process2 = toAtlasObjectId(processExecutionEntity2.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process2.getGuid(), process2Entity.getGuid()); - - - validateHDFSPaths(process2Entity, OUTPUTS, pFile1); - - Assert.assertEquals(process2Entity.getGuid(), processEntity.getGuid()); - - //Rerun same query with a new HDFS path. Will result in same process since HDFS paths is not part of qualified name for QUERY operations - String pFile2 = createTestDFSPath("somedfspath2"); - - query = "insert overwrite DIRECTORY '" + pFile2 + "' select id, name from " + tableName; - - runCommandWithDelay(query, 3000); - - String tblId = assertTableIsRegistered(DEFAULT_DB, tableName); - - AtlasEntity tblEntity = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries = (List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 1); - - Set p3Outputs = new LinkedHashSet() {{ - addAll(getOutputs(pFile2, Entity.Type.DFS_DIR)); - addAll(outputs); - }}; - - AtlasEntity process3Entity = validateProcess(constructEvent(query, HiveOperation.QUERY, inputs, p3Outputs)); - AtlasEntity processExecutionEntity3 = validateProcessExecution(processEntity, hiveEventContext); - AtlasObjectId process3 = toAtlasObjectId(processExecutionEntity3.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process3.getGuid(), process3Entity.getGuid()); - validateHDFSPaths(process3Entity, OUTPUTS, pFile2); - - Assert.assertEquals(numberOfProcessExecutions(process3Entity), 3); - Assert.assertEquals(process3Entity.getGuid(), processEntity.getGuid()); - } - - @Test - public void testInsertIntoDFSDirPartitioned() throws Exception { - //Test with partitioned table - String tableName = createTable(true); - String pFile1 = createTestDFSPath("somedfspath1"); - String query = "insert overwrite DIRECTORY '" + pFile1 + "' select id, name from " + tableName + " where dt = '" + PART_FILE + "'"; - - runCommand(query); - - Set inputs = getInputs(tableName, Entity.Type.TABLE); - Set outputs = getOutputs(pFile1, Entity.Type.DFS_DIR); - - outputs.iterator().next().setWriteType(WriteEntity.WriteType.PATH_WRITE); - - Set partitionIps = new LinkedHashSet<>(inputs); - - partitionIps.addAll(getInputs(DEFAULT_DB + "@" + tableName + "@dt='" + PART_FILE + "'", Entity.Type.PARTITION)); - - AtlasEntity processEntity = validateProcess(constructEvent(query, HiveOperation.QUERY, partitionIps, outputs), inputs, outputs); - - //Rerun same query with different HDFS path. Should not create another process and should update it. - - String pFile2 = createTestDFSPath("somedfspath2"); - query = "insert overwrite DIRECTORY '" + pFile2 + "' select id, name from " + tableName + " where dt = '" + PART_FILE + "'"; - - runCommand(query); - - Set pFile2Outputs = getOutputs(pFile2, Entity.Type.DFS_DIR); - - pFile2Outputs.iterator().next().setWriteType(WriteEntity.WriteType.PATH_WRITE); - - //Now the process has 2 paths - one older with deleted reference to partition and another with the the latest partition - Set p2Outputs = new LinkedHashSet() {{ - addAll(pFile2Outputs); - addAll(outputs); - }}; - - AtlasEntity process2Entity = validateProcess(constructEvent(query, HiveOperation.QUERY, partitionIps, pFile2Outputs), inputs, p2Outputs); - - validateHDFSPaths(process2Entity, OUTPUTS, pFile2); - - Assert.assertEquals(process2Entity.getGuid(), processEntity.getGuid()); - } - - //Disabling test as temporary table is not captured by hiveHook(https://issues.apache.org/jira/browse/ATLAS-1274) - @Test(enabled = false) - public void testInsertIntoTempTable() throws Exception { - String tableName = createTable(); - String insertTableName = createTable(false, false, true); - - assertTableIsRegistered(DEFAULT_DB, tableName); - assertTableIsNotRegistered(DEFAULT_DB, insertTableName, true); - - String query = "insert into " + insertTableName + " select id, name from " + tableName; - - runCommand(query); - - Set inputs = getInputs(tableName, Entity.Type.TABLE); - Set outputs = getOutputs(insertTableName, Entity.Type.TABLE); - - outputs.iterator().next().setWriteType(WriteEntity.WriteType.INSERT); - - HiveEventContext event = constructEvent(query, HiveOperation.QUERY, inputs, outputs); - AtlasEntity hiveProcess = validateProcess(event); - AtlasEntity hiveProcessExecution = validateProcessExecution(hiveProcess, event); - AtlasObjectId process = toAtlasObjectId(hiveProcessExecution.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process.getGuid(), hiveProcess.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(hiveProcess), 1); - - assertTableIsRegistered(DEFAULT_DB, tableName); - assertTableIsRegistered(DEFAULT_DB, insertTableName, null, true); - } - - @Test - public void testInsertIntoPartition() throws Exception { - boolean isPartitionedTable = true; - String tableName = createTable(isPartitionedTable); - String insertTableName = createTable(isPartitionedTable); - String query = "insert into " + insertTableName + " partition(dt = '"+ PART_FILE + "') select id, name from " + tableName + " where dt = '"+ PART_FILE + "'"; - - runCommand(query); - - Set inputs = getInputs(tableName, Entity.Type.TABLE); - Set outputs = getOutputs(insertTableName, Entity.Type.TABLE); - - outputs.iterator().next().setWriteType(WriteEntity.WriteType.INSERT); - - Set partitionIps = new LinkedHashSet() { - { - addAll(inputs); - add(getPartitionInput()); - } - }; - - Set partitionOps = new LinkedHashSet() { - { - addAll(outputs); - add(getPartitionOutput()); - } - }; - - HiveEventContext event = constructEvent(query, HiveOperation.QUERY, partitionIps, partitionOps); - AtlasEntity hiveProcess = validateProcess(event, inputs, outputs); - AtlasEntity hiveProcessExecution = validateProcessExecution(hiveProcess, event); - AtlasObjectId process = toAtlasObjectId(hiveProcessExecution.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process.getGuid(), hiveProcess.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(hiveProcess), 1); - assertTableIsRegistered(DEFAULT_DB, tableName); - - String tblId = assertTableIsRegistered(DEFAULT_DB, insertTableName); - AtlasEntity tblEntity = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries = (List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 1); - - //TODO -Add update test case - } - - @Test - public void testExportImportUnPartitionedTable() throws Exception { - String tableName = createTable(false); - - String tblId = assertTableIsRegistered(DEFAULT_DB, tableName); - - String filename = "file://" + mkdir("exportUnPartitioned"); - String query = "export table " + tableName + " to \"" + filename + "\""; - - runCommand(query); - - AtlasEntity tblEntity = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries = (List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 1); - - Set inputs = getInputs(tableName, Entity.Type.TABLE); - Set outputs = getOutputs(filename, Entity.Type.DFS_DIR); - - HiveEventContext event = constructEvent(query, HiveOperation.EXPORT, inputs, outputs); - AtlasEntity processEntity = validateProcess(event); - AtlasEntity hiveProcessExecution = validateProcessExecution(processEntity, event); - AtlasObjectId process = toAtlasObjectId(hiveProcessExecution.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process.getGuid(), processEntity.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity), 1); - validateHDFSPaths(processEntity, OUTPUTS, filename); - validateInputTables(processEntity, inputs); - - //Import - String importTableName = createTable(false); - - String importTblId = assertTableIsRegistered(DEFAULT_DB, importTableName); - - query = "import table " + importTableName + " from '" + filename + "'"; - - runCommand(query); - - AtlasEntity importTblEntity = atlasClientV2.getEntityByGuid(importTblId).getEntity(); - List importTblddlQueries = (List) importTblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(importTblddlQueries); - Assert.assertEquals(importTblddlQueries.size(), 1); - - outputs = getOutputs(importTableName, Entity.Type.TABLE); - - HiveEventContext event2 = constructEvent(query, HiveOperation.IMPORT, - getInputs(filename, Entity.Type.DFS_DIR), outputs); - AtlasEntity processEntity2 = validateProcess(event2); - AtlasEntity hiveProcessExecution2 = validateProcessExecution(processEntity2, event2); - AtlasObjectId process2 = toAtlasObjectId(hiveProcessExecution2.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process2.getGuid(), processEntity2.getGuid()); - - Assert.assertEquals(numberOfProcessExecutions(processEntity2), 1); - Assert.assertNotEquals(processEntity.getGuid(), processEntity2.getGuid()); - - //Should create another process - filename = "file://" + mkdir("export2UnPartitioned"); - query = "export table " + tableName + " to \"" + filename + "\""; - - runCommand(query); - - AtlasEntity tblEntity2 = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries2 = (List) tblEntity2.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries2); - Assert.assertEquals(ddlQueries2.size(), 1); - - inputs = getInputs(tableName, Entity.Type.TABLE); - outputs = getOutputs(filename, Entity.Type.DFS_DIR); - - HiveEventContext event3 = constructEvent(query, HiveOperation.EXPORT, inputs, outputs); - AtlasEntity processEntity3 = validateProcess(event3); - AtlasEntity hiveProcessExecution3 = validateProcessExecution(processEntity3, event3); - AtlasObjectId process3 = toAtlasObjectId(hiveProcessExecution3.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process3.getGuid(), processEntity3.getGuid()); - - Assert.assertEquals(numberOfProcessExecutions(processEntity3), 1); - - // Should be a different process compared to the previous ones - Assert.assertNotEquals(processEntity.getGuid(), processEntity3.getGuid()); - Assert.assertNotEquals(processEntity2.getGuid(), processEntity3.getGuid()); - - //import again shouyld create another process - query = "import table " + importTableName + " from '" + filename + "'"; - - runCommand(query); - - AtlasEntity tblEntity3 = atlasClientV2.getEntityByGuid(importTblId).getEntity(); - List ddlQueries3 = (List) tblEntity3.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries3); - Assert.assertEquals(ddlQueries3.size(), 1); - - outputs = getOutputs(importTableName, Entity.Type.TABLE); - - HiveEventContext event4 = constructEvent(query, HiveOperation.IMPORT, getInputs(filename, - Entity.Type.DFS_DIR), outputs); - AtlasEntity processEntity4 = validateProcess(event4); - AtlasEntity hiveProcessExecution4 = validateProcessExecution(processEntity4, event4); - AtlasObjectId process4 = toAtlasObjectId(hiveProcessExecution4.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process4.getGuid(), processEntity4.getGuid()); - - Assert.assertEquals(numberOfProcessExecutions(processEntity4), 1); - - // Should be a different process compared to the previous ones - Assert.assertNotEquals(processEntity.getGuid(), processEntity4.getGuid()); - Assert.assertNotEquals(processEntity2.getGuid(), processEntity4.getGuid()); - Assert.assertNotEquals(processEntity3.getGuid(), processEntity4.getGuid()); - } - - @Test - public void testExportImportPartitionedTable() throws Exception { - boolean isPartitionedTable = true; - String tableName = createTable(isPartitionedTable); - - String tblId = assertTableIsRegistered(DEFAULT_DB, tableName); - - //Add a partition - String partFile = "file://" + mkdir("partition"); - String query = "alter table " + tableName + " add partition (dt='"+ PART_FILE + "') location '" + partFile + "'"; - - runCommand(query); - - AtlasEntity tblEntity = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries = (List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 1); - - String filename = "pfile://" + mkdir("export"); - - query = "export table " + tableName + " to \"" + filename + "\""; - - runCommand(query); - - AtlasEntity tblEntity2 = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries2 = (List) tblEntity2.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries2); - Assert.assertEquals(ddlQueries2.size(), 1); - - Set expectedExportInputs = getInputs(tableName, Entity.Type.TABLE); - Set outputs = getOutputs(filename, Entity.Type.DFS_DIR); - Set partitionIps = getInputs(DEFAULT_DB + "@" + tableName + "@dt=" + PART_FILE, Entity.Type.PARTITION); //Note that export has only partition as input in this case - - partitionIps.addAll(expectedExportInputs); - - HiveEventContext event1 = constructEvent(query, HiveOperation.EXPORT, partitionIps, outputs); - AtlasEntity processEntity1 = validateProcess(event1, expectedExportInputs, outputs); - AtlasEntity hiveProcessExecution1 = validateProcessExecution(processEntity1, event1); - AtlasObjectId process1 = toAtlasObjectId(hiveProcessExecution1.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process1.getGuid(), processEntity1.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - - validateHDFSPaths(processEntity1, OUTPUTS, filename); - - //Import - String importTableName = createTable(true); - - String tblId2 = assertTableIsRegistered(DEFAULT_DB, tableName); - - query = "import table " + importTableName + " from '" + filename + "'"; - - runCommand(query); - - AtlasEntity tblEntity3 = atlasClientV2.getEntityByGuid(tblId2).getEntity(); - List ddlQueries3 = (List) tblEntity3.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries3); - Assert.assertEquals(ddlQueries3.size(), 1); - - Set expectedImportInputs = getInputs(filename, Entity.Type.DFS_DIR); - Set importOutputs = getOutputs(importTableName, Entity.Type.TABLE); - Set partitionOps = getOutputs(DEFAULT_DB + "@" + importTableName + "@dt=" + PART_FILE, Entity.Type.PARTITION); - - partitionOps.addAll(importOutputs); - - HiveEventContext event2 = constructEvent(query, HiveOperation.IMPORT, expectedImportInputs , partitionOps); - AtlasEntity processEntity2 = validateProcess(event2, expectedImportInputs, importOutputs); - AtlasEntity hiveProcessExecution2 = validateProcessExecution(processEntity2, event2); - AtlasObjectId process2 = toAtlasObjectId(hiveProcessExecution2.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process2.getGuid(), processEntity2.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity2), 1); - Assert.assertNotEquals(processEntity1.getGuid(), processEntity2.getGuid()); - - //Export should update same process - filename = "pfile://" + mkdir("export2"); - query = "export table " + tableName + " to \"" + filename + "\""; - - runCommand(query); - - Set outputs2 = getOutputs(filename, Entity.Type.DFS_DIR); - Set p3Outputs = new LinkedHashSet() {{ - addAll(outputs2); - addAll(outputs); - }}; - - HiveEventContext event3 = constructEvent(query, HiveOperation.EXPORT, partitionIps, outputs2); - - // this process entity should return same as the processEntity1 since the inputs and outputs are the same, - // hence the qualifiedName will be the same - AtlasEntity processEntity3 = validateProcess(event3, expectedExportInputs, p3Outputs); - AtlasEntity hiveProcessExecution3 = validateProcessExecution(processEntity3, event3); - AtlasObjectId process3 = toAtlasObjectId(hiveProcessExecution3.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process3.getGuid(), processEntity3.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity3), 2); - Assert.assertEquals(processEntity1.getGuid(), processEntity3.getGuid()); - - query = "alter table " + importTableName + " drop partition (dt='"+ PART_FILE + "')"; - - runCommand(query); - - //Import should update same process - query = "import table " + importTableName + " from '" + filename + "'"; - - runCommandWithDelay(query, 3000); - - Set importInputs = getInputs(filename, Entity.Type.DFS_DIR); - Set expectedImport2Inputs = new LinkedHashSet() {{ - addAll(importInputs); - addAll(expectedImportInputs); - }}; - - HiveEventContext event4 = constructEvent(query, HiveOperation.IMPORT, importInputs, partitionOps); - - // This process is going to be same as processEntity2 - AtlasEntity processEntity4 = validateProcess(event4, expectedImport2Inputs, importOutputs); - AtlasEntity hiveProcessExecution4 = validateProcessExecution(processEntity4, event4); - AtlasObjectId process4 = toAtlasObjectId(hiveProcessExecution4.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process4.getGuid(), processEntity4.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity4), 2); - Assert.assertEquals(processEntity2.getGuid(), processEntity4.getGuid()); - Assert.assertNotEquals(processEntity1.getGuid(), processEntity4.getGuid()); - } - - @Test - public void testIgnoreSelect() throws Exception { - String tableName = createTable(); - String query = "select * from " + tableName; - - runCommand(query); - - Set inputs = getInputs(tableName, Entity.Type.TABLE); - HiveEventContext hiveEventContext = constructEvent(query, HiveOperation.QUERY, inputs, null); - - assertProcessIsNotRegistered(hiveEventContext); - - //check with uppercase table name - query = "SELECT * from " + tableName.toUpperCase(); - - runCommand(query); - - assertProcessIsNotRegistered(hiveEventContext); - } - - @Test - public void testAlterTableRenameAliasRegistered() throws Exception{ - String tableName = createTable(false); - String tableGuid = assertTableIsRegistered(DEFAULT_DB, tableName); - String newTableName = tableName(); - String query = String.format("alter table %s rename to %s", tableName, newTableName); - - runCommand(query); - - String newTableGuid = assertTableIsRegistered(DEFAULT_DB, newTableName); - - assertEquals(tableGuid, newTableGuid); - - AtlasEntity atlasEntity = atlasClientV2.getEntityByGuid(newTableGuid).getEntity(); - Map valueMap = atlasEntity.getAttributes(); - Iterable aliasList = (Iterable) valueMap.get("aliases"); - String aliasTableName = aliasList.iterator().next(); - - assert tableName.toLowerCase().equals(aliasTableName); - } - - @Test - public void testAlterTableRename() throws Exception { - String tableName = createTable(true); - String newDBName = createDatabase(); - String tableId = assertTableIsRegistered(DEFAULT_DB, tableName); - AtlasEntity tableEntity = atlasClientV2.getEntityByGuid(tableId).getEntity(); - String createTime = String.valueOf(tableEntity.getAttribute(ATTRIBUTE_CREATE_TIME)); - - Assert.assertNotNull(createTime); - - String columnGuid = assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), NAME)); - String sdGuid = assertSDIsRegistered(HiveMetaStoreBridge.getStorageDescQFName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName)), null); - - assertDatabaseIsRegistered(newDBName); - - String colTraitDetails = createTrait(columnGuid); //Add trait to column - String sdTraitDetails = createTrait(sdGuid); //Add trait to sd - String partColumnGuid = assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), "dt")); - String partColTraitDetails = createTrait(partColumnGuid); //Add trait to part col keys - String newTableName = tableName(); - String query = String.format("alter table %s rename to %s", DEFAULT_DB + "." + tableName, newDBName + "." + newTableName); - - runCommandWithDelay(query, 3000); - - String newColGuid = assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, newDBName, newTableName), NAME)); - - Assert.assertEquals(newColGuid, columnGuid); - - assertColumnIsNotRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, newDBName, tableName), NAME)); - - assertTrait(columnGuid, colTraitDetails); - - String newSdGuid = assertSDIsRegistered(HiveMetaStoreBridge.getStorageDescQFName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, newDBName, newTableName)), null); - - Assert.assertEquals(newSdGuid, sdGuid); - assertTrait(sdGuid, sdTraitDetails); - assertTrait(partColumnGuid, partColTraitDetails); - assertTableIsNotRegistered(DEFAULT_DB, tableName); - - String renamedTableId = assertTableIsRegistered(newDBName, newTableName, new AssertPredicate() { - @Override - public void assertOnEntity(final AtlasEntity entity) throws Exception { - AtlasObjectId sd = toAtlasObjectId(entity.getAttribute(ATTRIBUTE_STORAGEDESC)); - - assertNotNull(sd); - } - }); - - AtlasEntity renamedTableEntity = atlasClientV2.getEntityByGuid(renamedTableId).getEntity(); - List ddlQueries = (List) renamedTableEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 2); - - } - - private List getColumns(String dbName, String tableName) throws Exception { - String tableId = assertTableIsRegistered(dbName, tableName); - AtlasEntityWithExtInfo tblEntityWithExtInfo = atlasClientV2.getEntityByGuid(tableId); - AtlasEntity tableEntity = tblEntityWithExtInfo.getEntity(); - - //with soft delete, the deleted columns are returned as well. So, filter the deleted ones - List columns = toAtlasObjectIdList(tableEntity.getAttribute(ATTRIBUTE_COLUMNS)); - List activeColumns = new ArrayList<>(); - - for (AtlasObjectId col : columns) { - AtlasEntity columnEntity = tblEntityWithExtInfo.getEntity(col.getGuid()); - - if (columnEntity.getStatus() == AtlasEntity.Status.ACTIVE) { - activeColumns.add(columnEntity); - } - } - - return activeColumns; - } - - private String createTrait(String guid) throws AtlasServiceException { - //add trait - //valid type names in v2 must consist of a letter followed by a sequence of letter, number, or _ characters - String traitName = "PII_Trait" + random(); - AtlasClassificationDef piiTrait = AtlasTypeUtil.createTraitTypeDef(traitName, Collections.emptySet()); - - atlasClientV2.createAtlasTypeDefs(new AtlasTypesDef(Collections.emptyList(), Collections.emptyList(), Collections.singletonList(piiTrait), Collections.emptyList())); - atlasClientV2.addClassifications(guid, Collections.singletonList(new AtlasClassification(piiTrait.getName()))); - - return traitName; - } - - private void assertTrait(String guid, String traitName) throws AtlasServiceException { - AtlasClassification.AtlasClassifications classifications = atlasClientV2.getClassifications(guid); - - Assert.assertEquals(classifications.getList().get(0).getTypeName(), traitName); - } - - @Test - public void testAlterTableAddColumn() throws Exception { - String tableName = createTable(); - String column = columnName(); - String query = "alter table " + tableName + " add columns (" + column + " string)"; - - runCommand(query); - - assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), column)); - - //Verify the number of columns present in the table - List columns = getColumns(DEFAULT_DB, tableName); - - Assert.assertEquals(columns.size(), 3); - - String tblId = assertTableIsRegistered(DEFAULT_DB, tableName); - AtlasEntity tblEntity = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries = (List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 2); - - } - - //ATLAS-1321: Disable problematic tests. Need to revisit and fix them later - @Test(enabled = false) - public void testAlterTableDropColumn() throws Exception { - String tableName = createTable(); - String colDropped = "id"; - String query = "alter table " + tableName + " replace columns (name string)"; - - runCommand(query); - - assertColumnIsNotRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), colDropped)); - - //Verify the number of columns present in the table - List columns = getColumns(DEFAULT_DB, tableName); - - assertEquals(columns.size(), 1); - assertEquals(columns.get(0).getAttribute(NAME), "name"); - - String tblId = assertTableIsRegistered(DEFAULT_DB, tableName); - AtlasEntity tblEntity = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries = (List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 2); - } - - @Test - public void testAlterTableChangeColumn() throws Exception { - //Change name - String oldColName = NAME; - String newColName = "name1"; - String tableName = createTable(); - String query = String.format("alter table %s change %s %s string", tableName, oldColName, newColName); - - runCommandWithDelay(query, 3000); - - assertColumnIsNotRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), oldColName)); - assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), newColName)); - - //Verify the number of columns present in the table - List columns = getColumns(DEFAULT_DB, tableName); - - Assert.assertEquals(columns.size(), 2); - - String tblId = assertTableIsRegistered(DEFAULT_DB, tableName); - AtlasEntity tblEntity = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries = (List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 2); - - //Change column type - oldColName = "name1"; - newColName = "name2"; - - String newColType = "int"; - - query = String.format("alter table %s change column %s %s %s", tableName, oldColName, newColName, newColType); - - runCommandWithDelay(query, 3000); - - columns = getColumns(DEFAULT_DB, tableName); - - Assert.assertEquals(columns.size(), 2); - - String newColQualifiedName = HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), newColName); - - assertColumnIsRegistered(newColQualifiedName, new AssertPredicate() { - @Override - public void assertOnEntity(AtlasEntity entity) throws Exception { - assertEquals(entity.getAttribute("type"), "int"); - } - }); - - assertColumnIsNotRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), oldColName)); - - AtlasEntity tblEntity2 = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries2 = (List) tblEntity2.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries2); - Assert.assertEquals(ddlQueries2.size(), 3); - - //Change name and add comment - oldColName = "name2"; - newColName = "name3"; - - String comment = "added comment"; - - query = String.format("alter table %s change column %s %s %s COMMENT '%s' after id", tableName, oldColName, newColName, newColType, comment); - - runCommandWithDelay(query, 3000); - - columns = getColumns(DEFAULT_DB, tableName); - - Assert.assertEquals(columns.size(), 2); - - assertColumnIsNotRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), oldColName)); - - newColQualifiedName = HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), newColName); - - assertColumnIsRegistered(newColQualifiedName, new AssertPredicate() { - @Override - public void assertOnEntity(AtlasEntity entity) throws Exception { - assertEquals(entity.getAttribute(ATTRIBUTE_COMMENT), comment); - } - }); - - //Change column position - oldColName = "name3"; - newColName = "name4"; - query = String.format("alter table %s change column %s %s %s first", tableName, oldColName, newColName, newColType); - - runCommandWithDelay(query, 3000); - - columns = getColumns(DEFAULT_DB, tableName); - - Assert.assertEquals(columns.size(), 2); - - assertColumnIsNotRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), oldColName)); - - newColQualifiedName = HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), newColName); - - assertColumnIsRegistered(newColQualifiedName); - - String finalNewColName = newColName; - - String tblId3 = assertTableIsRegistered(DEFAULT_DB, tableName, new AssertPredicate() { - @Override - public void assertOnEntity(AtlasEntity entity) throws Exception { - List columns = toAtlasObjectIdList(entity.getAttribute(ATTRIBUTE_COLUMNS)); - - assertEquals(columns.size(), 2); - } - } - ); - - AtlasEntity tblEntity3 = atlasClientV2.getEntityByGuid(tblId3).getEntity(); - List ddlQueries3 = (List) tblEntity3.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries3); - Assert.assertEquals(ddlQueries3.size(), 5); - - //Change col position again - oldColName = "name4"; - newColName = "name5"; - query = String.format("alter table %s change column %s %s %s after id", tableName, oldColName, newColName, newColType); - - runCommandWithDelay(query, 3000); - - columns = getColumns(DEFAULT_DB, tableName); - - Assert.assertEquals(columns.size(), 2); - - assertColumnIsNotRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), oldColName)); - - newColQualifiedName = HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), newColName); - - assertColumnIsRegistered(newColQualifiedName); - - //Check col position - String finalNewColName2 = newColName; - - String tblId4 = assertTableIsRegistered(DEFAULT_DB, tableName, new AssertPredicate() { - @Override - public void assertOnEntity(AtlasEntity entity) throws Exception { - List columns = toAtlasObjectIdList(entity.getAttribute(ATTRIBUTE_COLUMNS)); - - assertEquals(columns.size(), 2); - } - } - ); - - AtlasEntity tblEntity4 = atlasClientV2.getEntityByGuid(tblId4).getEntity(); - List ddlQueries4 = (List) tblEntity4.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries4); - Assert.assertEquals(ddlQueries4.size(), 6); - } - - /** - * Reenabling this test since HIVE-14706 is fixed now and the hive version we are using now sends - * us the column lineage information - * @throws Exception - */ - @Test - public void testColumnLevelLineage() throws Exception { - String sourceTable = "table" + random(); - - runCommand("create table " + sourceTable + "(a int, b int)"); - - String sourceTableGUID = assertTableIsRegistered(DEFAULT_DB, sourceTable); - String a_guid = assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, sourceTable), "a")); - String b_guid = assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, sourceTable), "b")); - String ctasTableName = "table" + random(); - String query = "create table " + ctasTableName + " as " + "select sum(a+b) as a, count(*) as b from " + sourceTable; - - runCommand(query); - - String dest_a_guid = assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, ctasTableName), "a")); - String dest_b_guid = assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, ctasTableName), "b")); - - Set inputs = getInputs(sourceTable, Entity.Type.TABLE); - Set outputs = getOutputs(ctasTableName, Entity.Type.TABLE); - HiveEventContext event = constructEvent(query, HiveOperation.CREATETABLE_AS_SELECT, inputs, outputs); - AtlasEntity processEntity1 = validateProcess(event); - AtlasEntity hiveProcessExecution1 = validateProcessExecution(processEntity1, event); - AtlasObjectId process1 = toAtlasObjectId(hiveProcessExecution1.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process1.getGuid(), processEntity1.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - Assert.assertEquals(processEntity1.getGuid(), processEntity1.getGuid()); - - assertTableIsRegistered(DEFAULT_DB, ctasTableName); - - String processQName = sortEventsAndGetProcessQualifiedName(event); - List aLineageInputs = Arrays.asList(a_guid, b_guid); - String aLineageProcessName = processQName + ":" + "a"; - - LOG.debug("Searching for column lineage process {} ", aLineageProcessName); - String guid = assertEntityIsRegistered(HiveDataTypes.HIVE_COLUMN_LINEAGE.getName(), ATTRIBUTE_QUALIFIED_NAME, aLineageProcessName, null); - - AtlasEntity colLineageEntity = atlasClientV2.getEntityByGuid(guid).getEntity(); - List processInputs = toAtlasObjectIdList(colLineageEntity.getAttribute("inputs")); - List processInputsAsString = new ArrayList<>(); - - for(AtlasObjectId input: processInputs){ - processInputsAsString.add(input.getGuid()); - } - - Collections.sort(processInputsAsString); - Collections.sort(aLineageInputs); - - Assert.assertEquals(processInputsAsString, aLineageInputs); - - List bLineageInputs = Arrays.asList(sourceTableGUID); - String bLineageProcessName = processQName + ":" + "b"; - - LOG.debug("Searching for column lineage process {} ", bLineageProcessName); - - String guid1 = assertEntityIsRegistered(HiveDataTypes.HIVE_COLUMN_LINEAGE.getName(), ATTRIBUTE_QUALIFIED_NAME, bLineageProcessName, null); - - - AtlasEntity colLineageEntity1 = atlasClientV2.getEntityByGuid(guid1).getEntity(); - List bProcessInputs = toAtlasObjectIdList(colLineageEntity1.getAttribute("inputs")); - List bProcessInputsAsString = new ArrayList<>(); - - for(AtlasObjectId input: bProcessInputs){ - bProcessInputsAsString.add(input.getGuid()); - } - - Collections.sort(bProcessInputsAsString); - Collections.sort(bLineageInputs); - - Assert.assertEquals(bProcessInputsAsString, bLineageInputs); - - //Test lineage API response - AtlasLineageInfo atlasLineageInfoInput = atlasClientV2.getLineageInfo(dest_a_guid, AtlasLineageInfo.LineageDirection.INPUT,0); - Map entityMap = atlasLineageInfoInput.getGuidEntityMap(); - - ObjectNode response = atlasClient.getInputGraphForEntity(dest_a_guid); - JsonNode vertices = response.get("values").get("vertices"); - JsonNode dest_a_val = vertices.get(dest_a_guid); - JsonNode src_a_val = vertices.get(a_guid); - JsonNode src_b_val = vertices.get(b_guid); - - Assert.assertNotNull(dest_a_val); - Assert.assertNotNull(src_a_val); - Assert.assertNotNull(src_b_val); - - ObjectNode b_response = atlasClient.getInputGraphForEntity(dest_b_guid); - JsonNode b_vertices = b_response.get("values").get("vertices"); - JsonNode b_val = b_vertices.get(dest_b_guid); - JsonNode src_tbl_val = b_vertices.get(sourceTableGUID); - - Assert.assertNotNull(b_val); - Assert.assertNotNull(src_tbl_val); - } - - @Test - public void testIgnoreTruncateTable() throws Exception { - String tableName = createTable(false); - String query = String.format("truncate table %s", tableName); - - runCommand(query); - - Set outputs = getOutputs(tableName, Entity.Type.TABLE); - HiveEventContext event = constructEvent(query, HiveOperation.TRUNCATETABLE, null, outputs); - - assertTableIsRegistered(DEFAULT_DB, tableName); - assertProcessIsNotRegistered(event); - } - - @Test - public void testAlterTablePartitionColumnType() throws Exception { - String tableName = createTable(true, true, false); - String newType = "int"; - String query = String.format("ALTER TABLE %s PARTITION COLUMN (dt %s)", tableName, newType); - - runCommand(query); - - String colQualifiedName = HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), "dt"); - String dtColId = assertColumnIsRegistered(colQualifiedName, new AssertPredicate() { - @Override - public void assertOnEntity(AtlasEntity column) throws Exception { - Assert.assertEquals(column.getAttribute("type"), newType); - } - }); - - assertTableIsRegistered(DEFAULT_DB, tableName, new AssertPredicate() { - @Override - public void assertOnEntity(AtlasEntity table) throws Exception { - final List partitionKeys = toAtlasObjectIdList(table.getAttribute("partitionKeys")); - Assert.assertEquals(partitionKeys.size(), 1); - Assert.assertEquals(partitionKeys.get(0).getGuid(), dtColId); - - } - }); - } - - @Test - public void testAlterTableWithoutHookConf() throws Exception { - String tableName = tableName(); - String createCommand = "create table " + tableName + " (id int, name string)"; - - driverWithNoHook.run(createCommand); - - assertTableIsNotRegistered(DEFAULT_DB, tableName); - - String command = "alter table " + tableName + " change id id_new string"; - - runCommand(command); - - assertTableIsRegistered(DEFAULT_DB, tableName); - - String tbqn = HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName); - - assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(tbqn, "id_new")); - } - - @Test - public void testTraitsPreservedOnColumnRename() throws Exception { - String dbName = createDatabase(); - String tableName = tableName(); - String createQuery = String.format("create table %s.%s (id int, name string)", dbName, tableName); - - runCommand(createQuery); - - String tbqn = HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, dbName, tableName); - String guid = assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(tbqn, "id")); - String trait = createTrait(guid); - String oldColName = "id"; - String newColName = "id_new"; - String query = String.format("alter table %s.%s change %s %s string", dbName, tableName, oldColName, newColName); - - runCommand(query); - - String guid2 = assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(tbqn, "id_new")); - - assertEquals(guid2, guid); - - assertTrue(atlasClient.getEntity(guid2).getTraitNames().contains(trait)); - } - - @Test - public void testAlterViewRename() throws Exception { - String tableName = createTable(); - String viewName = tableName(); - String newName = tableName(); - String query = "create view " + viewName + " as select * from " + tableName; - - runCommandWithDelay(query, 5000); - - query = "alter view " + viewName + " rename to " + newName; - - runCommandWithDelay(query, 5000); - - assertTableIsNotRegistered(DEFAULT_DB, viewName); - - String viewId = assertTableIsRegistered(DEFAULT_DB, newName); - AtlasEntity viewEntity = atlasClientV2.getEntityByGuid(viewId).getEntity(); - List ddlQueries = (List) viewEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 2); - } - - @Test - public void testAlterTableLocation() throws Exception { - //Its an external table, so the HDFS location should also be registered as an entity - String tableName = createTable(true, true, false); - String testPath = createTestDFSPath("testBaseDir"); - String query = "alter table " + tableName + " set location '" + testPath + "'"; - - runCommandWithDelay(query, 8000); - - String tblId = assertTableIsRegistered(DEFAULT_DB, tableName, new AssertPredicate() { - @Override - public void assertOnEntity(AtlasEntity tableRef) throws Exception { - AtlasObjectId sd = toAtlasObjectId(tableRef.getAttribute(ATTRIBUTE_STORAGEDESC)); - - assertNotNull(sd); - } - }); - - AtlasEntity tblEntity = atlasClientV2.getEntityByGuid(tblId).getEntity(); - List ddlQueries = (List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - Assert.assertNotNull(ddlQueries); - Assert.assertEquals(ddlQueries.size(), 2); - - String processQualifiedName = getTableProcessQualifiedName(DEFAULT_DB, tableName); - String processId = assertEntityIsRegistered(HiveDataTypes.HIVE_PROCESS.getName(), ATTRIBUTE_QUALIFIED_NAME, processQualifiedName, null); - AtlasEntity processEntity = atlasClientV2.getEntityByGuid(processId).getEntity(); - Assert.assertEquals(numberOfProcessExecutions(processEntity), 2); - //validateProcessExecution(processEntity, event); - validateHDFSPaths(processEntity, INPUTS, testPath); - } - - @Test - public void testAlterTableFileFormat() throws Exception { - String tableName = createTable(); - String testFormat = "orc"; - String query = "alter table " + tableName + " set FILEFORMAT " + testFormat; - - runCommand(query); - - assertTableIsRegistered(DEFAULT_DB, tableName, new AssertPredicate() { - @Override - public void assertOnEntity(AtlasEntity tableRef) throws Exception { - AtlasObjectId sdObjectId = toAtlasObjectId(tableRef.getAttribute(ATTRIBUTE_STORAGEDESC)); - AtlasEntity sdEntity = atlasClientV2.getEntityByGuid(sdObjectId.getGuid()).getEntity(); - - Assert.assertEquals(sdEntity.getAttribute(ATTRIBUTE_INPUT_FORMAT), "org.apache.hadoop.hive.ql.io.orc.OrcInputFormat"); - Assert.assertEquals(sdEntity.getAttribute(ATTRIBUTE_OUTPUT_FORMAT), "org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat"); - Assert.assertNotNull(sdEntity.getAttribute(ATTRIBUTE_SERDE_INFO)); - - AtlasStruct serdeInfo = toAtlasStruct(sdEntity.getAttribute(ATTRIBUTE_SERDE_INFO)); - - Assert.assertEquals(serdeInfo.getAttribute(ATTRIBUTE_SERIALIZATION_LIB), "org.apache.hadoop.hive.ql.io.orc.OrcSerde"); - Assert.assertNotNull(serdeInfo.getAttribute(ATTRIBUTE_PARAMETERS)); - Assert.assertEquals(((Map) serdeInfo.getAttribute(ATTRIBUTE_PARAMETERS)).get("serialization.format"), "1"); - } - }); - - - /** - * Hive 'alter table stored as' is not supported - See https://issues.apache.org/jira/browse/HIVE-9576 - * query = "alter table " + tableName + " STORED AS " + testFormat.toUpperCase(); - * runCommand(query); - - * tableRef = atlasClientV1.getEntity(tableId); - * sdRef = (AtlasEntity)tableRef.getAttribute(HiveMetaStoreBridge.STORAGE_DESC); - * Assert.assertEquals(sdRef.getAttribute(HiveMetaStoreBridge.STORAGE_DESC_INPUT_FMT), "org.apache.hadoop.hive.ql.io.orc.OrcInputFormat"); - * Assert.assertEquals(sdRef.getAttribute(HiveMetaStoreBridge.STORAGE_DESC_OUTPUT_FMT), "org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat"); - * Assert.assertEquals(((Map) sdRef.getAttribute(HiveMetaStoreBridge.PARAMETERS)).getAttribute("orc.compress"), "ZLIB"); - */ - } - - @Test - public void testAlterTableBucketingClusterSort() throws Exception { - String tableName = createTable(); - List cols = Collections.singletonList("id"); - - runBucketSortQuery(tableName, 5, cols, cols); - - cols = Arrays.asList("id", NAME); - - runBucketSortQuery(tableName, 2, cols, cols); - } - - private void runBucketSortQuery(String tableName, final int numBuckets, final List bucketCols, final List sortCols) throws Exception { - String fmtQuery = "alter table %s CLUSTERED BY (%s) SORTED BY (%s) INTO %s BUCKETS"; - String query = String.format(fmtQuery, tableName, stripListBrackets(bucketCols.toString()), stripListBrackets(sortCols.toString()), numBuckets); - - runCommand(query); - - assertTableIsRegistered(DEFAULT_DB, tableName, new AssertPredicate() { - @Override - public void assertOnEntity(AtlasEntity entity) throws Exception { - verifyBucketSortingProperties(entity, numBuckets, bucketCols, sortCols); - } - }); - } - - private String stripListBrackets(String listElements) { - return StringUtils.strip(StringUtils.strip(listElements, "["), "]"); - } - - private void verifyBucketSortingProperties(AtlasEntity tableRef, int numBuckets, List bucketColNames, List sortcolNames) throws Exception { - AtlasObjectId sdObjectId = toAtlasObjectId(tableRef.getAttribute(ATTRIBUTE_STORAGEDESC)); - AtlasEntity sdEntity = atlasClientV2.getEntityByGuid(sdObjectId.getGuid()).getEntity(); - - Assert.assertEquals((sdEntity.getAttribute(ATTRIBUTE_NUM_BUCKETS)), numBuckets); - Assert.assertEquals(sdEntity.getAttribute(ATTRIBUTE_BUCKET_COLS), bucketColNames); - - List hiveOrderStructList = toAtlasStructList(sdEntity.getAttribute(ATTRIBUTE_SORT_COLS)); - - Assert.assertNotNull(hiveOrderStructList); - Assert.assertEquals(hiveOrderStructList.size(), sortcolNames.size()); - - for (int i = 0; i < sortcolNames.size(); i++) { - AtlasStruct hiveOrderStruct = hiveOrderStructList.get(i); - - Assert.assertNotNull(hiveOrderStruct); - Assert.assertEquals(hiveOrderStruct.getAttribute("col"), sortcolNames.get(i)); - Assert.assertEquals(hiveOrderStruct.getAttribute("order"), 1); - } - } - - @Test - public void testAlterTableSerde() throws Exception { - //SERDE PROPERTIES - String tableName = createTable(); - Map expectedProps = new HashMap() {{ - put("key1", "value1"); - }}; - - runSerdePropsQuery(tableName, expectedProps); - - expectedProps.put("key2", "value2"); - - //Add another property - runSerdePropsQuery(tableName, expectedProps); - } - - @Test - public void testDropTable() throws Exception { - //Test Deletion of tables and its corrresponding columns - String tableName = createTable(true, true, false); - - assertTableIsRegistered(DEFAULT_DB, tableName); - assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), "id")); - assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), NAME)); - - String query = String.format("drop table %s ", tableName); - - runCommandWithDelay(query, 3000); - - assertColumnIsNotRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), "id")); - assertColumnIsNotRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, tableName), NAME)); - assertTableIsNotRegistered(DEFAULT_DB, tableName); - } - - private WriteEntity getPartitionOutput() { - TestWriteEntity partEntity = new TestWriteEntity(PART_FILE, Entity.Type.PARTITION); - - return partEntity; - } - - private ReadEntity getPartitionInput() { - ReadEntity partEntity = new TestReadEntity(PART_FILE, Entity.Type.PARTITION); - - return partEntity; - } - - @Test - public void testDropDatabaseWithCascade() throws Exception { - //Test Deletion of database and its corresponding tables - String dbName = "db" + random(); - - runCommand("create database " + dbName + " WITH DBPROPERTIES ('p1'='v1')"); - - int numTables = 10; - String[] tableNames = new String[numTables]; - - for(int i = 0; i < numTables; i++) { - tableNames[i] = createTable(true, true, false); - } - - String query = String.format("drop database %s cascade", dbName); - - runCommand(query); - - //Verify columns are not registered for one of the tables - assertColumnIsNotRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, dbName, tableNames[0]), "id")); - assertColumnIsNotRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, dbName, tableNames[0]), NAME)); - - for(int i = 0; i < numTables; i++) { - assertTableIsNotRegistered(dbName, tableNames[i]); - } - - assertDatabaseIsNotRegistered(dbName); - } - - @Test - public void testDropDatabaseWithoutCascade() throws Exception { - //Test Deletion of database and its corresponding tables - String dbName = "db" + random(); - - runCommand("create database " + dbName + " WITH DBPROPERTIES ('p1'='v1')"); - - int numTables = 5; - String[] tableNames = new String[numTables]; - - for(int i = 0; i < numTables; i++) { - tableNames[i] = createTable(true, true, false); - - String query = String.format("drop table %s", tableNames[i]); - - runCommand(query); - - assertTableIsNotRegistered(dbName, tableNames[i]); - } - - String query = String.format("drop database %s", dbName); - - runCommand(query); - - String dbQualifiedName = HiveMetaStoreBridge.getDBQualifiedName(CLUSTER_NAME, dbName); - - Thread.sleep(10000); - - try { - atlasClientV2.getEntityByAttribute(HiveDataTypes.HIVE_DB.getName(), Collections.singletonMap(ATTRIBUTE_QUALIFIED_NAME, dbQualifiedName)); - } catch (AtlasServiceException e) { - if (e.getStatus() == ClientResponse.Status.NOT_FOUND) { - return; - } - } - - fail(String.format("Entity was not supposed to exist for typeName = %s, attributeName = %s, attributeValue = %s", HiveDataTypes.HIVE_DB.getName(), ATTRIBUTE_QUALIFIED_NAME, dbQualifiedName)); - } - - @Test - public void testDropNonExistingDB() throws Exception { - //Test Deletion of a non existing DB - String dbName = "nonexistingdb"; - - assertDatabaseIsNotRegistered(dbName); - - String query = String.format("drop database if exists %s cascade", dbName); - - runCommand(query); - - //Should have no effect - assertDatabaseIsNotRegistered(dbName); - } - - @Test - public void testDropNonExistingTable() throws Exception { - //Test Deletion of a non existing table - String tableName = "nonexistingtable"; - - assertTableIsNotRegistered(DEFAULT_DB, tableName); - - String query = String.format("drop table if exists %s", tableName); - - runCommand(query); - - //Should have no effect - assertTableIsNotRegistered(DEFAULT_DB, tableName); - } - - @Test - public void testDropView() throws Exception { - //Test Deletion of tables and its corrresponding columns - String tableName = createTable(true, true, false); - String viewName = tableName(); - String query = "create view " + viewName + " as select * from " + tableName; - - runCommandWithDelay(query, 3000); - - assertTableIsRegistered(DEFAULT_DB, viewName); - assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, viewName), "id")); - assertColumnIsRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, viewName), NAME)); - - query = String.format("drop view %s ", viewName); - - runCommandWithDelay(query, 3000); - assertColumnIsNotRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, viewName), "id")); - assertColumnIsNotRegistered(HiveMetaStoreBridge.getColumnQualifiedName(HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, DEFAULT_DB, viewName), NAME)); - assertTableIsNotRegistered(DEFAULT_DB, viewName); - } - - private void runSerdePropsQuery(String tableName, Map expectedProps) throws Exception { - String serdeLib = "org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe"; - String serializedProps = getSerializedProps(expectedProps); - String query = String.format("alter table %s set SERDE '%s' WITH SERDEPROPERTIES (%s)", tableName, serdeLib, serializedProps); - - runCommand(query); - - verifyTableSdProperties(tableName, serdeLib, expectedProps); - } - - private String getSerializedProps(Map expectedProps) { - StringBuilder sb = new StringBuilder(); - - for(String expectedPropKey : expectedProps.keySet()) { - if(sb.length() > 0) { - sb.append(","); - } - - sb.append("'").append(expectedPropKey).append("'"); - sb.append("="); - sb.append("'").append(expectedProps.get(expectedPropKey)).append("'"); - } - - return sb.toString(); - } - - @Test - public void testAlterDBOwner() throws Exception { - String dbName = createDatabase(); - - assertDatabaseIsRegistered(dbName); - - String owner = "testOwner"; - String fmtQuery = "alter database %s set OWNER %s %s"; - String query = String.format(fmtQuery, dbName, "USER", owner); - - runCommandWithDelay(query, 3000); - - assertDatabaseIsRegistered(dbName, new AssertPredicate() { - @Override - public void assertOnEntity(AtlasEntity entity) { - assertEquals(entity.getAttribute(AtlasClient.OWNER), owner); - } - }); - } - - @Test - public void testAlterDBProperties() throws Exception { - String dbName = createDatabase(); - String fmtQuery = "alter database %s %s DBPROPERTIES (%s)"; - - testAlterProperties(Entity.Type.DATABASE, dbName, fmtQuery); - } - - @Test - public void testAlterTableProperties() throws Exception { - String tableName = createTable(); - String fmtQuery = "alter table %s %s TBLPROPERTIES (%s)"; - - testAlterProperties(Entity.Type.TABLE, tableName, fmtQuery); - } - - private void testAlterProperties(Entity.Type entityType, String entityName, String fmtQuery) throws Exception { - String SET_OP = "set"; - String UNSET_OP = "unset"; - Map expectedProps = new HashMap() {{ - put("testPropKey1", "testPropValue1"); - put("comment", "test comment"); - }}; - - String query = String.format(fmtQuery, entityName, SET_OP, getSerializedProps(expectedProps)); - - runCommandWithDelay(query, 3000); - - verifyEntityProperties(entityType, entityName, expectedProps, false); - - expectedProps.put("testPropKey2", "testPropValue2"); - //Add another property - - query = String.format(fmtQuery, entityName, SET_OP, getSerializedProps(expectedProps)); - - runCommandWithDelay(query, 3000); - - verifyEntityProperties(entityType, entityName, expectedProps, false); - - if (entityType != Entity.Type.DATABASE) { - //Database unset properties doesnt work - alter database %s unset DBPROPERTIES doesnt work - //Unset all the props - StringBuilder sb = new StringBuilder("'"); - - query = String.format(fmtQuery, entityName, UNSET_OP, Joiner.on("','").skipNulls().appendTo(sb, expectedProps.keySet()).append('\'')); - - runCommandWithDelay(query, 3000); - - verifyEntityProperties(entityType, entityName, expectedProps, true); - } - } - - @Test - public void testAlterViewProperties() throws Exception { - String tableName = createTable(); - String viewName = tableName(); - String query = "create view " + viewName + " as select * from " + tableName; - - runCommand(query); - - String fmtQuery = "alter view %s %s TBLPROPERTIES (%s)"; - - testAlterProperties(Entity.Type.TABLE, viewName, fmtQuery); - } - - private void verifyEntityProperties(Entity.Type type, String entityName, final Map expectedProps, final boolean checkIfNotExists) throws Exception { - switch(type) { - case TABLE: - assertTableIsRegistered(DEFAULT_DB, entityName, new AssertPredicate() { - @Override - public void assertOnEntity(AtlasEntity entity) throws Exception { - verifyProperties(entity, expectedProps, checkIfNotExists); - } - }); - break; - case DATABASE: - assertDatabaseIsRegistered(entityName, new AssertPredicate() { - @Override - public void assertOnEntity(AtlasEntity entity) throws Exception { - verifyProperties(entity, expectedProps, checkIfNotExists); - } - }); - break; - } - } - - private void verifyTableSdProperties(String tableName, final String serdeLib, final Map expectedProps) throws Exception { - assertTableIsRegistered(DEFAULT_DB, tableName, new AssertPredicate() { - @Override - public void assertOnEntity(AtlasEntity tableRef) throws Exception { - AtlasObjectId sdEntity = toAtlasObjectId(tableRef.getAttribute(ATTRIBUTE_STORAGEDESC)); - - assertNotNull(sdEntity); - } - }); - } - - - private void verifyProperties(AtlasStruct referenceable, Map expectedProps, boolean checkIfNotExists) { - Map parameters = (Map) referenceable.getAttribute(ATTRIBUTE_PARAMETERS); - - if (!checkIfNotExists) { - //Check if properties exist - Assert.assertNotNull(parameters); - for (String propKey : expectedProps.keySet()) { - Assert.assertEquals(parameters.get(propKey), expectedProps.get(propKey)); - } - } else { - //Check if properties dont exist - if (expectedProps != null && parameters != null) { - for (String propKey : expectedProps.keySet()) { - Assert.assertFalse(parameters.containsKey(propKey)); - } - } - } - } - - private String sortEventsAndGetProcessQualifiedName(final HiveEventContext event) throws HiveException{ - SortedSet sortedHiveInputs = event.getInputs() == null ? null : new TreeSet(entityComparator); - SortedSet sortedHiveOutputs = event.getOutputs() == null ? null : new TreeSet(entityComparator); - - if (event.getInputs() != null) { - sortedHiveInputs.addAll(event.getInputs()); - } - - if (event.getOutputs() != null) { - sortedHiveOutputs.addAll(event.getOutputs()); - } - - return getProcessQualifiedName(hiveMetaStoreBridge, event, sortedHiveInputs, sortedHiveOutputs, getSortedProcessDataSets(event.getInputs()), getSortedProcessDataSets(event.getOutputs())); - } - - private String assertProcessIsRegistered(final HiveEventContext event) throws Exception { - try { - String processQFName = sortEventsAndGetProcessQualifiedName(event); - - LOG.debug("Searching for process with query {}", processQFName); - - return assertEntityIsRegistered(HiveDataTypes.HIVE_PROCESS.getName(), ATTRIBUTE_QUALIFIED_NAME, processQFName, new AssertPredicate() { - @Override - public void assertOnEntity(final AtlasEntity entity) throws Exception { - List recentQueries = (List) entity.getAttribute(ATTRIBUTE_RECENT_QUERIES); - Assert.assertEquals(recentQueries.get(0), lower(event.getQueryStr())); - } - }); - } catch (Exception e) { - LOG.error("Exception : ", e); - throw e; - } - } - - private String assertProcessIsRegistered(final HiveEventContext event, final Set inputTbls, final Set outputTbls) throws Exception { - try { - SortedSet sortedHiveInputs = event.getInputs() == null ? null : new TreeSet(entityComparator); - SortedSet sortedHiveOutputs = event.getOutputs() == null ? null : new TreeSet(entityComparator); - - if (event.getInputs() != null) { - sortedHiveInputs.addAll(event.getInputs()); - } - - if (event.getOutputs() != null) { - sortedHiveOutputs.addAll(event.getOutputs()); - } - - String processQFName = getProcessQualifiedName(hiveMetaStoreBridge, event, sortedHiveInputs, sortedHiveOutputs, getSortedProcessDataSets(inputTbls), getSortedProcessDataSets(outputTbls)); - - LOG.debug("Searching for process with query {}", processQFName); - - return assertEntityIsRegistered(HiveDataTypes.HIVE_PROCESS.getName(), ATTRIBUTE_QUALIFIED_NAME, processQFName, new AssertPredicate() { - @Override - public void assertOnEntity(final AtlasEntity entity) throws Exception { - List recentQueries = (List) entity.getAttribute(BaseHiveEvent.ATTRIBUTE_RECENT_QUERIES); - - Assert.assertEquals(recentQueries.get(0), lower(event.getQueryStr())); - } - }); - } catch(Exception e) { - LOG.error("Exception : ", e); - throw e; - } - } - - private String assertProcessExecutionIsRegistered(AtlasEntity hiveProcess, final HiveEventContext event) throws Exception { - try { - String guid = ""; - List processExecutions = toAtlasObjectIdList(hiveProcess.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS_EXECUTIONS)); - for (AtlasObjectId processExecution : processExecutions) { - AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfo = atlasClientV2. - getEntityByGuid(processExecution.getGuid()); - AtlasEntity entity = atlasEntityWithExtInfo.getEntity(); - if (String.valueOf(entity.getAttribute(ATTRIBUTE_QUERY_TEXT)).equals(event.getQueryStr().toLowerCase().trim())) { - guid = entity.getGuid(); - } - } - - return assertEntityIsRegisteredViaGuid(guid, new AssertPredicate() { - @Override - public void assertOnEntity(final AtlasEntity entity) throws Exception { - String queryText = (String) entity.getAttribute(ATTRIBUTE_QUERY_TEXT); - Assert.assertEquals(queryText, event.getQueryStr().toLowerCase().trim()); - } - }); - } catch(Exception e) { - LOG.error("Exception : ", e); - throw e; - } - } - - - private String getDSTypeName(Entity entity) { - return Entity.Type.TABLE.equals(entity.getType()) ? HiveDataTypes.HIVE_TABLE.name() : HiveMetaStoreBridge.HDFS_PATH; - } - - private SortedMap getSortedProcessDataSets(Set inputTbls) { - SortedMap inputs = new TreeMap<>(entityComparator); - - if (inputTbls != null) { - for (final T tbl : inputTbls) { - AtlasEntity inputTableRef = new AtlasEntity(getDSTypeName(tbl), new HashMap() {{ - put(ATTRIBUTE_QUALIFIED_NAME, tbl.getName()); - }}); - - inputs.put(tbl, inputTableRef); - } - } - return inputs; - } - - private void assertProcessIsNotRegistered(HiveEventContext event) throws Exception { - try { - SortedSet sortedHiveInputs = event.getInputs() == null ? null : new TreeSet(entityComparator); - SortedSet sortedHiveOutputs = event.getOutputs() == null ? null : new TreeSet(entityComparator); - - if (event.getInputs() != null) { - sortedHiveInputs.addAll(event.getInputs()); - } - - if (event.getOutputs() != null) { - sortedHiveOutputs.addAll(event.getOutputs()); - } - - String processQFName = getProcessQualifiedName(hiveMetaStoreBridge, event, sortedHiveInputs, sortedHiveOutputs, getSortedProcessDataSets(event.getInputs()), getSortedProcessDataSets(event.getOutputs())); - - LOG.debug("Searching for process with query {}", processQFName); - - assertEntityIsNotRegistered(HiveDataTypes.HIVE_PROCESS.getName(), ATTRIBUTE_QUALIFIED_NAME, processQFName); - } catch(Exception e) { - LOG.error("Exception : ", e); - } - } - - private void assertTableIsNotRegistered(String dbName, String tableName, boolean isTemporaryTable) throws Exception { - LOG.debug("Searching for table {}.{}", dbName, tableName); - - String tableQualifiedName = HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, dbName, tableName, isTemporaryTable); - - assertEntityIsNotRegistered(HiveDataTypes.HIVE_TABLE.getName(), ATTRIBUTE_QUALIFIED_NAME, tableQualifiedName); - } - - private void assertTableIsNotRegistered(String dbName, String tableName) throws Exception { - LOG.debug("Searching for table {}.{}", dbName, tableName); - - String tableQualifiedName = HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, dbName, tableName, false); - - assertEntityIsNotRegistered(HiveDataTypes.HIVE_TABLE.getName(), ATTRIBUTE_QUALIFIED_NAME, tableQualifiedName); - } - - private String assertTableIsRegistered(String dbName, String tableName, AssertPredicate assertPredicate) throws Exception { - return assertTableIsRegistered(dbName, tableName, assertPredicate, false); - } - - @Test - public void testLineage() throws Exception { - String table1 = createTable(false); - String db2 = createDatabase(); - String table2 = tableName(); - String query = String.format("create table %s.%s as select * from %s", db2, table2, table1); - - runCommand(query); - - String table1Id = assertTableIsRegistered(DEFAULT_DB, table1); - String table2Id = assertTableIsRegistered(db2, table2); - AtlasLineageInfo inputLineage = atlasClientV2.getLineageInfo(table2Id, AtlasLineageInfo.LineageDirection.INPUT, 0); - Map entityMap = inputLineage.getGuidEntityMap(); - - assertTrue(entityMap.containsKey(table1Id)); - assertTrue(entityMap.containsKey(table2Id)); - - AtlasLineageInfo inputLineage1 = atlasClientV2.getLineageInfo(table1Id, AtlasLineageInfo.LineageDirection.OUTPUT, 0); - Map entityMap1 = inputLineage1.getGuidEntityMap(); - - assertTrue(entityMap1.containsKey(table1Id)); - assertTrue(entityMap1.containsKey(table2Id)); - } - - //For ATLAS-448 - @Test - public void testNoopOperation() throws Exception { - runCommand("show compactions"); - runCommand("show transactions"); - } - - private String createDatabase() throws Exception { - String dbName = dbName(); - - runCommand("create database " + dbName); - - return dbName; - } - - private String columnName() { - return "col" + random(); - } - - private String createTable() throws Exception { - return createTable(false); - } - - private String createTable(boolean isPartitioned) throws Exception { - String tableName = tableName(); - - runCommand("create table " + tableName + "(id int, name string) comment 'table comment' " + (isPartitioned ? " partitioned by(dt string)" : "")); - - return tableName; - } - - private String createTable(boolean isExternal, boolean isPartitioned, boolean isTemporary) throws Exception { - String tableName = tableName(); - - String location = ""; - if (isExternal) { - location = " location '" + createTestDFSPath("someTestPath") + "'"; - } - - runCommandWithDelay("create " + (isExternal ? " EXTERNAL " : "") + (isTemporary ? "TEMPORARY " : "") + "table " + tableName + "(id int, name string) comment 'table comment' " + (isPartitioned ? " partitioned by(dt string)" : "") + location, 3000); - - return tableName; - } - - // ReadEntity class doesn't offer a constructor that takes (name, type). A hack to get the tests going! - private static class TestReadEntity extends ReadEntity { - private final String name; - private final Entity.Type type; - - public TestReadEntity(String name, Entity.Type type) { - this.name = name; - this.type = type; - } - - @Override - public String getName() { return name; } - - @Override - public Entity.Type getType() { return type; } - } - - // WriteEntity class doesn't offer a constructor that takes (name, type). A hack to get the tests going! - private static class TestWriteEntity extends WriteEntity { - private final String name; - private final Entity.Type type; - - public TestWriteEntity(String name, Entity.Type type) { - this.name = name; - this.type = type; - } - - @Override - public String getName() { return name; } - - @Override - public Entity.Type getType() { return type; } - } - - private int numberOfProcessExecutions(AtlasEntity hiveProcess) { - return toAtlasObjectIdList(hiveProcess.getRelationshipAttribute( - BaseHiveEvent.ATTRIBUTE_PROCESS_EXECUTIONS)).size(); - } -} diff --git a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/hook/HiveMetastoreHookIT.java b/addons/hive-bridge/src/test/java/org/apache/atlas/hive/hook/HiveMetastoreHookIT.java deleted file mode 100755 index 2bce1b2a0e0..00000000000 --- a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/hook/HiveMetastoreHookIT.java +++ /dev/null @@ -1,384 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook; - -import org.apache.atlas.AtlasServiceException; -import org.apache.atlas.hive.HiveITBase; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.annotations.Test; - -import java.util.List; -import java.util.Map; - -import static org.apache.atlas.hive.hook.events.BaseHiveEvent.ATTRIBUTE_DDL_QUERIES; -import static org.apache.atlas.model.instance.AtlasEntity.Status.ACTIVE; -import static org.apache.atlas.model.instance.AtlasEntity.Status.DELETED; -import static org.testng.AssertJUnit.*; - -public class HiveMetastoreHookIT extends HiveITBase { - private static final Logger LOG = LoggerFactory.getLogger(HiveMetastoreHookIT.class); - - @Test (priority = 1) - public void testCreateDatabase() throws Exception { - String dbName = dbName(); - String query = "CREATE DATABASE " + dbName; - - runCommand(query); - String dbId = assertDatabaseIsRegistered(dbName); - AtlasEntity dbEntity = getAtlasEntity(dbId); - - assertEquals(((List) dbEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES)).size(), 0); - } - - @Test (priority = 2) - public void testAlterDatabase() throws Exception { - String dbName = dbName(); - String query = "CREATE DATABASE " + dbName; - - runCommand(query); - String dbId = assertDatabaseIsRegistered(dbName); - - AtlasEntity dbEntity = getAtlasEntity(dbId); - assertNotNull(dbEntity); - - // SET DBPROPERTIES - query = "ALTER DATABASE " + dbName + " SET DBPROPERTIES (\"prop1\"=\"val1\", \"prop2\"=\"val2\")"; - runCommandWithDelay(query); - - dbEntity = getAtlasEntity(dbId); - Map parameters = (Map) dbEntity.getAttribute("parameters"); - - assertEquals(((List) dbEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES)).size(), 0); - assertNotNull(parameters); - assertEquals(2, parameters.size()); - - // SET OWNER to 'hive' - query = "ALTER DATABASE " + dbName + " SET OWNER USER hive"; - runCommandWithDelay(query); - - dbEntity = getAtlasEntity(dbId); - - - assertEquals(((List) dbEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES)).size(), 0); - assertEquals(dbEntity.getAttribute("owner"), "hive"); - assertEquals(dbEntity.getAttribute("ownerType"), "USER"); - - // SET LOCATION - String hdfsPath = "hdfs://localhost:8020/warehouse/tablespace/managed/dwx/new_db.db"; - - query = String.format("ALTER DATABASE %s SET LOCATION \"%s\"", dbName, hdfsPath); - runCommandWithDelay(query); - - dbEntity = getAtlasEntity(dbId); - - assertEquals(((List) dbEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES)).size(), 0); - - String location = (String) dbEntity.getAttribute("location"); - assertEquals(location, hdfsPath); - } - - @Test (priority = 3) - public void testDropDatabase() throws Exception { - String dbName = dbName(); - String query = "CREATE DATABASE " + dbName; - - runCommand(query); - String dbId = assertDatabaseIsRegistered(dbName); - - AtlasEntity dbEntity = getAtlasEntity(dbId); - assertNotNull(dbEntity); - - query = "DROP DATABASE " + dbName; - runCommand(query); - assertDatabaseIsNotRegistered(dbName); - - dbEntity = getAtlasEntity(dbId); - assertEquals(dbEntity.getStatus(), DELETED); - } - - @Test (priority = 4) - public void testDropDatabaseWithTables() throws Exception { - String dbName = dbName(); - String query = "CREATE DATABASE " + dbName; - - runCommandWithDelay(query); - String dbId = assertDatabaseIsRegistered(dbName); - assertEquals(getAtlasEntity(dbId).getStatus(), ACTIVE); - - String table1 = tableName(); - runCommandWithDelay("CREATE TABLE " + dbName + "." + table1 + " (name string, age int, dob date)"); - String table1Id = assertTableIsRegistered(dbName, table1); - assertEquals(getAtlasEntity(table1Id).getStatus(), ACTIVE); - - String table2 = tableName(); - runCommandWithDelay("CREATE TABLE " + dbName + "." + table2 + " (name string, age int, dob date)"); - String table2Id = assertTableIsRegistered(dbName, table2); - assertEquals(getAtlasEntity(table2Id).getStatus(), ACTIVE); - - query = "DROP DATABASE " + dbName + " CASCADE"; - runCommandWithDelay(query); - assertDatabaseIsNotRegistered(dbName); - - assertEquals(getAtlasEntity(dbId).getStatus(), DELETED); - assertEquals(getAtlasEntity(table1Id).getStatus(), DELETED); - assertEquals(getAtlasEntity(table2Id).getStatus(), DELETED); - } - - @Test (priority = 5) - public void testCreateTable() throws Exception { - String dbName = dbName(); - String query = "CREATE DATABASE " + dbName; - - runCommand(query); - String dbId = assertDatabaseIsRegistered(dbName); - assertEquals(getAtlasEntity(dbId).getStatus(), ACTIVE); - - String tableName = tableName(); - runCommand("CREATE TABLE " + dbName + "." + tableName + " (name string, age int, dob date)"); - String tblId = assertTableIsRegistered(dbName, tableName); - AtlasEntity tblEntity = getAtlasEntity(tblId); - - assertEquals(((List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES)).size(), 0); - assertEquals(getAtlasEntity(tblId).getStatus(), ACTIVE); - } - - @Test (priority = 6) - public void testCreateView() throws Exception { - String dbName = dbName(); - String query = "CREATE DATABASE " + dbName; - - runCommand(query); - String dbId = assertDatabaseIsRegistered(dbName); - assertEquals(getAtlasEntity(dbId).getStatus(), ACTIVE); - - String tableName = tableName(); - runCommand("CREATE TABLE " + dbName + "." + tableName + " (name string, age int, dob date)"); - String tblId = assertTableIsRegistered(dbName, tableName); - assertEquals(getAtlasEntity(tblId).getStatus(), ACTIVE); - - String viewName = tableName(); - - runCommand("CREATE VIEW " + dbName + "." + viewName + " AS SELECT * FROM " + dbName + "." + tableName); - - tblId = assertTableIsRegistered(dbName, viewName); - AtlasEntity tblEntity = getAtlasEntity(tblId); - - assertEquals(((List) tblEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES)).size(), 0); - assertEquals(getAtlasEntity(tblId).getStatus(), ACTIVE); - } - - @Test (priority = 7) - public void testAlterTableProperties() throws Exception { - String dbName = dbName(); - String query = "CREATE DATABASE " + dbName; - - runCommand(query); - String dbId = assertDatabaseIsRegistered(dbName); - assertEquals(getAtlasEntity(dbId).getStatus(), ACTIVE); - assertEquals(((List) getAtlasEntity(dbId).getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES)).size(), 0); - - String tableName = tableName(); - runCommand("CREATE TABLE " + dbName + "." + tableName + " (name string, age int, dob date)"); - String tblId = assertTableIsRegistered(dbName, tableName); - assertEquals(getAtlasEntity(tblId).getStatus(), ACTIVE); - assertEquals(((List) getAtlasEntity(tblId).getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES)).size(), 0); - - // SET TBLPROPERTIES - query = "ALTER TABLE " + dbName + "." + tableName + " SET TBLPROPERTIES (\"prop1\"=\"val1\", \"prop2\"=\"val2\", \"prop3\"=\"val3\")"; - runCommandWithDelay(query); - - query = "ALTER TABLE " + dbName + "." + tableName + " SET TBLPROPERTIES (\"comment\" = \"sample comment\")"; - runCommandWithDelay(query); - - // SET SERDE - query = "ALTER TABLE " + dbName + "." + tableName + " SET SERDE \"org.apache.hadoop.hive.ql.io.orc.OrcSerde\" WITH SERDEPROPERTIES (\"prop1\"=\"val1\", \"prop2\"=\"val2\")"; - runCommandWithDelay(query); - - // SET SERDEPROPERTIES - query = "ALTER TABLE " + dbName + "." + tableName + " SET SERDEPROPERTIES (\"prop1\"=\"val1\", \"prop2\"=\"val2\")"; - runCommandWithDelay(query); - - AtlasEntity tableEntity = getAtlasEntity(tblId); - Map tableParameters = (Map) tableEntity.getAttribute("parameters"); - - assertEquals(tableParameters.get("comment"), "sample comment"); - assertEquals(tableParameters.get("prop1"), "val1"); - assertEquals(tableParameters.get("prop2"), "val2"); - assertEquals(tableParameters.get("prop3"), "val3"); - - AtlasEntity sdEntity = getAtlasEntity((String) ((Map) tableEntity.getAttribute("sd")).get("guid")); - Map serdeInfo = (Map) sdEntity.getAttribute("serdeInfo"); - Map serdeAttrs = (Map) serdeInfo.get("attributes"); - - assertEquals(serdeAttrs.get("serializationLib"), "org.apache.hadoop.hive.ql.io.orc.OrcSerde"); - assertEquals(((Map) serdeAttrs.get("parameters")).get("prop1"), "val1"); - assertEquals(((Map) serdeAttrs.get("parameters")).get("prop2"), "val2"); - assertEquals(((List) tableEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES)).size(), 0); - } - - @Test (priority = 8) - public void testAlterTableRenameTableName() throws Exception { - String dbName = dbName(); - String query = "CREATE DATABASE " + dbName; - - runCommand(query); - String dbId = assertDatabaseIsRegistered(dbName); - assertEquals(getAtlasEntity(dbId).getStatus(), ACTIVE); - - String tableName = tableName(); - runCommand("CREATE TABLE " + dbName + "." + tableName + " (name string, age int, dob date)"); - String tblId = assertTableIsRegistered(dbName, tableName); - assertEquals(getAtlasEntity(tblId).getStatus(), ACTIVE); - - // RENAME TABLE NAME - String newTableName = tableName + "_new"; - query = "ALTER TABLE " + dbName + "." + tableName + " RENAME TO " + dbName + "." + newTableName; - runCommandWithDelay(query); - - AtlasEntityWithExtInfo tableEntityWithExtInfo = getAtlasEntityWithExtInfo(tblId); - AtlasEntity tableEntity = tableEntityWithExtInfo.getEntity(); - - assertEquals(((List) tableEntity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES)).size(), 0); - - // validate table rename in table entity - assertEquals(newTableName, tableEntity.getAttribute("name")); - assertTrue(((String) tableEntity.getAttribute("qualifiedName")).contains(newTableName)); - - // validate table rename in column and sd entity - for (AtlasEntity referredEntity : tableEntityWithExtInfo.getReferredEntities().values()) { - assertTrue(((String) referredEntity.getAttribute("qualifiedName")).contains(newTableName)); - } - } - - @Test (priority = 9) - public void testAlterTableRenameColumnName() throws Exception { - String dbName = dbName(); - String query = "CREATE DATABASE " + dbName; - - runCommand(query); - String dbId = assertDatabaseIsRegistered(dbName); - assertEquals(getAtlasEntity(dbId).getStatus(), ACTIVE); - - String tableName = tableName(); - runCommand("CREATE TABLE " + dbName + "." + tableName + " (col1 int, col2 int, col3 int)"); - String tblId = assertTableIsRegistered(dbName, tableName); - AtlasEntityWithExtInfo tableEntityWithExtInfo = getAtlasEntityWithExtInfo(tblId); - - assertEquals(tableEntityWithExtInfo.getEntity().getStatus(), ACTIVE); - - String col1Id = getColumnId(tableEntityWithExtInfo, "col1"); - String col2Id = getColumnId(tableEntityWithExtInfo, "col2"); - - // RENAME COLUMN NAME - query = "ALTER TABLE " + dbName + "." + tableName + " CHANGE col1 col11 int"; - runCommandWithDelay(query); - - AtlasEntity col1Entity = getAtlasEntity(col1Id); - assertEquals(col1Entity.getAttribute("name"), "col11"); - assertTrue(((String) col1Entity.getAttribute("qualifiedName")).contains("col11")); - - // CHANGE COLUMN NAME and DATATYPE - query = "ALTER TABLE " + dbName + "." + tableName + " CHANGE col2 col22 string"; - runCommandWithDelay(query); - - AtlasEntity col2Entity = getAtlasEntity(col2Id); - assertEquals(col2Entity.getAttribute("name"), "col22"); - assertEquals(col2Entity.getAttribute("type"), "string"); - assertEquals(((List) getAtlasEntity(tblId).getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES)).size(), 0); - } - - @Test (priority = 10) - public void testDropTable() throws Exception { - String dbName = dbName(); - String query = "CREATE DATABASE " + dbName; - - runCommand(query); - String dbId = assertDatabaseIsRegistered(dbName); - assertEquals(getAtlasEntity(dbId).getStatus(), ACTIVE); - - String tableName = tableName(); - runCommand("CREATE TABLE " + dbName + "." + tableName + " (name string, age int, dob date)"); - String tblId = assertTableIsRegistered(dbName, tableName); - assertEquals(getAtlasEntity(tblId).getStatus(), ACTIVE); - - query = "DROP TABLE " + dbName + "." + tableName; - runCommandWithDelay(query); - - assertEquals(getAtlasEntity(tblId).getStatus(), DELETED); - } - - @Test (priority = 11) - public void testDropView() throws Exception { - String dbName = dbName(); - String query = "CREATE DATABASE " + dbName; - - runCommand(query); - String dbId = assertDatabaseIsRegistered(dbName); - assertEquals(getAtlasEntity(dbId).getStatus(), ACTIVE); - - String tableName = tableName(); - runCommand("CREATE TABLE " + dbName + "." + tableName + " (name string, age int, dob date)"); - String tblId = assertTableIsRegistered(dbName, tableName); - assertEquals(getAtlasEntity(tblId).getStatus(), ACTIVE); - - String viewName = tableName(); - runCommand("CREATE VIEW " + dbName + "." + viewName + " AS SELECT * FROM " + dbName + "." + tableName); - tblId = assertTableIsRegistered(dbName, viewName); - assertEquals(getAtlasEntity(tblId).getStatus(), ACTIVE); - - query = "DROP VIEW " + dbName + "." + viewName; - runCommandWithDelay(query); - - assertEquals(getAtlasEntity(tblId).getStatus(), DELETED); - } - - private String getColumnId(AtlasEntityWithExtInfo entityWithExtInfo, String columnName) { - String ret = null; - - for (AtlasEntity entity : entityWithExtInfo.getReferredEntities().values()) { - - if (entity.getTypeName().equals("hive_column") && entity.getAttribute("name").equals(columnName)) { - ret = entity.getGuid(); - break; - } - } - - return ret; - } - - private AtlasEntity getAtlasEntity(String guid) throws AtlasServiceException { - return atlasClientV2.getEntityByGuid(guid).getEntity(); - } - - private AtlasEntityWithExtInfo getAtlasEntityWithExtInfo(String guid) throws AtlasServiceException { - return atlasClientV2.getEntityByGuid(guid); - } - - protected void runCommand(String cmd) throws Exception { - runCommandWithDelay(driverWithoutContext, cmd, 0); - } - - protected void runCommandWithDelay(String cmd) throws Exception { - int delayTimeInMs = 10000; - runCommandWithDelay(driverWithoutContext, cmd, delayTimeInMs); - } -} \ No newline at end of file diff --git a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/hook/utils/ActiveEntityFilterTest.java b/addons/hive-bridge/src/test/java/org/apache/atlas/hive/hook/utils/ActiveEntityFilterTest.java deleted file mode 100644 index a20121496e2..00000000000 --- a/addons/hive-bridge/src/test/java/org/apache/atlas/hive/hook/utils/ActiveEntityFilterTest.java +++ /dev/null @@ -1,210 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.hive.hook.utils; - -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.type.AtlasType; -import org.apache.atlas.utils.TestResourceFileUtils; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -public class ActiveEntityFilterTest { - private static String FILE_SUFFIX_ACTUAL_RESULTS = "-v2"; - private static String ADDITIONAL_TYPE_HDFS_PATH = "hdfs_path"; - - @BeforeClass - public void setup() { - ActiveEntityFilter.init(true, Arrays.asList(new String[]{ADDITIONAL_TYPE_HDFS_PATH})); - } - - @Test - public void verifyMessages() throws IOException { - assertAtlasEntitiesWithExtInfoFromFile("hs2-drop-db"); - assertAtlasEntitiesWithExtInfoFromFile("hs2-create-db"); - assertAtlasEntitiesWithExtInfoFromFile("hs2-create-table"); - assertMessageFromFile("hs2-table-rename"); - assertMessageFromFile("hs2-alter-view"); - assertMessageFromFile("hs2-drop-table"); - assertAtlasEntitiesWithExtInfoFromFile("hs2-create-process"); - assertMessageFromFile("hs2-load-inpath"); - } - - private void assertMessageFromFile(String msgFile) throws IOException { - List incoming = loadList(msgFile); - List expected = loadList(msgFile + FILE_SUFFIX_ACTUAL_RESULTS); - int expectedSize = expected.size(); - - List actual = ActiveEntityFilter.apply((List) incoming); - assertEquals(actual.size(), expected.size()); - for (int i = 0; i < expectedSize; i++) { - if (actual.get(i) instanceof HookNotification.EntityCreateRequestV2) { - HookNotification.EntityCreateRequestV2 actualN = (HookNotification.EntityCreateRequestV2) actual.get(i); - HookNotification.EntityCreateRequestV2 expectedN = (HookNotification.EntityCreateRequestV2) expected.get(i); - - assertAtlasEntitiesWithExtInfo(actualN.getEntities(), expectedN.getEntities()); - } - - if (actual.get(i) instanceof HookNotification.EntityUpdateRequestV2) { - HookNotification.EntityUpdateRequestV2 actualN = (HookNotification.EntityUpdateRequestV2) actual.get(i); - HookNotification.EntityUpdateRequestV2 expectedN = (HookNotification.EntityUpdateRequestV2) expected.get(i); - - assertAtlasEntitiesWithExtInfo(actualN.getEntities(), expectedN.getEntities()); - } - - if (actual.get(i) instanceof HookNotification.EntityPartialUpdateRequestV2) { - HookNotification.EntityPartialUpdateRequestV2 actualN = (HookNotification.EntityPartialUpdateRequestV2) actual.get(i); - HookNotification.EntityPartialUpdateRequestV2 expectedN = (HookNotification.EntityPartialUpdateRequestV2) expected.get(i); - - assertAtlasEntitiesWithExtInfo(actualN.getEntity(), expectedN.getEntity()); - } - } - } - - private List loadList(String msgFile) throws IOException { - List list = TestResourceFileUtils.readObjectFromJson("", msgFile, List.class); - List ret = new ArrayList<>(); - - for (int i = 0; i < list.size(); i++) { - HookNotification notification = createNotification((LinkedHashMap) list.get(i)); - if (notification == null) { - continue; - } - - ret.add(notification); - } - - return ret; - } - - private HookNotification createNotification(LinkedHashMap linkedHashMap) { - assertTrue(linkedHashMap.containsKey("type")); - - String type = (String) linkedHashMap.get("type"); - switch (type) { - case "ENTITY_CREATE_V2": - return AtlasType.fromLinkedHashMap(linkedHashMap, HookNotification.EntityCreateRequestV2.class); - - case "ENTITY_FULL_UPDATE_V2": - return AtlasType.fromLinkedHashMap(linkedHashMap, HookNotification.EntityUpdateRequestV2.class); - - case "ENTITY_PARTIAL_UPDATE_V2": - return AtlasType.fromLinkedHashMap(linkedHashMap, HookNotification.EntityPartialUpdateRequestV2.class); - - default: - return null; - } - } - - - private void assertAtlasEntitiesWithExtInfo(AtlasEntity.AtlasEntityWithExtInfo actual, AtlasEntity.AtlasEntityWithExtInfo expected) { - String actualJson = AtlasType.toJson(actual); - String expectedJson = AtlasType.toJson(expected); - - LinkedHashMap actualLHM = AtlasType.fromJson(actualJson, LinkedHashMap.class); - LinkedHashMap expectedLHM = AtlasType.fromJson(expectedJson, LinkedHashMap.class); - - AssertLinkedHashMap.assertEquals(actualLHM, expectedLHM); - } - - private void assertAtlasEntitiesWithExtInfoFromFile(String entityFile) throws IOException { - AtlasEntity.AtlasEntitiesWithExtInfo incoming = TestResourceFileUtils.readObjectFromJson("", entityFile, AtlasEntity.AtlasEntitiesWithExtInfo.class); - AtlasEntity.AtlasEntitiesWithExtInfo expected = TestResourceFileUtils.readObjectFromJson("", entityFile + FILE_SUFFIX_ACTUAL_RESULTS, AtlasEntity.AtlasEntitiesWithExtInfo.class); - - HiveDDLEntityFilter hiveLineageEntityFilter = new HiveDDLEntityFilter(null); - AtlasEntity.AtlasEntitiesWithExtInfo actual = hiveLineageEntityFilter.apply(incoming); - assertAtlasEntitiesWithExtInfo(actual, expected); - } - - private void assertAtlasEntitiesWithExtInfo(AtlasEntity.AtlasEntitiesWithExtInfo actual, AtlasEntity.AtlasEntitiesWithExtInfo expected) { - assertNotNull(actual); - assertNotNull(expected); - - assertEquals(actual.getEntities().size(), expected.getEntities().size()); - assertEntity(actual.getEntities(), expected.getEntities()); - - if (expected.getReferredEntities() == null && actual.getReferredEntities() != null) { - fail("expected.getReferredEntities() == null, but expected.getReferredEntities() != null"); - } - - if (expected.getReferredEntities() != null && actual.getReferredEntities() != null) { - assertEntity(actual.getReferredEntities(), expected.getReferredEntities()); - } - } - - private void assertEntity(Map actual, Map expected) { - assertEquals(actual.size(), expected.size()); - } - - private void assertEntity(List actual, List expected) { - AssertLinkedHashMap.assertEquals(actual, expected); - } - - private static class AssertLinkedHashMap { - private static final String MISMATCH_KEY_FORMAT = "Mismatch: Key: %s"; - private static final Set excludeKeys = new HashSet() {{ - add("guid"); - add("owner"); - }}; - - public static void assertEquals(LinkedHashMap actual, LinkedHashMap expected) { - for (String key : expected.keySet()) { - assertTrue(actual.containsKey(key), "Key: " + key + " Not found!"); - - if (excludeKeys.contains(key)) { - continue; - } - - if (actual.get(key) instanceof LinkedHashMap) { - assertEquals((LinkedHashMap) actual.get(key), (LinkedHashMap) expected.get(key)); - continue; - } - - Assert.assertEquals(actual.get(key), actual.get(key), String.format(MISMATCH_KEY_FORMAT, key)); - } - } - - public static void assertEquals(List actual, List expected) { - Assert.assertEquals(actual.size(), expected.size()); - for (int i = 0; i < actual.size(); i++) { - AtlasEntity actualEntity = actual.get(i); - AtlasEntity expectedEntity = expected.get(i); - - String actualJson = AtlasType.toJson(actualEntity); - String expectedJson = AtlasType.toJson(expectedEntity); - - Assert.assertEquals(actualJson, expectedJson, "Actual: " + actualJson); - } - } - } -} diff --git a/addons/hive-bridge/src/test/resources/atlas-application.properties b/addons/hive-bridge/src/test/resources/atlas-application.properties deleted file mode 100644 index 5d24a3014c4..00000000000 --- a/addons/hive-bridge/src/test/resources/atlas-application.properties +++ /dev/null @@ -1,125 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# - -######### Atlas Server Configs ######### -atlas.rest.address=http://localhost:31000 - -######### Graph Database Configs ######### - - -# Graph database implementation. Value inserted by maven. -atlas.graphdb.backend=org.apache.atlas.repository.graphdb.janus.AtlasJanusGraphDatabase - -# Graph Storage -atlas.graph.storage.backend=berkeleyje - -# Entity repository implementation -atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.InMemoryEntityAuditRepository - -# Graph Search Index Backend -atlas.graph.index.search.backend=solr - -#Berkeley storage directory -atlas.graph.storage.directory=${sys:atlas.data}/berkley - -#hbase -#For standalone mode , specify localhost -#for distributed mode, specify zookeeper quorum here - -atlas.graph.storage.hostname=${graph.storage.hostname} -atlas.graph.storage.hbase.regions-per-server=1 -atlas.graph.storage.lock.wait-time=10000 - -#ElasticSearch -atlas.graph.index.search.directory=${sys:atlas.data}/es -atlas.graph.index.search.elasticsearch.client-only=false -atlas.graph.index.search.elasticsearch.local-mode=true -atlas.graph.index.search.elasticsearch.create.sleep=2000 - -# Solr cloud mode properties -atlas.graph.index.search.solr.mode=cloud -atlas.graph.index.search.solr.zookeeper-url=${solr.zk.address} -atlas.graph.index.search.solr.embedded=true -atlas.graph.index.search.max-result-set-size=150 - - -######### Notification Configs ######### -atlas.notification.embedded=true - -atlas.kafka.zookeeper.connect=localhost:19026 -atlas.kafka.bootstrap.servers=localhost:19027 -atlas.kafka.data=${sys:atlas.data}/kafka -atlas.kafka.zookeeper.session.timeout.ms=4000 -atlas.kafka.zookeeper.sync.time.ms=20 -atlas.kafka.consumer.timeout.ms=4000 -atlas.kafka.auto.commit.interval.ms=100 -atlas.kafka.hook.group.id=atlas -atlas.kafka.entities.group.id=atlas_entities -#atlas.kafka.auto.commit.enable=false - -atlas.kafka.enable.auto.commit=false -atlas.kafka.auto.offset.reset=earliest -atlas.kafka.session.timeout.ms=30000 -atlas.kafka.offsets.topic.replication.factor=1 - - - -######### Entity Audit Configs ######### -atlas.audit.hbase.tablename=ATLAS_ENTITY_AUDIT_EVENTS -atlas.audit.zookeeper.session.timeout.ms=1000 -atlas.audit.hbase.zookeeper.quorum=localhost -atlas.audit.hbase.zookeeper.property.clientPort=19026 - -######### Security Properties ######### - -# SSL config -atlas.enableTLS=false -atlas.server.https.port=31443 - -######### Security Properties ######### - -hbase.security.authentication=simple - -atlas.hook.falcon.synchronous=true - -######### JAAS Configuration ######## - -atlas.jaas.KafkaClient.loginModuleName = com.sun.security.auth.module.Krb5LoginModule -atlas.jaas.KafkaClient.loginModuleControlFlag = required -atlas.jaas.KafkaClient.option.useKeyTab = true -atlas.jaas.KafkaClient.option.storeKey = true -atlas.jaas.KafkaClient.option.serviceName = kafka -atlas.jaas.KafkaClient.option.keyTab = /etc/security/keytabs/atlas.service.keytab -atlas.jaas.KafkaClient.option.principal = atlas/_HOST@EXAMPLE.COM - -######### High Availability Configuration ######## -atlas.server.ha.enabled=false -#atlas.server.ids=id1 -#atlas.server.address.id1=localhost:21000 - -######### Atlas Authorization ######### -atlas.authorizer.impl=none -# atlas.authorizer.impl=simple -# atlas.authorizer.simple.authz.policy.file=atlas-simple-authz-policy.json - -######### Atlas Authentication ######### -atlas.authentication.method.file=true -atlas.authentication.method.ldap.type=none -atlas.authentication.method.kerberos=false -# atlas.authentication.method.file.filename=users-credentials.properties -atlas.hook.hive.hs2.ignore.ddl.operations=false \ No newline at end of file diff --git a/addons/hive-bridge/src/test/resources/atlas-log4j.xml b/addons/hive-bridge/src/test/resources/atlas-log4j.xml deleted file mode 100755 index 262a710f7aa..00000000000 --- a/addons/hive-bridge/src/test/resources/atlas-log4j.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/hive-bridge/src/test/resources/hive-site.xml b/addons/hive-bridge/src/test/resources/hive-site.xml deleted file mode 100644 index f9ec5773e88..00000000000 --- a/addons/hive-bridge/src/test/resources/hive-site.xml +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - hive.exec.submit.local.task.via.child - false - - - - mapreduce.framework.name - local - - - - fs.default.name - file:/// - - - - hive.exec.post.hooks - org.apache.atlas.hive.hook.HiveHook - - - - hive.metastore.event.listeners - org.apache.atlas.hive.hook.HiveMetastoreHookImpl - - - - hive.support.concurrency - false - - - - hive.metastore.warehouse.dir - ${project.basedir}/target/metastore - - - - javax.jdo.option.ConnectionURL - jdbc:derby:;databaseName=${project.basedir}/target/metastore_db;create=true - - - - atlas.hook.hive.synchronous - true - - - - fs.pfile.impl - org.apache.hadoop.fs.ProxyLocalFileSystem - - - - hive.in.test - true - - - - hive.zookeeper.quorum - localhost:19026 - - - - hive.metastore.schema.verification - false - - - - hive.metastore.disallow.incompatible.col.type.changes - false - - - - datanucleus.schema.autoCreateAll - true - - - - hive.exec.scratchdir - ${project.basedir}/target/scratchdir - - - \ No newline at end of file diff --git a/addons/hive-bridge/src/test/resources/json/hs2-alter-view-v2.json b/addons/hive-bridge/src/test/resources/json/hs2-alter-view-v2.json deleted file mode 100644 index ebe896ba9ae..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-alter-view-v2.json +++ /dev/null @@ -1,35 +0,0 @@ -[ - { - "type": "ENTITY_CREATE_V2", - "user": "hive", - "entities": { - "entities": [ - { - "typeName": "hive_table_ddl", - "attributes": { - "serviceType": "hive", - "qualifiedName": "cadb02.hh6_renamed_view2@cm:1616450675937", - "execTime": 1616450675937, - "queryText": "ALTER VIEW hh6_renamed_view RENAME TO hh6_renamed_view2", - "name": "ALTER VIEW hh6_renamed_view RENAME TO hh6_renamed_view2", - "userName": "hive" - }, - "guid": "-14529329955589487", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed_view2@cm" - }, - "relationshipType": "hive_table_ddl_queries" - } - }, - "proxy": false - } - ] - } - } -] diff --git a/addons/hive-bridge/src/test/resources/json/hs2-alter-view.json b/addons/hive-bridge/src/test/resources/json/hs2-alter-view.json deleted file mode 100644 index cfe77847ca3..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-alter-view.json +++ /dev/null @@ -1,268 +0,0 @@ -[ - { - "type": "ENTITY_PARTIAL_UPDATE_V2", - "user": "hive", - "entityId": { - "typeName": "hive_column", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed_view.col1@cm" - } - }, - "entity": { - "entity": { - "typeName": "hive_column", - "attributes": { - "qualifiedName": "cadb02.hh6_renamed_view2.col1@cm" - }, - "guid": "-14529329955589486", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "proxy": false - } - } - }, - { - "type": "ENTITY_PARTIAL_UPDATE_V2", - "user": "hive", - "entityId": { - "typeName": "hive_storagedesc", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed_view@cm_storage" - } - }, - "entity": { - "entity": { - "typeName": "hive_storagedesc", - "attributes": { - "qualifiedName": "cadb02.hh6_renamed_view2@cm_storage", - "storedAsSubDirectories": false, - "location": null, - "compressed": false, - "inputFormat": "org.apache.hadoop.hive.ql.io.orc.OrcInputFormat", - "parameters": {}, - "outputFormat": "org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat", - "serdeInfo": { - "typeName": "hive_serde", - "attributes": { - "serializationLib": null, - "name": null, - "parameters": {} - } - }, - "numBuckets": -1 - }, - "guid": "-14529329955589484", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "proxy": false - } - } - }, - { - "type": "ENTITY_PARTIAL_UPDATE_V2", - "user": "hive", - "entityId": { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed_view@cm" - } - }, - "entity": { - "entity": { - "typeName": "hive_table", - "attributes": { - "owner": "hive", - "temporary": false, - "lastAccessTime": 1616450675000, - "aliases": [ - "hh6_renamed_view" - ], - "qualifiedName": "cadb02.hh6_renamed_view2@cm", - "viewExpandedText": "select `hh6_renamed`.`col1` from `cadb02`.`hh6_renamed`", - "tableType": "VIRTUAL_VIEW", - "createTime": 1616450675000, - "name": "hh6_renamed_view2", - "comment": null, - "parameters": { - "transient_lastDdlTime": "1616450676", - "bucketing_version": "2", - "last_modified_time": "1616450676", - "last_modified_by": "hive" - }, - "retention": 0, - "viewOriginalText": "select * from hh6_renamed" - }, - "guid": "-14529329955589483", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "proxy": false - } - } - }, - { - "type": "ENTITY_FULL_UPDATE_V2", - "user": "hive", - "entities": { - "referredEntities": { - "-14529329955589485": { - "typeName": "hive_column", - "attributes": { - "owner": "hive", - "qualifiedName": "cadb02.hh6_renamed_view2.col1@cm", - "name": "col1", - "comment": null, - "position": 0, - "type": "int" - }, - "guid": "-14529329955589485", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "guid": "-14529329955589483", - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed_view2@cm" - }, - "relationshipType": "hive_table_columns" - } - }, - "proxy": false - }, - "-14529329955589484": { - "typeName": "hive_storagedesc", - "attributes": { - "qualifiedName": "cadb02.hh6_renamed_view2@cm_storage", - "storedAsSubDirectories": false, - "location": null, - "compressed": false, - "inputFormat": "org.apache.hadoop.hive.ql.io.orc.OrcInputFormat", - "parameters": {}, - "outputFormat": "org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat", - "serdeInfo": { - "typeName": "hive_serde", - "attributes": { - "serializationLib": null, - "name": null, - "parameters": {} - } - }, - "numBuckets": -1 - }, - "guid": "-14529329955589484", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "guid": "-14529329955589483", - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed_view2@cm" - }, - "relationshipType": "hive_table_storagedesc" - } - }, - "proxy": false - } - }, - "entities": [ - { - "typeName": "hive_table", - "attributes": { - "owner": "hive", - "temporary": false, - "lastAccessTime": 1616450675000, - "aliases": [ - "hh6_renamed_view" - ], - "qualifiedName": "cadb02.hh6_renamed_view2@cm", - "viewExpandedText": "select `hh6_renamed`.`col1` from `cadb02`.`hh6_renamed`", - "tableType": "VIRTUAL_VIEW", - "createTime": 1616450675000, - "name": "hh6_renamed_view2", - "comment": null, - "parameters": { - "transient_lastDdlTime": "1616450676", - "bucketing_version": "2", - "last_modified_time": "1616450676", - "last_modified_by": "hive" - }, - "retention": 0, - "viewOriginalText": "select * from hh6_renamed" - }, - "guid": "-14529329955589483", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "sd": { - "guid": "-14529329955589484", - "typeName": "hive_storagedesc", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed_view2@cm_storage" - }, - "relationshipType": "hive_table_storagedesc" - }, - "columns": [ - { - "guid": "-14529329955589485", - "typeName": "hive_column", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed_view2.col1@cm" - }, - "relationshipType": "hive_table_columns" - } - ], - "partitionKeys": [], - "db": { - "typeName": "hive_db", - "uniqueAttributes": { - "qualifiedName": "cadb02@cm" - }, - "relationshipType": "hive_table_db" - } - }, - "proxy": false - } - ] - } - }, - { - "type": "ENTITY_CREATE_V2", - "user": "hive", - "entities": { - "entities": [ - { - "typeName": "hive_table_ddl", - "attributes": { - "serviceType": "hive", - "qualifiedName": "cadb02.hh6_renamed_view2@cm:1616450675937", - "execTime": 1616450675937, - "queryText": "ALTER VIEW hh6_renamed_view RENAME TO hh6_renamed_view2", - "name": "ALTER VIEW hh6_renamed_view RENAME TO hh6_renamed_view2", - "userName": "hive" - }, - "guid": "-14529329955589487", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed_view2@cm" - }, - "relationshipType": "hive_table_ddl_queries" - } - }, - "proxy": false - } - ] - } - } -] diff --git a/addons/hive-bridge/src/test/resources/json/hs2-create-db-v2.json b/addons/hive-bridge/src/test/resources/json/hs2-create-db-v2.json deleted file mode 100644 index 28d3b6b24ed..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-create-db-v2.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "referredEntities": {}, - "entities": [ - { - "typeName": "hive_db_ddl", - "attributes": { - "serviceType": "hive", - "qualifiedName": "cadb02@cm:1616450673617", - "execTime": 1616450673617, - "queryText": "create database cadb02", - "name": "create database cadb02", - "userName": "hive" - }, - "guid": "-14529329955589449", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "db": { - "typeName": "hive_db", - "uniqueAttributes": { - "qualifiedName": "cadb02@cm" - }, - "relationshipType": "hive_db_ddl_queries" - } - }, - "proxy": false - }, - { - "typeName": "hdfs_path", - "attributes": { - "path": "hdfs://ve0126.halxg.cloudera.com:8020/warehouse/tablespace/external/hive/cadb02.db", - "qualifiedName": "hdfs://ve0126.halxg.cloudera.com:8020/warehouse/tablespace/external/hive/cadb02.db@cm", - "clusterName": "cm", - "name": "/warehouse/tablespace/external/hive/cadb02.db" - }, - "guid": "-14529329955589450", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "hiveDb": { - "typeName": "hive_db", - "uniqueAttributes": { - "qualifiedName": "cadb02@cm" - }, - "relationshipType": "hive_db_location" - } - }, - "proxy": false - } - ] -} diff --git a/addons/hive-bridge/src/test/resources/json/hs2-create-db.json b/addons/hive-bridge/src/test/resources/json/hs2-create-db.json deleted file mode 100644 index a5b810f729f..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-create-db.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "referredEntities": {}, - "entities": [ - { - "typeName": "hive_db", - "attributes": { - "owner": "hive", - "ownerType": "USER", - "managedLocation": null, - "qualifiedName": "cadb02@cm", - "clusterName": "cm", - "name": "cadb02", - "location": "hdfs://ve0126.halxg.cloudera.com:8020/warehouse/tablespace/external/hive/cadb02.db", - "parameters": {} - }, - "guid": "-14529329955589448", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "proxy": false - }, - { - "typeName": "hive_db_ddl", - "attributes": { - "serviceType": "hive", - "qualifiedName": "cadb02@cm:1616450673617", - "execTime": 1616450673617, - "queryText": "create database cadb02", - "name": "create database cadb02", - "userName": "hive" - }, - "guid": "-14529329955589449", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "db": { - "guid": "-14529329955589448", - "typeName": "hive_db", - "uniqueAttributes": { - "qualifiedName": "cadb02@cm" - }, - "relationshipType": "hive_db_ddl_queries" - } - }, - "proxy": false - }, - { - "typeName": "hdfs_path", - "attributes": { - "path": "hdfs://ve0126.halxg.cloudera.com:8020/warehouse/tablespace/external/hive/cadb02.db", - "qualifiedName": "hdfs://ve0126.halxg.cloudera.com:8020/warehouse/tablespace/external/hive/cadb02.db@cm", - "clusterName": "cm", - "name": "/warehouse/tablespace/external/hive/cadb02.db" - }, - "guid": "-14529329955589450", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "hiveDb": { - "guid": "-14529329955589448", - "typeName": "hive_db", - "uniqueAttributes": { - "qualifiedName": "cadb02@cm" - }, - "relationshipType": "hive_db_location" - } - }, - "proxy": false - } - ] -} diff --git a/addons/hive-bridge/src/test/resources/json/hs2-create-process-v2.json b/addons/hive-bridge/src/test/resources/json/hs2-create-process-v2.json deleted file mode 100644 index 9291cde24fe..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-create-process-v2.json +++ /dev/null @@ -1,141 +0,0 @@ -{ - "referredEntities": {}, - "entities": [ - { - "typeName": "hive_table_ddl", - "attributes": { - "serviceType": "hive", - "qualifiedName": "cadb202.vw202@primary:1616604468798", - "execTime": 1616604468798, - "queryText": "create table vw202 as select * from hh202", - "name": "create table vw202 as select * from hh202", - "userName": "hive" - }, - "guid": "-44808597128613", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb202.vw202@primary" - }, - "relationshipType": "hive_table_ddl_queries" - } - }, - "proxy": false - }, - { - "typeName": "hive_process", - "attributes": { - "recentQueries": [ - "create table vw202 as select * from hh202" - ], - "qualifiedName": "cadb202.vw202@primary:1616604471000", - "clusterName": "primary", - "name": "cadb202.vw202@primary:1616604471000", - "queryText": "", - "operationType": "CREATETABLE_AS_SELECT", - "startTime": 1616604475518, - "queryPlan": "Not Supported", - "endTime": 1616604475518, - "userName": "", - "queryId": "" - }, - "guid": "-44808597128614", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "outputs": [ - { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb202.vw202@primary" - }, - "relationshipType": "process_dataset_outputs" - } - ], - "inputs": [ - { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb202.hh202@primary" - }, - "relationshipType": "dataset_process_inputs" - } - ] - }, - "proxy": false - }, - { - "typeName": "hive_process_execution", - "attributes": { - "hostName": "21806.local", - "qualifiedName": "cadb202.vw202@primary:1616604471000:1616604468798:1616604475518", - "name": "cadb202.vw202@primary:1616604471000:1616604468798:1616604475518", - "queryText": "create table vw202 as select * from hh202", - "startTime": 1616604468798, - "queryPlan": "Not Supported", - "endTime": 1616604475518, - "userName": "hive", - "queryId": "hive_20210324094633_2144da6f-70ac-476e-aeec-0e758cdf1fa6" - }, - "guid": "-44808597128615", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "process": { - "guid": "-44808597128614", - "typeName": "hive_process", - "relationshipType": "hive_process_process_executions" - } - }, - "proxy": false - }, - { - "typeName": "hive_column_lineage", - "attributes": { - "expression": null, - "qualifiedName": "cadb202.vw202@primary:1616604471000:col202", - "name": "cadb202.vw202@primary:1616604471000:col202", - "depenendencyType": "SIMPLE" - }, - "guid": "-44808597128616", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "outputs": [ - { - "typeName": "hive_column", - "uniqueAttributes": { - "qualifiedName": "cadb202.vw202.col202@primary" - }, - "relationshipType": "process_dataset_outputs" - } - ], - "inputs": [ - { - "typeName": "hive_column", - "uniqueAttributes": { - "qualifiedName": "cadb202.hh202.col202@primary" - }, - "relationshipType": "dataset_process_inputs" - } - ], - "query": { - "guid": "-44808597128614", - "typeName": "hive_process", - "uniqueAttributes": { - "qualifiedName": "cadb202.vw202@primary:1616604471000" - }, - "relationshipType": "hive_process_column_lineage" - } - }, - "proxy": false - } - ] -} \ No newline at end of file diff --git a/addons/hive-bridge/src/test/resources/json/hs2-create-process.json b/addons/hive-bridge/src/test/resources/json/hs2-create-process.json deleted file mode 100644 index 1bbd95a995e..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-create-process.json +++ /dev/null @@ -1,283 +0,0 @@ -{ - "referredEntities": { - "-44808597128606": { - "typeName": "hive_db", - "attributes": { - "owner": "hive", - "ownerType": "USER", - "qualifiedName": "cadb202@primary", - "clusterName": "primary", - "name": "cadb202", - "location": "file:/Users/hive/Apache/atlas-wip/addons/hive-bridge/target/metastore/cadb202.db", - "parameters": {} - }, - "guid": "-44808597128606", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "proxy": false - }, - "-44808597128612": { - "typeName": "hive_column", - "attributes": { - "owner": "hive", - "qualifiedName": "cadb202.vw202.col202@primary", - "name": "col202", - "comment": null, - "position": 0, - "type": "string" - }, - "guid": "-44808597128612", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "guid": "-44808597128610", - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb202.vw202@primary" - }, - "relationshipType": "hive_table_columns" - } - }, - "proxy": false - }, - "-44808597128611": { - "typeName": "hive_storagedesc", - "attributes": { - "qualifiedName": "cadb202.vw202@primary_storage", - "storedAsSubDirectories": false, - "location": "file:/Users/hive/Apache/atlas-wip/addons/hive-bridge/target/metastore/cadb202.db/vw202", - "compressed": false, - "inputFormat": "org.apache.hadoop.mapred.TextInputFormat", - "parameters": {}, - "outputFormat": "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat", - "serdeInfo": { - "typeName": "hive_serde", - "attributes": { - "serializationLib": "org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe", - "name": null, - "parameters": { - "serialization.format": "1" - } - } - }, - "numBuckets": -1 - }, - "guid": "-44808597128611", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "guid": "-44808597128610", - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb202.vw202@primary" - }, - "relationshipType": "hive_table_storagedesc" - } - }, - "proxy": false - }, - "-44808597128610": { - "typeName": "hive_table", - "attributes": { - "owner": "hive", - "tableType": "MANAGED_TABLE", - "temporary": false, - "lastAccessTime": 1616604471000, - "createTime": 1616604471000, - "qualifiedName": "cadb202.vw202@primary", - "name": "vw202", - "comment": null, - "parameters": { - "totalSize": "0", - "numRows": "0", - "rawDataSize": "0", - "COLUMN_STATS_ACCURATE": "{\"BASIC_STATS\":\"true\"}", - "numFiles": "0", - "transient_lastDdlTime": "1616604472", - "bucketing_version": "2" - }, - "retention": 0 - }, - "guid": "-44808597128610", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "sd": { - "guid": "-44808597128611", - "typeName": "hive_storagedesc", - "uniqueAttributes": { - "qualifiedName": "cadb202.vw202@primary_storage" - }, - "relationshipType": "hive_table_storagedesc" - }, - "columns": [ - { - "guid": "-44808597128612", - "typeName": "hive_column", - "uniqueAttributes": { - "qualifiedName": "cadb202.vw202.col202@primary" - }, - "relationshipType": "hive_table_columns" - } - ], - "partitionKeys": [], - "db": { - "guid": "-44808597128606", - "typeName": "hive_db", - "uniqueAttributes": { - "qualifiedName": "cadb202@primary" - }, - "relationshipType": "hive_table_db" - } - }, - "proxy": false - } - }, - "entities": [ - { - "typeName": "hive_table_ddl", - "attributes": { - "serviceType": "hive", - "qualifiedName": "cadb202.vw202@primary:1616604468798", - "execTime": 1616604468798, - "queryText": "create table vw202 as select * from hh202", - "name": "create table vw202 as select * from hh202", - "userName": "hive" - }, - "guid": "-44808597128613", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "guid": "-44808597128610", - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb202.vw202@primary" - }, - "relationshipType": "hive_table_ddl_queries" - } - }, - "proxy": false - }, - { - "typeName": "hive_process", - "attributes": { - "recentQueries": [ - "create table vw202 as select * from hh202" - ], - "qualifiedName": "cadb202.vw202@primary:1616604471000", - "clusterName": "primary", - "name": "cadb202.vw202@primary:1616604471000", - "queryText": "", - "operationType": "CREATETABLE_AS_SELECT", - "startTime": 1616604475518, - "queryPlan": "Not Supported", - "endTime": 1616604475518, - "userName": "", - "queryId": "" - }, - "guid": "-44808597128614", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "outputs": [ - { - "guid": "-44808597128610", - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb202.vw202@primary" - }, - "relationshipType": "process_dataset_outputs" - } - ], - "inputs": [ - { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb202.hh202@primary" - }, - "relationshipType": "dataset_process_inputs" - } - ] - }, - "proxy": false - }, - { - "typeName": "hive_process_execution", - "attributes": { - "hostName": "21806.local", - "qualifiedName": "cadb202.vw202@primary:1616604471000:1616604468798:1616604475518", - "name": "cadb202.vw202@primary:1616604471000:1616604468798:1616604475518", - "queryText": "create table vw202 as select * from hh202", - "startTime": 1616604468798, - "queryPlan": "Not Supported", - "endTime": 1616604475518, - "userName": "hive", - "queryId": "hive_20210324094633_2144da6f-70ac-476e-aeec-0e758cdf1fa6" - }, - "guid": "-44808597128615", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "process": { - "guid": "-44808597128614", - "typeName": "hive_process", - "relationshipType": "hive_process_process_executions" - } - }, - "proxy": false - }, - { - "typeName": "hive_column_lineage", - "attributes": { - "expression": null, - "qualifiedName": "cadb202.vw202@primary:1616604471000:col202", - "name": "cadb202.vw202@primary:1616604471000:col202", - "depenendencyType": "SIMPLE" - }, - "guid": "-44808597128616", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "outputs": [ - { - "guid": "-44808597128612", - "typeName": "hive_column", - "uniqueAttributes": { - "qualifiedName": "cadb202.vw202.col202@primary" - }, - "relationshipType": "process_dataset_outputs" - } - ], - "inputs": [ - { - "typeName": "hive_column", - "uniqueAttributes": { - "qualifiedName": "cadb202.hh202.col202@primary" - }, - "relationshipType": "dataset_process_inputs" - } - ], - "query": { - "guid": "-44808597128614", - "typeName": "hive_process", - "uniqueAttributes": { - "qualifiedName": "cadb202.vw202@primary:1616604471000" - }, - "relationshipType": "hive_process_column_lineage" - } - }, - "proxy": false - } - ] -} \ No newline at end of file diff --git a/addons/hive-bridge/src/test/resources/json/hs2-create-table-v2.json b/addons/hive-bridge/src/test/resources/json/hs2-create-table-v2.json deleted file mode 100644 index ebf9e51fd48..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-create-table-v2.json +++ /dev/null @@ -1,115 +0,0 @@ -{ - "referredEntities": { - "-14529329955589455": { - "typeName": "hdfs_path", - "attributes": { - "path": "hdfs://ve0126.halxg.cloudera.com:8020/tmp/external/hh6.csv", - "qualifiedName": "hdfs://ve0126.halxg.cloudera.com:8020/tmp/external/hh6.csv@cm", - "clusterName": "cm", - "name": "/tmp/external/hh6.csv" - }, - "guid": "-14529329955589455", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "proxy": false - } - }, - "entities": [ - { - "typeName": "hive_process", - "attributes": { - "recentQueries": [ - "create external table hh6(col1 int) location '/tmp/external/hh6.csv'" - ], - "qualifiedName": "cadb02.hh6@cm:1616450674000", - "clusterName": "cm", - "name": "cadb02.hh6@cm:1616450674000", - "queryText": "", - "operationType": "CREATETABLE", - "startTime": 1616450674217, - "queryPlan": "Not Supported", - "endTime": 1616450674217, - "userName": "", - "queryId": "" - }, - "guid": "-14529329955589456", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "outputs": [ - { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6@cm" - }, - "relationshipType": "process_dataset_outputs" - } - ], - "inputs": [ - { - "guid": "-14529329955589455", - "typeName": "hdfs_path", - "uniqueAttributes": { - "qualifiedName": "hdfs://ve0126.halxg.cloudera.com:8020/tmp/external/hh6.csv@cm" - }, - "relationshipType": "dataset_process_inputs" - } - ] - }, - "proxy": false - }, - { - "typeName": "hive_process_execution", - "attributes": { - "hostName": "ve0126.halxg.cloudera.com", - "qualifiedName": "cadb02.hh6@cm:1616450674000:1616450673854:1616450674217", - "name": "cadb02.hh6@cm:1616450674000:1616450673854:1616450674217", - "queryText": "create external table hh6(col1 int) location '/tmp/external/hh6.csv'", - "startTime": 1616450673854, - "queryPlan": "Not Supported", - "endTime": 1616450674217, - "userName": "hive", - "queryId": "hive_20210322150433_52b16d58-6a44-49e2-afe4-4bb1a5bb7484" - }, - "guid": "-14529329955589457", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "process": { - "guid": "-14529329955589456", - "typeName": "hive_process", - "relationshipType": "hive_process_process_executions" - } - }, - "proxy": false - }, - { - "typeName": "hive_table_ddl", - "attributes": { - "serviceType": "hive", - "qualifiedName": "cadb02.hh6@cm:1616450673854", - "execTime": 1616450673854, - "queryText": "create external table hh6(col1 int) location '/tmp/external/hh6.csv'", - "name": "create external table hh6(col1 int) location '/tmp/external/hh6.csv'", - "userName": "hive" - }, - "guid": "-14529329955589458", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6@cm" - }, - "relationshipType": "hive_table_ddl_queries" - } - }, - "proxy": false - } - ] -} \ No newline at end of file diff --git a/addons/hive-bridge/src/test/resources/json/hs2-create-table.json b/addons/hive-bridge/src/test/resources/json/hs2-create-table.json deleted file mode 100644 index 4e13ed1526c..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-create-table.json +++ /dev/null @@ -1,255 +0,0 @@ -{ - "referredEntities": { - "-14529329955589453": { - "typeName": "hive_storagedesc", - "attributes": { - "qualifiedName": "cadb02.hh6@cm_storage", - "storedAsSubDirectories": false, - "location": "hdfs://ve0126.halxg.cloudera.com:8020/tmp/external/hh6.csv", - "compressed": false, - "inputFormat": "org.apache.hadoop.mapred.TextInputFormat", - "parameters": {}, - "outputFormat": "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat", - "serdeInfo": { - "typeName": "hive_serde", - "attributes": { - "serializationLib": "org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe", - "name": null, - "parameters": { - "serialization.format": "1" - } - } - }, - "numBuckets": -1 - }, - "guid": "-14529329955589453", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "guid": "-14529329955589452", - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6@cm" - }, - "relationshipType": "hive_table_storagedesc" - } - }, - "proxy": false - }, - "-14529329955589451": { - "typeName": "hive_db", - "attributes": { - "owner": "hive", - "ownerType": "USER", - "managedLocation": null, - "qualifiedName": "cadb02@cm", - "clusterName": "cm", - "name": "cadb02", - "location": "hdfs://ve0126.halxg.cloudera.com:8020/warehouse/tablespace/external/hive/cadb02.db", - "parameters": {} - }, - "guid": "-14529329955589451", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "proxy": false - }, - "-14529329955589455": { - "typeName": "hdfs_path", - "attributes": { - "path": "hdfs://ve0126.halxg.cloudera.com:8020/tmp/external/hh6.csv", - "qualifiedName": "hdfs://ve0126.halxg.cloudera.com:8020/tmp/external/hh6.csv@cm", - "clusterName": "cm", - "name": "/tmp/external/hh6.csv" - }, - "guid": "-14529329955589455", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "proxy": false - }, - "-14529329955589454": { - "typeName": "hive_column", - "attributes": { - "owner": "hive", - "qualifiedName": "cadb02.hh6.col1@cm", - "name": "col1", - "comment": null, - "position": 0, - "type": "int" - }, - "guid": "-14529329955589454", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "guid": "-14529329955589452", - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6@cm" - }, - "relationshipType": "hive_table_columns" - } - }, - "proxy": false - } - }, - "entities": [ - { - "typeName": "hive_table", - "attributes": { - "owner": "hive", - "tableType": "EXTERNAL_TABLE", - "temporary": false, - "lastAccessTime": 1616450674000, - "createTime": 1616450674000, - "qualifiedName": "cadb02.hh6@cm", - "name": "hh6", - "comment": null, - "parameters": { - "totalSize": "0", - "EXTERNAL": "TRUE", - "numFiles": "0", - "transient_lastDdlTime": "1616450674", - "bucketing_version": "2", - "numFilesErasureCoded": "0" - }, - "retention": 0 - }, - "guid": "-14529329955589452", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "sd": { - "guid": "-14529329955589453", - "typeName": "hive_storagedesc", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6@cm_storage" - }, - "relationshipType": "hive_table_storagedesc" - }, - "columns": [ - { - "guid": "-14529329955589454", - "typeName": "hive_column", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6.col1@cm" - }, - "relationshipType": "hive_table_columns" - } - ], - "partitionKeys": [], - "db": { - "guid": "-14529329955589451", - "typeName": "hive_db", - "uniqueAttributes": { - "qualifiedName": "cadb02@cm" - }, - "relationshipType": "hive_table_db" - } - }, - "proxy": false - }, - { - "typeName": "hive_process", - "attributes": { - "recentQueries": [ - "create external table hh6(col1 int) location '/tmp/external/hh6.csv'" - ], - "qualifiedName": "cadb02.hh6@cm:1616450674000", - "clusterName": "cm", - "name": "cadb02.hh6@cm:1616450674000", - "queryText": "", - "operationType": "CREATETABLE", - "startTime": 1616450674217, - "queryPlan": "Not Supported", - "endTime": 1616450674217, - "userName": "", - "queryId": "" - }, - "guid": "-14529329955589456", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "outputs": [ - { - "guid": "-14529329955589452", - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6@cm" - }, - "relationshipType": "process_dataset_outputs" - } - ], - "inputs": [ - { - "guid": "-14529329955589455", - "typeName": "hdfs_path", - "uniqueAttributes": { - "qualifiedName": "hdfs://ve0126.halxg.cloudera.com:8020/tmp/external/hh6.csv@cm" - }, - "relationshipType": "dataset_process_inputs" - } - ] - }, - "proxy": false - }, - { - "typeName": "hive_process_execution", - "attributes": { - "hostName": "ve0126.halxg.cloudera.com", - "qualifiedName": "cadb02.hh6@cm:1616450674000:1616450673854:1616450674217", - "name": "cadb02.hh6@cm:1616450674000:1616450673854:1616450674217", - "queryText": "create external table hh6(col1 int) location '/tmp/external/hh6.csv'", - "startTime": 1616450673854, - "queryPlan": "Not Supported", - "endTime": 1616450674217, - "userName": "hive", - "queryId": "hive_20210322150433_52b16d58-6a44-49e2-afe4-4bb1a5bb7484" - }, - "guid": "-14529329955589457", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "process": { - "guid": "-14529329955589456", - "typeName": "hive_process", - "relationshipType": "hive_process_process_executions" - } - }, - "proxy": false - }, - { - "typeName": "hive_table_ddl", - "attributes": { - "serviceType": "hive", - "qualifiedName": "cadb02.hh6@cm:1616450673854", - "execTime": 1616450673854, - "queryText": "create external table hh6(col1 int) location '/tmp/external/hh6.csv'", - "name": "create external table hh6(col1 int) location '/tmp/external/hh6.csv'", - "userName": "hive" - }, - "guid": "-14529329955589458", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "guid": "-14529329955589452", - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6@cm" - }, - "relationshipType": "hive_table_ddl_queries" - } - }, - "proxy": false - } - ] -} \ No newline at end of file diff --git a/addons/hive-bridge/src/test/resources/json/hs2-drop-db-v2.json b/addons/hive-bridge/src/test/resources/json/hs2-drop-db-v2.json deleted file mode 100644 index 76860cea9a5..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-drop-db-v2.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "entities": [ - ] -} diff --git a/addons/hive-bridge/src/test/resources/json/hs2-drop-db.json b/addons/hive-bridge/src/test/resources/json/hs2-drop-db.json deleted file mode 100644 index 429f95fb38e..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-drop-db.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "entities": [ - { - "typeName": "hive_db", - "uniqueAttributes": { - "qualifiedName": "cadb02@cm" - } - } - ] -} diff --git a/addons/hive-bridge/src/test/resources/json/hs2-drop-table-v2.json b/addons/hive-bridge/src/test/resources/json/hs2-drop-table-v2.json deleted file mode 100644 index 0637a088a01..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-drop-table-v2.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/addons/hive-bridge/src/test/resources/json/hs2-drop-table.json b/addons/hive-bridge/src/test/resources/json/hs2-drop-table.json deleted file mode 100644 index ed620324939..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-drop-table.json +++ /dev/null @@ -1,50 +0,0 @@ -[ - { - "type": "ENTITY_DELETE_V2", - "user": "hive", - "entities": [ - { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed@cm" - } - } - ] - }, - { - "type": "ENTITY_DELETE_V2", - "user": "hive", - "entities": [ - { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed_view2@cm" - } - } - ] - }, - { - "type": "ENTITY_DELETE_V2", - "user": "hive", - "entities": [ - { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.cc1@cm" - } - } - ] - }, - { - "type": "ENTITY_DELETE_V2", - "user": "hive", - "entities": [ - { - "typeName": "hive_db", - "uniqueAttributes": { - "qualifiedName": "cadb02@cm" - } - } - ] - } -] diff --git a/addons/hive-bridge/src/test/resources/json/hs2-load-inpath-v2.json b/addons/hive-bridge/src/test/resources/json/hs2-load-inpath-v2.json deleted file mode 100644 index 499a9c2e872..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-load-inpath-v2.json +++ /dev/null @@ -1,96 +0,0 @@ -[ - { - "type": "ENTITY_CREATE_V2", - "user": "hive", - "entities": { - "referredEntities": { - "-98504074851374": { - "typeName": "hdfs_path", - "attributes": { - "path": "file:/Users/hive/Apache/atlas-wip/addons/hive-bridge/target/load-data-thi5jt1lgj", - "qualifiedName": "file:/users/hive/apache/atlas-wip/addons/hive-bridge/target/load-data-thi5jt1lgj", - "clusterName": "primary", - "name": "/Users/hive/Apache/atlas-wip/addons/hive-bridge/target/load-data-thi5jt1lgj" - }, - "guid": "-98504074851374", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "proxy": false - } - }, - "entities": [ - { - "typeName": "hive_process", - "attributes": { - "recentQueries": [ - "load data local inpath 'file:///users/hive/apache/atlas-wip/addons/hive-bridge/target/load-data-thi5jt1lgj' into table table_nrx8uoggc0 partition(dt = '2015-01-01')" - ], - "qualifiedName": "LOAD->:default.table_nrx8uoggc0@primary:1622738598000", - "clusterName": "primary", - "name": "LOAD->:default.table_nrx8uoggc0@primary:1622738598000", - "queryText": "", - "operationType": "LOAD", - "startTime": 1622738659471, - "queryPlan": "Not Supported", - "endTime": 1622738659471, - "userName": "", - "queryId": "" - }, - "guid": "-98504074851381", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "outputs": [ - { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "default.table_nrx8uoggc0@primary" - }, - "relationshipType": "process_dataset_outputs" - } - ], - "inputs": [ - { - "guid": "-98504074851374", - "typeName": "hdfs_path", - "uniqueAttributes": { - "qualifiedName": "file:/users/hive/apache/atlas-wip/addons/hive-bridge/target/load-data-thi5jt1lgj" - }, - "relationshipType": "dataset_process_inputs" - } - ] - }, - "proxy": false - }, - { - "typeName": "hive_process_execution", - "attributes": { - "hostName": "21806.local", - "qualifiedName": "LOAD->:default.table_nrx8uoggc0@primary:1622738598000:1622738658982:1622738659471", - "name": "LOAD->:default.table_nrx8uoggc0@primary:1622738598000:1622738658982:1622738659471", - "queryText": "load data local inpath 'file:///users/hive/apache/atlas-wip/addons/hive-bridge/target/load-data-thi5jt1lgj' into table table_nrx8uoggc0 partition(dt = '2015-01-01')", - "startTime": 1622738658982, - "queryPlan": "Not Supported", - "endTime": 1622738659471, - "userName": "hive", - "queryId": "hive_20210603094308_ef789483-7de1-462b-ac74-bb0ebe7aeedf" - }, - "guid": "-98504074851382", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "process": { - "guid": "-98504074851381", - "typeName": "hive_process", - "relationshipType": "hive_process_process_executions" - } - }, - "proxy": false - } - ] - } - } -] \ No newline at end of file diff --git a/addons/hive-bridge/src/test/resources/json/hs2-load-inpath.json b/addons/hive-bridge/src/test/resources/json/hs2-load-inpath.json deleted file mode 100644 index 499a9c2e872..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-load-inpath.json +++ /dev/null @@ -1,96 +0,0 @@ -[ - { - "type": "ENTITY_CREATE_V2", - "user": "hive", - "entities": { - "referredEntities": { - "-98504074851374": { - "typeName": "hdfs_path", - "attributes": { - "path": "file:/Users/hive/Apache/atlas-wip/addons/hive-bridge/target/load-data-thi5jt1lgj", - "qualifiedName": "file:/users/hive/apache/atlas-wip/addons/hive-bridge/target/load-data-thi5jt1lgj", - "clusterName": "primary", - "name": "/Users/hive/Apache/atlas-wip/addons/hive-bridge/target/load-data-thi5jt1lgj" - }, - "guid": "-98504074851374", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "proxy": false - } - }, - "entities": [ - { - "typeName": "hive_process", - "attributes": { - "recentQueries": [ - "load data local inpath 'file:///users/hive/apache/atlas-wip/addons/hive-bridge/target/load-data-thi5jt1lgj' into table table_nrx8uoggc0 partition(dt = '2015-01-01')" - ], - "qualifiedName": "LOAD->:default.table_nrx8uoggc0@primary:1622738598000", - "clusterName": "primary", - "name": "LOAD->:default.table_nrx8uoggc0@primary:1622738598000", - "queryText": "", - "operationType": "LOAD", - "startTime": 1622738659471, - "queryPlan": "Not Supported", - "endTime": 1622738659471, - "userName": "", - "queryId": "" - }, - "guid": "-98504074851381", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "outputs": [ - { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "default.table_nrx8uoggc0@primary" - }, - "relationshipType": "process_dataset_outputs" - } - ], - "inputs": [ - { - "guid": "-98504074851374", - "typeName": "hdfs_path", - "uniqueAttributes": { - "qualifiedName": "file:/users/hive/apache/atlas-wip/addons/hive-bridge/target/load-data-thi5jt1lgj" - }, - "relationshipType": "dataset_process_inputs" - } - ] - }, - "proxy": false - }, - { - "typeName": "hive_process_execution", - "attributes": { - "hostName": "21806.local", - "qualifiedName": "LOAD->:default.table_nrx8uoggc0@primary:1622738598000:1622738658982:1622738659471", - "name": "LOAD->:default.table_nrx8uoggc0@primary:1622738598000:1622738658982:1622738659471", - "queryText": "load data local inpath 'file:///users/hive/apache/atlas-wip/addons/hive-bridge/target/load-data-thi5jt1lgj' into table table_nrx8uoggc0 partition(dt = '2015-01-01')", - "startTime": 1622738658982, - "queryPlan": "Not Supported", - "endTime": 1622738659471, - "userName": "hive", - "queryId": "hive_20210603094308_ef789483-7de1-462b-ac74-bb0ebe7aeedf" - }, - "guid": "-98504074851382", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "process": { - "guid": "-98504074851381", - "typeName": "hive_process", - "relationshipType": "hive_process_process_executions" - } - }, - "proxy": false - } - ] - } - } -] \ No newline at end of file diff --git a/addons/hive-bridge/src/test/resources/json/hs2-table-rename-v2.json b/addons/hive-bridge/src/test/resources/json/hs2-table-rename-v2.json deleted file mode 100644 index f133e7ffbf9..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-table-rename-v2.json +++ /dev/null @@ -1,35 +0,0 @@ -[ - { - "type": "ENTITY_CREATE_V2", - "user": "hive", - "entities": { - "entities": [ - { - "typeName": "hive_table_ddl", - "attributes": { - "serviceType": "hive", - "qualifiedName": "cadb02.hh6_renamed@cm:1616450674247", - "execTime": 1616450674247, - "queryText": "ALTER TABLE hh6 RENAME TO hh6_renamed", - "name": "ALTER TABLE hh6 RENAME TO hh6_renamed", - "userName": "hive" - }, - "guid": "-14529329955589467", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed@cm" - }, - "relationshipType": "hive_table_ddl_queries" - } - }, - "proxy": false - } - ] - } - } -] diff --git a/addons/hive-bridge/src/test/resources/json/hs2-table-rename.json b/addons/hive-bridge/src/test/resources/json/hs2-table-rename.json deleted file mode 100644 index 6b8094dc83d..00000000000 --- a/addons/hive-bridge/src/test/resources/json/hs2-table-rename.json +++ /dev/null @@ -1,276 +0,0 @@ -[ - { - "type": "ENTITY_PARTIAL_UPDATE_V2", - "user": "hive", - "entityId": { - "typeName": "hive_column", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6.col1@cm" - } - }, - "entity": { - "entity": { - "typeName": "hive_column", - "attributes": { - "qualifiedName": "cadb02.hh6_renamed.col1@cm" - }, - "guid": "-14529329955589466", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "proxy": false - } - } - }, - { - "type": "ENTITY_PARTIAL_UPDATE_V2", - "user": "hive", - "entityId": { - "typeName": "hive_storagedesc", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6@cm_storage" - } - }, - "entity": { - "entity": { - "typeName": "hive_storagedesc", - "attributes": { - "qualifiedName": "cadb02.hh6_renamed@cm_storage", - "storedAsSubDirectories": false, - "location": "hdfs://ve0126.halxg.cloudera.com:8020/tmp/external/hh6.csv", - "compressed": false, - "inputFormat": "org.apache.hadoop.mapred.TextInputFormat", - "parameters": {}, - "outputFormat": "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat", - "serdeInfo": { - "typeName": "hive_serde", - "attributes": { - "serializationLib": "org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe", - "name": null, - "parameters": { - "serialization.format": "1" - } - } - }, - "numBuckets": -1 - }, - "guid": "-14529329955589464", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "proxy": false - } - } - }, - { - "type": "ENTITY_PARTIAL_UPDATE_V2", - "user": "hive", - "entityId": { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6@cm" - } - }, - "entity": { - "entity": { - "typeName": "hive_table", - "attributes": { - "owner": "hive", - "tableType": "EXTERNAL_TABLE", - "temporary": false, - "lastAccessTime": 1616450674000, - "aliases": [ - "hh6" - ], - "createTime": 1616450674000, - "qualifiedName": "cadb02.hh6_renamed@cm", - "name": "hh6_renamed", - "comment": null, - "parameters": { - "last_modified_time": "1616450674", - "totalSize": "0", - "EXTERNAL": "TRUE", - "numFiles": "0", - "transient_lastDdlTime": "1616450674", - "bucketing_version": "2", - "last_modified_by": "hive", - "numFilesErasureCoded": "0" - }, - "retention": 0 - }, - "guid": "-14529329955589463", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "proxy": false - } - } - }, - { - "type": "ENTITY_FULL_UPDATE_V2", - "user": "hive", - "entities": { - "referredEntities": { - "-14529329955589464": { - "typeName": "hive_storagedesc", - "attributes": { - "qualifiedName": "cadb02.hh6_renamed@cm_storage", - "storedAsSubDirectories": false, - "location": "hdfs://ve0126.halxg.cloudera.com:8020/tmp/external/hh6.csv", - "compressed": false, - "inputFormat": "org.apache.hadoop.mapred.TextInputFormat", - "parameters": {}, - "outputFormat": "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat", - "serdeInfo": { - "typeName": "hive_serde", - "attributes": { - "serializationLib": "org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe", - "name": null, - "parameters": { - "serialization.format": "1" - } - } - }, - "numBuckets": -1 - }, - "guid": "-14529329955589464", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "guid": "-14529329955589463", - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed@cm" - }, - "relationshipType": "hive_table_storagedesc" - } - }, - "proxy": false - }, - "-14529329955589465": { - "typeName": "hive_column", - "attributes": { - "owner": "hive", - "qualifiedName": "cadb02.hh6_renamed.col1@cm", - "name": "col1", - "comment": null, - "position": 0, - "type": "int" - }, - "guid": "-14529329955589465", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "guid": "-14529329955589463", - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed@cm" - }, - "relationshipType": "hive_table_columns" - } - }, - "proxy": false - } - }, - "entities": [ - { - "typeName": "hive_table", - "attributes": { - "owner": "hive", - "tableType": "EXTERNAL_TABLE", - "temporary": false, - "lastAccessTime": 1616450674000, - "aliases": [ - "hh6" - ], - "createTime": 1616450674000, - "qualifiedName": "cadb02.hh6_renamed@cm", - "name": "hh6_renamed", - "comment": null, - "parameters": { - "last_modified_time": "1616450674", - "totalSize": "0", - "EXTERNAL": "TRUE", - "numFiles": "0", - "transient_lastDdlTime": "1616450674", - "bucketing_version": "2", - "last_modified_by": "hive", - "numFilesErasureCoded": "0" - }, - "retention": 0 - }, - "guid": "-14529329955589463", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "sd": { - "guid": "-14529329955589464", - "typeName": "hive_storagedesc", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed@cm_storage" - }, - "relationshipType": "hive_table_storagedesc" - }, - "columns": [ - { - "guid": "-14529329955589465", - "typeName": "hive_column", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed.col1@cm" - }, - "relationshipType": "hive_table_columns" - } - ], - "partitionKeys": [], - "db": { - "typeName": "hive_db", - "uniqueAttributes": { - "qualifiedName": "cadb02@cm" - }, - "relationshipType": "hive_table_db" - } - }, - "proxy": false - } - ] - } - }, - { - "type": "ENTITY_CREATE_V2", - "user": "hive", - "entities": { - "entities": [ - { - "typeName": "hive_table_ddl", - "attributes": { - "serviceType": "hive", - "qualifiedName": "cadb02.hh6_renamed@cm:1616450674247", - "execTime": 1616450674247, - "queryText": "ALTER TABLE hh6 RENAME TO hh6_renamed", - "name": "ALTER TABLE hh6 RENAME TO hh6_renamed", - "userName": "hive" - }, - "guid": "-14529329955589467", - "isIncomplete": false, - "provenanceType": 0, - "version": 0, - "relationshipAttributes": { - "table": { - "typeName": "hive_table", - "uniqueAttributes": { - "qualifiedName": "cadb02.hh6_renamed@cm" - }, - "relationshipType": "hive_table_ddl_queries" - } - }, - "proxy": false - } - ] - } - } -] diff --git a/addons/hive-bridge/src/test/resources/users-credentials.properties b/addons/hive-bridge/src/test/resources/users-credentials.properties deleted file mode 100644 index 5046dbaf646..00000000000 --- a/addons/hive-bridge/src/test/resources/users-credentials.properties +++ /dev/null @@ -1,3 +0,0 @@ -#username=group::sha256-password -admin=ADMIN::a4a88c0872bf652bb9ed803ece5fd6e82354838a9bf59ab4babb1dab322154e1 -rangertagsync=RANGER_TAG_SYNC::0afe7a1968b07d4c3ff4ed8c2d809a32ffea706c66cd795ead9048e81cfaf034 diff --git a/addons/impala-bridge-shim/pom.xml b/addons/impala-bridge-shim/pom.xml deleted file mode 100644 index 079eb850068..00000000000 --- a/addons/impala-bridge-shim/pom.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - impala-bridge-shim - Apache Atlas Impala Bridge Shim Module - Apache Atlas Impala Bridge Shim - jar - - - - org.apache.atlas - atlas-plugin-classloader - - - org.apache.atlas - impala-hook-api - - - \ No newline at end of file diff --git a/addons/impala-bridge-shim/src/main/java/org/apache/atlas/impala/hook/ImpalaLineageHook.java b/addons/impala-bridge-shim/src/main/java/org/apache/atlas/impala/hook/ImpalaLineageHook.java deleted file mode 100644 index 34e6dcf4edc..00000000000 --- a/addons/impala-bridge-shim/src/main/java/org/apache/atlas/impala/hook/ImpalaLineageHook.java +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.hook; - -import org.apache.atlas.plugin.classloader.AtlasPluginClassLoader; -import org.apache.impala.hooks.QueryCompleteContext; -import org.apache.impala.hooks.QueryEventHook; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class is used to convert lineage records from Impala to lineage notifications and - * send them to Atlas. - */ -public class ImpalaLineageHook implements QueryEventHook { - private static final Logger LOG = LoggerFactory.getLogger(ImpalaLineageHook.class); - - private static final String ATLAS_PLUGIN_TYPE_IMPALA = "impala"; - private static final String ATLAS_IMPALA_LINEAGE_HOOK_IMPL_CLASSNAME = - "org.apache.atlas.impala.hook.ImpalaHook"; - - private AtlasPluginClassLoader atlasPluginClassLoader = null; - private QueryEventHook impalaLineageHookImpl; - - public ImpalaLineageHook() { - } - - /** - * Execute Impala hook - */ - public void onQueryComplete(QueryCompleteContext context) { - LOG.debug("==> ImpalaLineageHook.onQueryComplete()"); - - try { - activatePluginClassLoader(); - impalaLineageHookImpl.onQueryComplete(context); - } catch (Exception ex) { - String errorMessage = String.format("Error in processing impala lineage: {}", context.getLineageGraph()); - LOG.error(errorMessage, ex); - } finally { - deactivatePluginClassLoader(); - } - - LOG.debug("<== ImpalaLineageHook.onQueryComplete()"); - } - - /** - * Initialization of Impala hook - */ - public void onImpalaStartup() { - LOG.debug("==> ImpalaLineageHook.onImpalaStartup()"); - - try { - atlasPluginClassLoader = AtlasPluginClassLoader.getInstance(ATLAS_PLUGIN_TYPE_IMPALA, this.getClass()); - - @SuppressWarnings("unchecked") - Class cls = (Class) Class - .forName(ATLAS_IMPALA_LINEAGE_HOOK_IMPL_CLASSNAME, true, atlasPluginClassLoader); - - activatePluginClassLoader(); - - impalaLineageHookImpl = cls.newInstance(); - impalaLineageHookImpl.onImpalaStartup(); - } catch (Exception excp) { - LOG.error("Error instantiating Atlas hook implementation for Impala lineage", excp); - } finally { - deactivatePluginClassLoader(); - } - - LOG.debug("<== ImpalaLineageHook.onImpalaStartup()"); - } - - private void activatePluginClassLoader() { - if (atlasPluginClassLoader != null) { - atlasPluginClassLoader.activate(); - } - } - - private void deactivatePluginClassLoader() { - if (atlasPluginClassLoader != null) { - atlasPluginClassLoader.deactivate(); - } - } -} \ No newline at end of file diff --git a/addons/impala-bridge/pom.xml b/addons/impala-bridge/pom.xml deleted file mode 100644 index 186251abe25..00000000000 --- a/addons/impala-bridge/pom.xml +++ /dev/null @@ -1,549 +0,0 @@ - - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - impala-bridge - Apache Atlas Impala Bridge Module - Apache Atlas Impala Bridge - jar - - - - - org.slf4j - slf4j-api - - - - org.slf4j - slf4j-log4j12 - - - - org.apache.atlas - atlas-notification - - - - org.apache.atlas - impala-hook-api - - - - - org.apache.atlas - atlas-client-v2 - ${project.version} - test - - - org.apache.logging.log4j - log4j-core - ${log4j2.version} - test - - - org.apache.logging.log4j - log4j-api - ${log4j2.version} - test - - - - com.sun.jersey - jersey-server - ${jersey.version} - test - - - - org.apache.atlas - hive-bridge - test - - - - org.apache.atlas - atlas-webapp - war - test - - - - org.apache.hadoop - hadoop-client - - - javax.servlet - servlet-api - - - org.eclipse.jetty - * - - - - - - org.apache.hadoop - hadoop-annotations - - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.databind.version} - - - - commons-io - commons-io - ${commons-io.version} - - - - commons-cli - commons-cli - ${commons-cli.version} - - - - commons-lang - commons-lang - ${commons-lang.version} - - - - org.testng - testng - - - - org.mockito - mockito-all - - - - org.eclipse.jetty - jetty-server - test - - - - org.apache.atlas - atlas-graphdb-impls - pom - test - - - - org.apache.atlas - atlas-intg - tests - test - - - - org.apache.atlas - atlas-repository - tests - test - - - - org.apache.hive - hive-exec - ${hive.version} - test - - - javax.servlet - * - - - - - - org.apache.hive - hive-jdbc - ${hive.version} - test - - - javax.servlet - * - - - javax.ws.rs - * - - - org.eclipse.jetty - * - - - - - - org.apache.hive - hive-cli - ${hive.version} - test - - - javax.servlet - * - - - org.eclipse.jetty.aggregate - * - - - - - - - - dist - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-hook - package - - copy - - - ${project.build.directory}/dependency/hook/impala/atlas-impala-plugin-impl - false - false - true - - - ${project.groupId} - ${project.artifactId} - ${project.version} - - - ${project.groupId} - atlas-client-common - ${project.version} - - - ${project.groupId} - atlas-client-v1 - ${project.version} - - - ${project.groupId} - atlas-client-v2 - ${project.version} - - - ${project.groupId} - atlas-intg - ${project.version} - - - ${project.groupId} - atlas-notification - ${project.version} - - - ${project.groupId} - atlas-common - ${project.version} - - - org.apache.kafka - kafka_${kafka.scala.binary.version} - ${kafka.version} - - - org.apache.kafka - kafka-clients - ${kafka.version} - - - com.sun.jersey.contribs - jersey-multipart - ${jersey.version} - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.databind.version} - - - com.fasterxml.jackson.core - jackson-core - ${jackson.version} - - - com.fasterxml.jackson.core - jackson-annotations - ${jackson.version} - - - commons-configuration - commons-configuration - ${commons-conf.version} - - - com.sun.jersey - jersey-json - ${jersey.version} - - - javax.ws.rs - jsr311-api - ${jsr.version} - - - - - - copy-hook-shim - package - - copy - - - ${project.build.directory}/dependency/hook/impala - false - false - true - - - ${project.groupId} - impala-bridge-shim - ${project.version} - - - ${project.groupId} - atlas-plugin-classloader - ${project.version} - - - - - - - - - - - - - - org.eclipse.jetty - jetty-maven-plugin - ${jetty.version} - - ${skipTests} - - - 31000 - 60000 - - ../../webapp/target/atlas-webapp-${project.version}.war - true - ../../webapp/src/main/webapp - - / - ${project.basedir}/../../webapp/src/main/webapp/WEB-INF/web.xml - - true - - true - - atlas.home - ${project.build.directory} - - - atlas.conf - ${project.build.directory}/test-classes - - - atlas.data - ${project.build.directory}/data - - - atlas.log.dir - ${project.build.directory}/logs - - - atlas.log.file - application.log - - - log4j.configuration - file:///${project.build.directory}/test-classes/atlas-log4j.xml - - - atlas.graphdb.backend - ${graphdb.backend.impl} - - - embedded.solr.directory - ${project.build.directory} - - - solr.log.dir - ${project.build.directory}/logs - - - org.eclipse.jetty.annotations.maxWait - 5000 - - - atlas-stop - 31001 - ${jetty-maven-plugin.stopWait} - ${debug.jetty.daemon} - ${project.build.testOutputDirectory} - true - jar - - - - org.apache.curator - curator-client - ${curator.version} - - - - org.apache.zookeeper - zookeeper - ${zookeeper.version} - - - - - start-jetty - pre-integration-test - - - stop - deploy-war - - - - stop-jetty - post-integration-test - - stop - - - - - - - org.apache.maven.plugins - maven-site-plugin - - - org.apache.maven.doxia - doxia-module-twiki - ${doxia.version} - - - org.apache.maven.doxia - doxia-core - ${doxia.version} - - - - - - site - - prepare-package - - - - false - false - - - - - org.codehaus.mojo - exec-maven-plugin - 1.2.1 - false - - - - - - org.apache.maven.plugins - maven-resources-plugin - - - copy-resources - validate - - copy-resources - - - ${basedir}/target/models - - - ${basedir}/../models - - 0000-Area0/0010-base_model.json - 1000-Hadoop/** - - - - - - - copy-solr-resources - validate - - copy-resources - - - ${project.build.directory}/solr - - - ${basedir}/../../test-tools/src/main/resources/solr - - - - - - - - - - diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/ImpalaLineageTool.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/ImpalaLineageTool.java deleted file mode 100644 index 6e6d6f1eeda..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/ImpalaLineageTool.java +++ /dev/null @@ -1,216 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala; - -import org.apache.atlas.impala.hook.ImpalaLineageHook; - -import java.io.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOCase; -import org.apache.commons.io.comparator.LastModifiedFileComparator; -import org.apache.commons.io.filefilter.PrefixFileFilter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Entry point of actual implementation of Impala lineage tool. It reads the lineage records in - * lineage log. It then calls instance of ImpalaLineageHook to convert lineage records to - * lineage notifications and send them to Atlas. - */ -public class ImpalaLineageTool { - private static final Logger LOG = LoggerFactory.getLogger(ImpalaLineageTool.class); - private static final String WAL_FILE_EXTENSION = ".wal"; - private static final String WAL_FILE_PREFIX = "WAL"; - private String directoryName; - private String prefix; - - public ImpalaLineageTool(String[] args) { - try { - Options options = new Options(); - options.addOption("d", "directory", true, "the lineage files' folder"); - options.addOption("p", "prefix", true, "the prefix of the lineage files"); - - CommandLine cmd = new DefaultParser().parse(options, args); - directoryName = cmd.getOptionValue("d"); - prefix = cmd.getOptionValue("p"); - } catch(ParseException e) { - LOG.warn("Failed to parse command arguments. Error: ", e.getMessage()); - printUsage(); - - throw new RuntimeException(e); - } - } - - public void run() { - ImpalaLineageHook impalaLineageHook = new ImpalaLineageHook(); - - File[] currentFiles = getCurrentFiles(); - int fileNum = currentFiles.length; - - for(int i = 0; i < fileNum; i++) { - String filename = currentFiles[i].getAbsolutePath(); - String walFilename = directoryName + WAL_FILE_PREFIX + currentFiles[i].getName() + WAL_FILE_EXTENSION; - - LOG.info("Importing: {}", filename); - importHImpalaEntities(impalaLineageHook, filename, walFilename); - - if(i != fileNum - 1) { - deleteLineageAndWal(currentFiles[i], walFilename); - } - } - LOG.info("Impala bridge processing: Done! "); - } - - public static void main(String[] args) { - if (args != null && args.length != 4) { - // The lineage file location and prefix should be input as the parameters - System.out.println("Impala bridge: wrong number of arguments. Please try again"); - printUsage(); - return; - } - - ImpalaLineageTool instance = new ImpalaLineageTool(args); - instance.run(); - } - - /** - * Delete the used lineage file and wal file - * @param currentFile The current file - * @param wal The wal file - */ - public static void deleteLineageAndWal(File currentFile, String wal) { - if(currentFile.exists() && currentFile.delete()) { - LOG.info("Lineage file {} is deleted successfully", currentFile.getPath()); - } else { - LOG.info("Failed to delete the lineage file {}", currentFile.getPath()); - } - - File file = new File(wal); - - if(file.exists() && file.delete()) { - LOG.info("Wal file {} deleted successfully", wal); - } else { - LOG.info("Failed to delete the wal file {}", wal); - } - } - - private static void printUsage() { - System.out.println(); - System.out.println(); - System.out.println("Usage: import-impala.sh [-d ] [-p ]" ); - System.out.println(" Imports specified lineage files by given directory and file prefix."); - System.out.println(); - } - - /** - * This function figures out the right lineage file path+name to process sorted by the last - * time they are modified. (old -> new) - * @return get the lineage files from given directory with given prefix. - */ - public File[] getCurrentFiles() { - try { - LOG.info("Scanning: " + directoryName); - File folder = new File(directoryName); - File[] listOfFiles = folder.listFiles((FileFilter) new PrefixFileFilter(prefix, IOCase.SENSITIVE)); - - if ((listOfFiles == null) || (listOfFiles.length == 0)) { - LOG.info("Found no lineage files."); - return new File[0]; - } - - if(listOfFiles.length > 1) { - Arrays.sort(listOfFiles, LastModifiedFileComparator.LASTMODIFIED_COMPARATOR); - } - - LOG.info("Found {} lineage files" + listOfFiles.length); - return listOfFiles; - } catch(Exception e) { - LOG.error("Import lineage file failed.", e); - } - return new File[0]; - } - - private boolean processImpalaLineageHook(ImpalaLineageHook impalaLineageHook, List lineageList) { - boolean allSucceed = true; - - // returns true if successfully sent to Atlas - for (String lineageRecord : lineageList) { - try { - impalaLineageHook.process(lineageRecord); - } catch (Exception ex) { - String errorMessage = String.format("Exception at query {} \n", lineageRecord); - LOG.error(errorMessage, ex); - - allSucceed = false; - } - } - - return allSucceed; - } - - /** - * Create a list of lineage queries based on the lineage file and the wal file - * @param name - * @param walfile - * @return - */ - public void importHImpalaEntities(ImpalaLineageHook impalaLineageHook, String name, String walfile) { - List lineageList = new ArrayList<>(); - - try { - File lineageFile = new File(name); //use current file length to minus the offset - File walFile = new File(walfile); - // if the wal file does not exist, create one with 0 byte read, else, read the number - if(!walFile.exists()) { - BufferedWriter writer = new BufferedWriter(new FileWriter(walfile)); - writer.write("0, " + name); - writer.close(); - } - - LOG.debug("Reading: " + name); - String lineageRecord = FileUtils.readFileToString(lineageFile, "UTF-8"); - - lineageList.add(lineageRecord); - - // call instance of ImpalaLineageHook to process the list of Impala lineage record - if(processImpalaLineageHook(impalaLineageHook, lineageList)) { - // write how many bytes the current file is to the wal file - FileWriter newWalFile = new FileWriter(walfile, true); - BufferedWriter newWalFileBuf = new BufferedWriter(newWalFile); - newWalFileBuf.newLine(); - newWalFileBuf.write(String.valueOf(lineageFile.length()) + "," + name); - - newWalFileBuf.close(); - newWalFile.close(); - } else { - LOG.error("Error sending some of impala lineage records to ImpalaHook"); - } - } catch (Exception e) { - LOG.error("Error in processing lineage records. Exception: " + e.getMessage()); - } - } - -} \ No newline at end of file diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/AtlasImpalaHookContext.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/AtlasImpalaHookContext.java deleted file mode 100644 index 51b2f832e77..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/AtlasImpalaHookContext.java +++ /dev/null @@ -1,213 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.hook; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import org.apache.atlas.impala.model.ImpalaOperationType; -import org.apache.atlas.impala.model.ImpalaQuery; -import org.apache.atlas.impala.model.LineageVertex; -import org.apache.atlas.impala.model.LineageVertexMetadata; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.commons.lang.StringUtils; - - -/** - * Contain the info related to an linear record from Impala - */ -public class AtlasImpalaHookContext { - public static final char QNAME_SEP_METADATA_NAMESPACE = '@'; - public static final char QNAME_SEP_ENTITY_NAME = '.'; - public static final char QNAME_SEP_PROCESS = ':'; - - private final ImpalaLineageHook hook; - private final ImpalaOperationType impalaOperation; - private final ImpalaQuery lineageQuery; - private final Map qNameEntityMap = new HashMap<>(); - - public AtlasImpalaHookContext(ImpalaLineageHook hook, ImpalaOperationType operationType, - ImpalaQuery lineageQuery) throws Exception { - this.hook = hook; - this.impalaOperation = operationType; - this.lineageQuery = lineageQuery; - - } - - public ImpalaQuery getLineageQuery() { - return lineageQuery; - } - public String getQueryStr() { return lineageQuery.getQueryText(); } - - public ImpalaOperationType getImpalaOperationType() { - return impalaOperation; - } - - public void putEntity(String qualifiedName, AtlasEntity entity) { - qNameEntityMap.put(qualifiedName, entity); - } - - public AtlasEntity getEntity(String qualifiedName) { - return qNameEntityMap.get(qualifiedName); - } - - public Collection getEntities() { return qNameEntityMap.values(); } - - public String getMetadataNamespace() { - return hook.getMetadataNamespace(); - } - - public String getHostName() { - return hook.getHostName(); - } - - public boolean isConvertHdfsPathToLowerCase() { - return hook.isConvertHdfsPathToLowerCase(); - } - - public String getQualifiedNameForDb(String dbName) { - return (dbName + QNAME_SEP_METADATA_NAMESPACE).toLowerCase() + getMetadataNamespace(); - } - - public String getQualifiedNameForTable(String fullTableName) throws IllegalArgumentException { - if (fullTableName == null) { - throw new IllegalArgumentException("fullTableName is null"); - } - - int sepPos = fullTableName.lastIndexOf(QNAME_SEP_ENTITY_NAME); - - if (!isSeparatorIndexValid(sepPos)) { - throw new IllegalArgumentException(fullTableName + " does not contain database name"); - } - - return getQualifiedNameForTable(fullTableName.substring(0, sepPos), fullTableName.substring(sepPos+1)); - } - - public String getQualifiedNameForTable(String dbName, String tableName) { - return (dbName + QNAME_SEP_ENTITY_NAME + tableName + QNAME_SEP_METADATA_NAMESPACE).toLowerCase() + getMetadataNamespace(); - } - - public String getQualifiedNameForColumn(LineageVertex vertex) { - // get database name and table name - LineageVertexMetadata metadata = vertex.getMetadata(); - - if (metadata == null) { - return getQualifiedNameForColumn(vertex.getVertexId()); - } - - String fullTableName = metadata.getTableName(); - - if (StringUtils.isEmpty(fullTableName)) { - throw new IllegalArgumentException("fullTableName in column metadata is null"); - } - - int sepPos = fullTableName.lastIndexOf(QNAME_SEP_ENTITY_NAME); - - if (!isSeparatorIndexValid(sepPos)) { - throw new IllegalArgumentException(fullTableName + "in column metadata does not contain database name"); - } - - // get pure column name - String columnName = vertex.getVertexId(); - if (StringUtils.isEmpty(columnName)) { - throw new IllegalArgumentException("column name in vertexId is null"); - } - - int sepPosLast = columnName.lastIndexOf(QNAME_SEP_ENTITY_NAME); - if (isSeparatorIndexValid(sepPosLast)) { - columnName = columnName.substring(sepPosLast+1); - } - - return getQualifiedNameForColumn( - fullTableName.substring(0, sepPos), - fullTableName.substring(sepPos+1), - columnName); - } - - public String getQualifiedNameForColumn(String fullColumnName) throws IllegalArgumentException { - if (fullColumnName == null) { - throw new IllegalArgumentException("fullColumnName is null"); - } - - int sepPosFirst = fullColumnName.indexOf(QNAME_SEP_ENTITY_NAME); - int sepPosLast = fullColumnName.lastIndexOf(QNAME_SEP_ENTITY_NAME); - - if (!isSeparatorIndexValid(sepPosFirst) || !isSeparatorIndexValid(sepPosLast) || - sepPosFirst == sepPosLast) { - throw new IllegalArgumentException( - String.format("fullColumnName {} does not contain database name or table name", - fullColumnName)); - } - - return getQualifiedNameForColumn( - fullColumnName.substring(0, sepPosFirst), - fullColumnName.substring(sepPosFirst+1, sepPosLast), - fullColumnName.substring(sepPosLast+1)); - } - - public String getColumnNameOnly(String fullColumnName) throws IllegalArgumentException { - if (fullColumnName == null) { - throw new IllegalArgumentException("fullColumnName is null"); - } - - int sepPosLast = fullColumnName.lastIndexOf(QNAME_SEP_ENTITY_NAME); - - if (!isSeparatorIndexValid(sepPosLast)) { - return fullColumnName; - } - - return fullColumnName.substring(sepPosLast+1); - } - - public String getQualifiedNameForColumn(String dbName, String tableName, String columnName) { - return - (dbName + QNAME_SEP_ENTITY_NAME + tableName + QNAME_SEP_ENTITY_NAME + - columnName + QNAME_SEP_METADATA_NAMESPACE).toLowerCase() + getMetadataNamespace(); - } - - public String getUserName() { return lineageQuery.getUser(); } - - public String getDatabaseNameFromTable(String fullTableName) { - int sepPos = fullTableName.lastIndexOf(QNAME_SEP_ENTITY_NAME); - if (isSeparatorIndexValid(sepPos)) { - return fullTableName.substring(0, sepPos); - } - - return null; - } - - public String getTableNameFromColumn(String columnName) { - int sepPos = columnName.lastIndexOf(QNAME_SEP_ENTITY_NAME); - if (!isSeparatorIndexValid(sepPos)) { - return null; - } - - String tableName = columnName.substring(0, sepPos); - if (!ImpalaIdentifierParser.isTableNameValid(tableName)) { - return null; - } - - return tableName; - } - - public boolean isSeparatorIndexValid(int index) { - return index > 0; - } - -} diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/ImpalaHook.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/ImpalaHook.java deleted file mode 100644 index fc047629a65..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/ImpalaHook.java +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.hook; - -import org.apache.impala.hooks.QueryCompleteContext; -import org.apache.impala.hooks.QueryEventHook; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ImpalaHook implements QueryEventHook { - private static final Logger LOG = LoggerFactory.getLogger(ImpalaHook.class); - - private ImpalaLineageHook lineageHook; - - /** - * Execute Impala hook - */ - public void onQueryComplete(QueryCompleteContext context) { - try { - lineageHook.process(context.getLineageGraph()); - } catch (Exception ex) { - String errorMessage = String.format("Error in processing impala lineage: {}", context.getLineageGraph()); - LOG.error(errorMessage, ex); - } - } - - /** - * Initialization of Impala hook - */ - public void onImpalaStartup() { - lineageHook = new ImpalaLineageHook(); - } -} diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/ImpalaIdentifierParser.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/ImpalaIdentifierParser.java deleted file mode 100644 index 33e44f729e2..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/ImpalaIdentifierParser.java +++ /dev/null @@ -1,389 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.hook; - -import java.util.Arrays; -import java.util.HashSet; - -import java.util.Set; -import org.apache.commons.lang.StringUtils; - -/** - * Check if a string is a valid Impala table identifier. - * It could be . or - */ -public class ImpalaIdentifierParser { - // http://www.cloudera.com/content/www/en-us/documentation/enterprise/latest/topics/impala_identifiers.html - // https://github.com/apache/impala/blob/64e6719870db5602a6fa85014bc6c264080b9414/tests/common/patterns.py - // VALID_IMPALA_IDENTIFIER_REGEX = re.compile(r'^[a-zA-Z][a-zA-Z0-9_]{,127}$') - // add "." to allow . - public static final String VALID_IMPALA_IDENTIFIER_REGEX = "^[a-zA-Z][a-zA-Z0-9_.]{0,127}$"; - - public static boolean isTableNameValid(String inTableName) { - if (StringUtils.isEmpty(inTableName)) { - return false; - } - - if (!inTableName.matches(VALID_IMPALA_IDENTIFIER_REGEX)) { - return false; - } - - String[] tokens = inTableName.split("."); - if (tokens.length > 2) { - // valid value should be . or - return false; - } - - for (String token : tokens) { - if (isReserved(token)) { - return false; - } - } - - return true; - } - - // The following is extracted from Impala code. - // Mainly from https://github.com/apache/impala/blob/master/fe/src/main/jflex/sql-scanner.flex - // Map from keyword string to token id. - // We use a linked hash map because the insertion order is important. - // for example, we want "and" to come after "&&" to make sure error reporting - // uses "and" as a display name and not "&&". - // Please keep the puts sorted alphabetically by keyword (where the order - // does not affect the desired error reporting) - static HashSet keywordMap; - // map from token id to token description - static HashSet tokenIdMap; - // Reserved words are words that cannot be used as identifiers. It is a superset of - // keywords. - static Set reservedWords; - - - public static void init() { - // initilize keywords - keywordMap = new HashSet<>(); - keywordMap.add("&&"); - keywordMap.add("add"); - keywordMap.add("aggregate"); - keywordMap.add("all"); - keywordMap.add("alter"); - keywordMap.add("analytic"); - keywordMap.add("and"); - keywordMap.add("anti"); - keywordMap.add("api_version"); - keywordMap.add("array"); - keywordMap.add("as"); - keywordMap.add("asc"); - keywordMap.add("authorization"); - keywordMap.add("avro"); - keywordMap.add("between"); - keywordMap.add("bigint"); - keywordMap.add("binary"); - keywordMap.add("block_size"); - keywordMap.add("boolean"); - keywordMap.add("by"); - keywordMap.add("cached"); - keywordMap.add("case"); - keywordMap.add("cascade"); - keywordMap.add("cast"); - keywordMap.add("change"); - keywordMap.add("char"); - keywordMap.add("class"); - keywordMap.add("close_fn"); - keywordMap.add("column"); - keywordMap.add("columns"); - keywordMap.add("comment"); - keywordMap.add("compression"); - keywordMap.add("compute"); - keywordMap.add("copy"); - keywordMap.add("create"); - keywordMap.add("cross"); - keywordMap.add("current"); - keywordMap.add("data"); - keywordMap.add("database"); - keywordMap.add("databases"); - keywordMap.add("date"); - keywordMap.add("datetime"); - keywordMap.add("decimal"); - //keywordMap.add("default"); "default" can be database or table name - keywordMap.add("delete"); - keywordMap.add("delimited"); - keywordMap.add("desc"); - keywordMap.add("describe"); - keywordMap.add("distinct"); - keywordMap.add("div"); - keywordMap.add("double"); - keywordMap.add("drop"); - keywordMap.add("else"); - keywordMap.add("encoding"); - keywordMap.add("end"); - keywordMap.add("escaped"); - keywordMap.add("exists"); - keywordMap.add("explain"); - keywordMap.add("extended"); - keywordMap.add("external"); - keywordMap.add("false"); - keywordMap.add("fields"); - keywordMap.add("fileformat"); - keywordMap.add("files"); - keywordMap.add("finalize_fn"); - keywordMap.add("first"); - keywordMap.add("float"); - keywordMap.add("following"); - keywordMap.add("for"); - keywordMap.add("format"); - keywordMap.add("formatted"); - keywordMap.add("from"); - keywordMap.add("full"); - keywordMap.add("function"); - keywordMap.add("functions"); - keywordMap.add("grant"); - keywordMap.add("group"); - keywordMap.add("hash"); - keywordMap.add("having"); - keywordMap.add("if"); - keywordMap.add("ilike"); - keywordMap.add("ignore"); - keywordMap.add("in"); - keywordMap.add("incremental"); - keywordMap.add("init_fn"); - keywordMap.add("inner"); - keywordMap.add("inpath"); - keywordMap.add("insert"); - keywordMap.add("int"); - keywordMap.add("integer"); - keywordMap.add("intermediate"); - keywordMap.add("interval"); - keywordMap.add("into"); - keywordMap.add("invalidate"); - keywordMap.add("iregexp"); - keywordMap.add("is"); - keywordMap.add("join"); - keywordMap.add("kudu"); - keywordMap.add("last"); - keywordMap.add("left"); - keywordMap.add("like"); - keywordMap.add("limit"); - keywordMap.add("lines"); - keywordMap.add("load"); - keywordMap.add("location"); - keywordMap.add("map"); - keywordMap.add("merge_fn"); - keywordMap.add("metadata"); - keywordMap.add("not"); - keywordMap.add("null"); - keywordMap.add("nulls"); - keywordMap.add("offset"); - keywordMap.add("on"); - keywordMap.add("||"); - keywordMap.add("or"); - keywordMap.add("orc"); - keywordMap.add("order"); - keywordMap.add("outer"); - keywordMap.add("over"); - keywordMap.add("overwrite"); - keywordMap.add("parquet"); - keywordMap.add("parquetfile"); - keywordMap.add("partition"); - keywordMap.add("partitioned"); - keywordMap.add("partitions"); - keywordMap.add("preceding"); - keywordMap.add("prepare_fn"); - keywordMap.add("primary"); - keywordMap.add("produced"); - keywordMap.add("purge"); - keywordMap.add("range"); - keywordMap.add("rcfile"); - keywordMap.add("real"); - keywordMap.add("recover"); - keywordMap.add("refresh"); - keywordMap.add("regexp"); - keywordMap.add("rename"); - keywordMap.add("repeatable"); - keywordMap.add("replace"); - keywordMap.add("replication"); - keywordMap.add("restrict"); - keywordMap.add("returns"); - keywordMap.add("revoke"); - keywordMap.add("right"); - keywordMap.add("rlike"); - keywordMap.add("role"); - keywordMap.add("roles"); - keywordMap.add("row"); - keywordMap.add("rows"); - keywordMap.add("schema"); - keywordMap.add("schemas"); - keywordMap.add("select"); - keywordMap.add("semi"); - keywordMap.add("sequencefile"); - keywordMap.add("serdeproperties"); - keywordMap.add("serialize_fn"); - keywordMap.add("set"); - keywordMap.add("show"); - keywordMap.add("smallint"); - keywordMap.add("sort"); - keywordMap.add("stats"); - keywordMap.add("stored"); - keywordMap.add("straight_join"); - keywordMap.add("string"); - keywordMap.add("struct"); - keywordMap.add("symbol"); - keywordMap.add("table"); - keywordMap.add("tables"); - keywordMap.add("tablesample"); - keywordMap.add("tblproperties"); - keywordMap.add("terminated"); - keywordMap.add("textfile"); - keywordMap.add("then"); - keywordMap.add("timestamp"); - keywordMap.add("tinyint"); - keywordMap.add("to"); - keywordMap.add("true"); - keywordMap.add("truncate"); - keywordMap.add("unbounded"); - keywordMap.add("uncached"); - keywordMap.add("union"); - keywordMap.add("unknown"); - keywordMap.add("update"); - keywordMap.add("update_fn"); - keywordMap.add("upsert"); - keywordMap.add("use"); - keywordMap.add("using"); - keywordMap.add("values"); - keywordMap.add("varchar"); - keywordMap.add("view"); - keywordMap.add("when"); - keywordMap.add("where"); - keywordMap.add("with"); - - // Initilize tokenIdMap for error reporting - tokenIdMap = new HashSet<>(keywordMap); - - // add non-keyword tokens. Please keep this in the same order as they are used in this - // file. - tokenIdMap.add("EOF"); - tokenIdMap.add("..."); - tokenIdMap.add(":"); - tokenIdMap.add(";"); - tokenIdMap.add("COMMA"); - tokenIdMap.add("."); - tokenIdMap.add("*"); - tokenIdMap.add("("); - tokenIdMap.add(")"); - tokenIdMap.add("["); - tokenIdMap.add("]"); - tokenIdMap.add("/"); - tokenIdMap.add("%"); - tokenIdMap.add("+"); - tokenIdMap.add("-"); - tokenIdMap.add("&"); - tokenIdMap.add("|"); - tokenIdMap.add("^"); - tokenIdMap.add("~"); - tokenIdMap.add("="); - tokenIdMap.add("!"); - tokenIdMap.add("<"); - tokenIdMap.add(">"); - tokenIdMap.add("UNMATCHED STRING LITERAL"); - tokenIdMap.add("!="); - tokenIdMap.add("INTEGER LITERAL"); - tokenIdMap.add("NUMERIC OVERFLOW"); - tokenIdMap.add("DECIMAL LITERAL"); - tokenIdMap.add("EMPTY IDENTIFIER"); - tokenIdMap.add("IDENTIFIER"); - tokenIdMap.add("STRING LITERAL"); - tokenIdMap.add("COMMENTED_PLAN_HINT_START"); - tokenIdMap.add("COMMENTED_PLAN_HINT_END"); - tokenIdMap.add("Unexpected character"); - - - // For impala 3.0, reserved words = keywords + sql16ReservedWords - builtinFunctions - // - whitelist - // unused reserved words = reserved words - keywords. These words are reserved for - // forward compatibility purposes. - reservedWords = new HashSet<>(keywordMap); - // Add SQL:2016 reserved words - reservedWords.addAll(Arrays.asList(new String[] { - "abs", "acos", "allocate", "any", "are", "array_agg", "array_max_cardinality", - "asensitive", "asin", "asymmetric", "at", "atan", "atomic", "avg", "begin", - "begin_frame", "begin_partition", "blob", "both", "call", "called", "cardinality", - "cascaded", "ceil", "ceiling", "char_length", "character", "character_length", - "check", "classifier", "clob", "close", "coalesce", "collate", "collect", - "commit", "condition", "connect", "constraint", "contains", "convert", "copy", - "corr", "corresponding", "cos", "cosh", "count", "covar_pop", "covar_samp", - "cube", "cume_dist", "current_catalog", "current_date", - "current_default_transform_group", "current_path", "current_path", "current_role", - "current_role", "current_row", "current_schema", "current_time", - "current_timestamp", "current_transform_group_for_type", "current_user", "cursor", - "cycle", "day", "deallocate", "dec", "decfloat", "declare", "define", - "dense_rank", "deref", "deterministic", "disconnect", "dynamic", "each", - "element", "empty", "end-exec", "end_frame", "end_partition", "equals", "escape", - "every", "except", "exec", "execute", "exp", "extract", "fetch", "filter", - "first_value", "floor", "foreign", "frame_row", "free", "fusion", "get", "global", - "grouping", "groups", "hold", "hour", "identity", "indicator", "initial", "inout", - "insensitive", "integer", "intersect", "intersection", "json_array", - "json_arrayagg", "json_exists", "json_object", "json_objectagg", "json_query", - "json_table", "json_table_primitive", "json_value", "lag", "language", "large", - "last_value", "lateral", "lead", "leading", "like_regex", "listagg", "ln", - "local", "localtime", "localtimestamp", "log", "log10 ", "lower", "match", - "match_number", "match_recognize", "matches", "max", "member", "merge", "method", - "min", "minute", "mod", "modifies", "module", "month", "multiset", "national", - "natural", "nchar", "nclob", "new", "no", "none", "normalize", "nth_value", - "ntile", "nullif", "numeric", "occurrences_regex", "octet_length", "of", "old", - "omit", "one", "only", "open", "out", "overlaps", "overlay", "parameter", - "pattern", "per", "percent", "percent_rank", "percentile_cont", "percentile_disc", - "period", "portion", "position", "position_regex", "power", "precedes", - "precision", "prepare", "procedure", "ptf", "rank", "reads", "real", "recursive", - "ref", "references", "referencing", "regr_avgx", "regr_avgy", "regr_count", - "regr_intercept", "regr_r2", "regr_slope", "regr_sxx", "regr_sxy", "regr_syy", - "release", "result", "return", "rollback", "rollup", "row_number", "running", - "savepoint", "scope", "scroll", "search", "second", "seek", "sensitive", - "session_user", "similar", "sin", "sinh", "skip", "some", "specific", - "specifictype", "sql", "sqlexception", "sqlstate", "sqlwarning", "sqrt", "start", - "static", "stddev_pop", "stddev_samp", "submultiset", "subset", "substring", - "substring_regex", "succeeds", "sum", "symmetric", "system", "system_time", - "system_user", "tan", "tanh", "time", "timezone_hour", "timezone_minute", - "trailing", "translate", "translate_regex", "translation", "treat", "trigger", - "trim", "trim_array", "uescape", "unique", "unknown", "unnest", "update ", - "upper", "user", "value", "value_of", "var_pop", "var_samp", "varbinary", - "varying", "versioning", "whenever", "width_bucket", "window", "within", - "without", "year"})); - // TODO: Remove impala builtin function names. Need to find content of - // BuiltinsDb.getInstance().getAllFunctions() - //reservedWords.removeAll(BuiltinsDb.getInstance().getAllFunctions().keySet()); - - // Remove whitelist words. These words might be heavily used in production, and - // impala is unlikely to implement SQL features around these words in the near future. - reservedWords.removeAll(Arrays.asList(new String[] { - // time units - "year", "month", "day", "hour", "minute", "second", - "begin", "call", "check", "classifier", "close", "identity", "language", - "localtime", "member", "module", "new", "nullif", "old", "open", "parameter", - "period", "result", "return", "sql", "start", "system", "time", "user", "value" - })); - } - - static { - init(); - } - - static boolean isReserved(String token) { - return token != null && reservedWords.contains(token.toLowerCase()); - } -} diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/ImpalaLineageHook.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/ImpalaLineageHook.java deleted file mode 100644 index 907f24478cf..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/ImpalaLineageHook.java +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.hook; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import com.google.common.collect.Sets; -import java.io.IOException; -import org.apache.atlas.hook.AtlasHook; -import org.apache.atlas.impala.hook.events.BaseImpalaEvent; -import org.apache.atlas.impala.hook.events.CreateImpalaProcess; -import org.apache.atlas.impala.model.ImpalaOperationType; -import org.apache.atlas.impala.model.ImpalaQuery; -import org.apache.atlas.type.AtlasType; -import org.apache.commons.lang.StringUtils; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import javax.security.auth.Subject; -import javax.security.auth.kerberos.KerberosPrincipal; -import java.util.HashSet; - -import static org.apache.atlas.repository.Constants.IMPALA_SOURCE; - -public class ImpalaLineageHook extends AtlasHook { - private static final Logger LOG = LoggerFactory.getLogger(ImpalaLineageHook.class); - public static final String ATLAS_ENDPOINT = "atlas.rest.address"; - public static final String REALM_SEPARATOR = "@"; - public static final String CONF_PREFIX = "atlas.hook.impala."; - public static final String CONF_REALM_NAME = "atlas.realm.name"; - public static final String HDFS_PATH_CONVERT_TO_LOWER_CASE = CONF_PREFIX + "hdfs_path.convert_to_lowercase"; - public static final String DEFAULT_HOST_NAME = "localhost"; - - private static final String realm; - private static final boolean convertHdfsPathToLowerCase; - private static String hostName; - - static { - realm = atlasProperties.getString(CONF_REALM_NAME, DEFAULT_CLUSTER_NAME); // what should default be ?? - convertHdfsPathToLowerCase = atlasProperties.getBoolean(HDFS_PATH_CONVERT_TO_LOWER_CASE, false); - - try { - hostName = InetAddress.getLocalHost().getHostName(); - } catch (UnknownHostException e) { - LOG.warn("No hostname found. Setting the hostname to default value {}", DEFAULT_HOST_NAME, e); - hostName = DEFAULT_HOST_NAME; - } - } - - public ImpalaLineageHook() { - - } - - public String getMessageSource() { - return IMPALA_SOURCE; - } - - public void process(String impalaQueryString) throws Exception { - if (StringUtils.isEmpty(impalaQueryString)) { - LOG.warn("==> ImpalaLineageHook.process skips because the impalaQueryString is empty <=="); - return; - } - - ImpalaQuery lineageQuery = AtlasType.fromJson(impalaQueryString, ImpalaQuery.class); - process(lineageQuery); - } - - public void process(ImpalaQuery lineageQuery) throws Exception { - if (lineageQuery == null) { - LOG.warn("==> ImpalaLineageHook.process skips because the query object is null <=="); - return; - } - - if (StringUtils.isEmpty(lineageQuery.getQueryText())) { - LOG.warn("==> ImpalaLineageHook.process skips because the query text is empty <=="); - return; - } - - if (LOG.isDebugEnabled()) { - LOG.debug("==> ImpalaLineageHook.process({})", lineageQuery.getQueryText()); - } - - try { - ImpalaOperationType operationType = ImpalaOperationParser.getImpalaOperationType(lineageQuery.getQueryText()); - AtlasImpalaHookContext context = - new AtlasImpalaHookContext(this, operationType, lineageQuery); - BaseImpalaEvent event = null; - - switch (operationType) { - case CREATEVIEW: - case CREATETABLE_AS_SELECT: - case ALTERVIEW_AS: - case QUERY: - event = new CreateImpalaProcess(context); - break; - default: - if (LOG.isDebugEnabled()) { - LOG.debug("HiveHook.run({}): operation ignored", lineageQuery.getQueryText()); - } - break; - } - - if (event != null) { - LOG.debug("Processing event: " + lineageQuery.getQueryText()); - - final UserGroupInformation ugi = getUgiFromUserName(lineageQuery.getUser()); - - super.notifyEntities(event.getNotificationMessages(), ugi); - } - } catch (Throwable t) { - - LOG.error("ImpalaLineageHook.process(): failed to process query {}", - AtlasType.toJson(lineageQuery), t); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== ImpalaLineageHook.process({})", lineageQuery.getQueryText()); - } - } - - public String getHostName() { - return hostName; - } - - private UserGroupInformation getUgiFromUserName(String userName) throws IOException { - String userPrincipal = userName.contains(REALM_SEPARATOR)? userName : userName + "@" + getRealm(); - Subject userSubject = new Subject(false, Sets.newHashSet( - new KerberosPrincipal(userPrincipal)), new HashSet(),new HashSet()); - return UserGroupInformation.getUGIFromSubject(userSubject); - } - - public String getRealm() { - return realm; - } - - public boolean isConvertHdfsPathToLowerCase() { - return convertHdfsPathToLowerCase; - } -} \ No newline at end of file diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/ImpalaOperationParser.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/ImpalaOperationParser.java deleted file mode 100644 index 98f3eed1b75..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/ImpalaOperationParser.java +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.hook; - -import org.apache.atlas.impala.model.ImpalaOperationType; -import org.apache.commons.lang.StringUtils; -import java.util.regex.Pattern; - -/** - * Parse an Impala query text and output the impala operation type - */ -public class ImpalaOperationParser { - - private static final Pattern COMMENT_PATTERN = Pattern.compile("/\\*.*?\\*/", Pattern.DOTALL); - - private static final Pattern CREATE_VIEW_PATTERN = - Pattern.compile("^[ ]*\\bcreate\\b.*\\bview\\b.*", Pattern.DOTALL | Pattern.CASE_INSENSITIVE); - - private static final Pattern CREATE_TABLE_AS_SELECT_PATTERN = - Pattern.compile("^[ ]*\\bcreate\\b.*\\btable\\b.*\\bas\\b.*\\bselect\\b.*", Pattern.DOTALL | Pattern.CASE_INSENSITIVE); - - private static final Pattern ALTER_VIEW_AS_SELECT_PATTERN = - Pattern.compile("^[ ]*\\balter\\b.*\\bview\\b.*\\bas.*\\bselect\\b.*", Pattern.DOTALL | Pattern.CASE_INSENSITIVE); - - private static final Pattern INSERT_SELECT_FROM_PATTERN = - Pattern.compile("^[ ]*\\binsert\\b.*\\b(into|overwrite)\\b.*\\bselect\\b.*\\bfrom\\b.*", Pattern.DOTALL | Pattern.CASE_INSENSITIVE); - - public ImpalaOperationParser() { - } - - public static ImpalaOperationType getImpalaOperationType(String queryText) { - // Impala does no generate lineage record for command "LOAD DATA IN PATH" - String queryTextWithNoComments = COMMENT_PATTERN.matcher(queryText).replaceAll(""); - if (doesMatch(queryTextWithNoComments, CREATE_VIEW_PATTERN)) { - return ImpalaOperationType.CREATEVIEW; - } else if (doesMatch(queryTextWithNoComments, CREATE_TABLE_AS_SELECT_PATTERN)) { - return ImpalaOperationType.CREATETABLE_AS_SELECT; - } else if (doesMatch(queryTextWithNoComments, ALTER_VIEW_AS_SELECT_PATTERN)) { - return ImpalaOperationType.ALTERVIEW_AS; - } else if (doesMatch(queryTextWithNoComments, INSERT_SELECT_FROM_PATTERN)) { - return ImpalaOperationType.QUERY; - } - - return ImpalaOperationType.UNKNOWN; - } - - public static ImpalaOperationType getImpalaOperationSubType(ImpalaOperationType operationType, String queryText) { - if (operationType == ImpalaOperationType.QUERY) { - if (StringUtils.containsIgnoreCase(queryText, "insert into")) { - return ImpalaOperationType.INSERT; - } else if (StringUtils.containsIgnoreCase(queryText, "insert overwrite")) { - return ImpalaOperationType.INSERT_OVERWRITE; - } - } - - return ImpalaOperationType.UNKNOWN; - } - - private static boolean doesMatch(final String queryText, final Pattern pattern) { - return pattern.matcher(queryText).matches(); - } - -} \ No newline at end of file diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/events/BaseImpalaEvent.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/events/BaseImpalaEvent.java deleted file mode 100644 index 32efb8321ce..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/events/BaseImpalaEvent.java +++ /dev/null @@ -1,665 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.hook.events; - -import static org.apache.atlas.impala.hook.AtlasImpalaHookContext.QNAME_SEP_PROCESS; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.apache.atlas.impala.hook.AtlasImpalaHookContext; -import org.apache.atlas.impala.hook.ImpalaOperationParser; -import org.apache.atlas.impala.model.ImpalaDataType; -import org.apache.atlas.impala.model.ImpalaNode; -import org.apache.atlas.impala.model.ImpalaOperationType; -import org.apache.atlas.impala.model.ImpalaVertexType; -import org.apache.atlas.impala.model.LineageVertex; -import org.apache.atlas.impala.model.LineageVertexMetadata; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityExtInfo; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.type.AtlasTypeUtil; - -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * The base class for generating notification event to Atlas server - * Most code is copied from BaseHiveEvent to avoid depending on org.apache.atlas.hive.hook - */ -public abstract class BaseImpalaEvent { - private static final Logger LOG = LoggerFactory.getLogger(BaseImpalaEvent.class); - - // Impala should re-use the same entity type as hive. So Hive and Impala can operate on same - // database or table - public static final String HIVE_TYPE_DB = "hive_db"; - public static final String HIVE_TYPE_TABLE = "hive_table"; - public static final String HIVE_TYPE_COLUMN = "hive_column"; - - public static final String ATTRIBUTE_QUALIFIED_NAME = "qualifiedName"; - public static final String ATTRIBUTE_NAME = "name"; - public static final String ATTRIBUTE_OWNER = "owner"; - public static final String ATTRIBUTE_CLUSTER_NAME = "clusterName"; - public static final String ATTRIBUTE_CREATE_TIME = "createTime"; - public static final String ATTRIBUTE_LAST_ACCESS_TIME = "lastAccessTime"; - public static final String ATTRIBUTE_DB = "db"; - public static final String ATTRIBUTE_COLUMNS = "columns"; - public static final String ATTRIBUTE_TABLE = "table"; - public static final String ATTRIBUTE_INPUTS = "inputs"; - public static final String ATTRIBUTE_OUTPUTS = "outputs"; - public static final String ATTRIBUTE_OPERATION_TYPE = "operationType"; - public static final String ATTRIBUTE_START_TIME = "startTime"; - public static final String ATTRIBUTE_USER_NAME = "userName"; - public static final String ATTRIBUTE_QUERY_TEXT = "queryText"; - public static final String ATTRIBUTE_PROCESS = "process"; - public static final String ATTRIBUTE_PROCESS_EXECUTIONS = "processExecutions"; - public static final String ATTRIBUTE_QUERY_ID = "queryId"; - public static final String ATTRIBUTE_QUERY_PLAN = "queryPlan"; - public static final String ATTRIBUTE_END_TIME = "endTime"; - public static final String ATTRIBUTE_RECENT_QUERIES = "recentQueries"; - public static final String ATTRIBUTE_QUERY = "query"; - public static final String ATTRIBUTE_DEPENDENCY_TYPE = "dependencyType"; - public static final String ATTRIBUTE_HOSTNAME = "hostName"; - public static final String EMPTY_ATTRIBUTE_VALUE = ""; - public static final String ATTRIBUTE_EXEC_TIME = "execTime"; - public static final String ATTRIBUTE_DDL_QUERIES = "ddlQueries"; - public static final String ATTRIBUTE_SERVICE_TYPE = "serviceType"; - public static final long MILLIS_CONVERT_FACTOR = 1000; - - protected final AtlasImpalaHookContext context; - protected final Map vertexNameMap; - protected final Map verticesMap; - - public BaseImpalaEvent(AtlasImpalaHookContext context) { - - this.context = context; - vertexNameMap = new HashMap<>(); - verticesMap = new HashMap<>(); - } - - public AtlasImpalaHookContext getContext() { - return context; - } - - public abstract List getNotificationMessages() throws Exception; - - public String getUserName() { return context.getUserName(); } - - public String getTableNameFromVertex(LineageVertex vertex) { - if (vertex.getVertexType() == ImpalaVertexType.COLUMN) { - LineageVertexMetadata metadata = vertex.getMetadata(); - - if (metadata != null) { - return metadata.getTableName(); - } - } - - return getTableNameFromColumn(vertex.getVertexId()); - } - - public String getTableNameFromColumn(String columnName) { - return context.getTableNameFromColumn(columnName); - } - - public String getQualifiedName(ImpalaNode node) throws IllegalArgumentException { - - return getQualifiedName(node.getOwnVertex()); - } - - public String getQualifiedName(LineageVertex node) throws IllegalArgumentException { - if (node == null) { - throw new IllegalArgumentException("node is null"); - } - - ImpalaVertexType nodeType = node.getVertexType(); - - if (nodeType == null) { - if (node.getVertexId() != null) { - LOG.warn("null qualified name for type: null and name: {}", node.getVertexId()); - } - return null; - } - - if (node.getVertexId() == null) { - LOG.warn("null qualified name for type: {} and name: null", nodeType); - return null; - } - - switch (nodeType) { - case DATABASE: - return context.getQualifiedNameForDb(node.getVertexId()); - - case TABLE: - return context.getQualifiedNameForTable(node.getVertexId()); - - case COLUMN: - return context.getQualifiedNameForColumn(node); - - default: - LOG.warn("null qualified name for type: {} and name: {}", nodeType, node.getVertexId()); - return null; - } - } - - static final class AtlasEntityComparator implements Comparator { - @Override - public int compare(AtlasEntity entity1, AtlasEntity entity2) { - String name1 = (String)entity1.getAttribute(ATTRIBUTE_QUALIFIED_NAME); - String name2 = (String)entity2.getAttribute(ATTRIBUTE_QUALIFIED_NAME); - - if (name1 == null) { - return -1; - } - - if (name2 == null) { - return 1; - } - - return name1.toLowerCase().compareTo(name2.toLowerCase()); - } - } - - static final Comparator entityComparator = new AtlasEntityComparator(); - - protected String getQualifiedName(List inputs, List outputs) throws Exception { - ImpalaOperationType operation = context.getImpalaOperationType(); - - if (operation == ImpalaOperationType.CREATEVIEW || - operation == ImpalaOperationType.CREATETABLE_AS_SELECT || - operation == ImpalaOperationType.ALTERVIEW_AS) { - List sortedEntities = new ArrayList<>(outputs); - - Collections.sort(sortedEntities, entityComparator); - - for (AtlasEntity entity : sortedEntities) { - if (entity.getTypeName().equalsIgnoreCase(HIVE_TYPE_TABLE)) { - Long createTime = (Long)entity.getAttribute(ATTRIBUTE_CREATE_TIME); - - return (String)entity.getAttribute(ATTRIBUTE_QUALIFIED_NAME) + QNAME_SEP_PROCESS + createTime; - } - } - } - - if (operation != ImpalaOperationType.QUERY) { - String errorMessage = String.format("Expect operation to be QUERY, but get unexpected operation type {}", operation.name()); - LOG.error(errorMessage); - throw new IllegalArgumentException(errorMessage); - } - - // construct qualified name for QUERY - String qualifiedName = null; - String operationName = operation.toString(); - - if (operationName != null) { - StringBuilder sb = new StringBuilder(operationName); - - addToProcessQualifiedName(sb, inputs, false); - sb.append("->"); - addToProcessQualifiedName(sb, outputs, true); - - qualifiedName = sb.toString(); - } - - - return qualifiedName; - } - - protected void addToProcessQualifiedName(StringBuilder processQualifiedName, Collection entities, boolean isOutput) { - if (entities == null) { - return; - } - - ImpalaOperationType operation = context.getImpalaOperationType(); - String queryText = context.getQueryStr(); - List sortedEntities = new ArrayList<>(entities); - - Collections.sort(sortedEntities, entityComparator); - - Set dataSetsProcessed = new HashSet<>(); - - for (AtlasEntity entity : sortedEntities) { - String qualifiedName = null; - long createTime = 0; - - qualifiedName = (String)entity.getAttribute(ATTRIBUTE_QUALIFIED_NAME); - - if (entity.getTypeName().equalsIgnoreCase(HIVE_TYPE_TABLE)) { - Long createTimeObj = (Long)entity.getAttribute(ATTRIBUTE_CREATE_TIME); - if (createTimeObj != null) { - createTime = createTimeObj; - } - } - - if (qualifiedName == null || !dataSetsProcessed.add(qualifiedName)) { - continue; - } - - if (isOutput) { - boolean addWriteType = false; - ImpalaOperationType subType = ImpalaOperationParser.getImpalaOperationSubType(operation, queryText); - - switch (subType) { - // Impala does not generate lineage for UPDATE and DELETE - case INSERT: - case INSERT_OVERWRITE: - addWriteType = true; - break; - } - - if (addWriteType) { - processQualifiedName.append(QNAME_SEP_PROCESS).append(subType.name()); - } - } - - processQualifiedName.append(QNAME_SEP_PROCESS).append(qualifiedName.toLowerCase().replaceAll("/", "")); - - if (createTime != 0) { - processQualifiedName.append(QNAME_SEP_PROCESS).append(createTime); - } - } - } - - protected AtlasEntity getInputOutputEntity(ImpalaNode node, AtlasEntityExtInfo entityExtInfo) throws Exception { - AtlasEntity ret = null; - - switch(node.getNodeType()) { - case TABLE: - case PARTITION: - case DFS_DIR: { - ret = toAtlasEntity(node, entityExtInfo); - } - break; - } - - return ret; - } - - protected AtlasEntity toAtlasEntity(ImpalaNode node, AtlasEntityExtInfo entityExtInfo) throws Exception { - AtlasEntity ret = null; - - switch (node.getNodeType()) { - case DATABASE: - ret = toDbEntity(node); - break; - - case TABLE: - case PARTITION: - ret = toTableEntity(node, entityExtInfo); - break; - - default: - break; - } - - return ret; - } - - protected AtlasEntity toDbEntity(ImpalaNode db) throws Exception { - return toDbEntity(db.getNodeName()); - } - - protected AtlasEntity toDbEntity(String dbName) throws Exception { - String dbQualifiedName = context.getQualifiedNameForDb(dbName); - AtlasEntity ret = context.getEntity(dbQualifiedName); - - if (ret == null) { - ret = new AtlasEntity(HIVE_TYPE_DB); - - // Impala hook should not send metadata entities. set 'guid' to null - which will: - // - result in this entity to be not included in 'referredEntities' - // - cause Atlas server to resolve the entity by its qualifiedName - ret.setGuid(null); - - ret.setAttribute(ATTRIBUTE_QUALIFIED_NAME, dbQualifiedName); - ret.setAttribute(ATTRIBUTE_NAME, dbName.toLowerCase()); - ret.setAttribute(ATTRIBUTE_CLUSTER_NAME, context.getMetadataNamespace()); - - context.putEntity(dbQualifiedName, ret); - } - - return ret; - } - - protected AtlasEntityWithExtInfo toTableEntity(ImpalaNode table) throws Exception { - AtlasEntityWithExtInfo ret = new AtlasEntityWithExtInfo(); - - AtlasEntity entity = toTableEntity(table, ret); - - if (entity != null) { - ret.setEntity(entity); - } else { - ret = null; - } - - return ret; - } - - protected AtlasEntity toTableEntity(ImpalaNode table, AtlasEntitiesWithExtInfo entities) throws Exception { - AtlasEntity ret = toTableEntity(table, (AtlasEntityExtInfo) entities); - - if (ret != null) { - entities.addEntity(ret); - } - - return ret; - } - - protected AtlasEntity toTableEntity(ImpalaNode table, AtlasEntityExtInfo entityExtInfo) throws Exception { - if ((table == null) || (table.getNodeName() == null)) { - throw new IllegalArgumentException("table is null or its name is null"); - } - - String dbName = context.getDatabaseNameFromTable(table.getNodeName()); - if (dbName == null) { - throw new IllegalArgumentException(String.format("db name is null for table: {}", table.getNodeName())); - } - - AtlasEntity dbEntity = toDbEntity(dbName); - - if (entityExtInfo != null) { - if (dbEntity != null) { - entityExtInfo.addReferredEntity(dbEntity); - } - } - - AtlasEntity ret = toTableEntity(getObjectId(dbEntity), table, entityExtInfo); - - return ret; - } - - protected AtlasEntity toTableEntity(AtlasObjectId dbId, ImpalaNode table, AtlasEntityExtInfo entityExtInfo) throws Exception { - String tblQualifiedName = getQualifiedName(table); - AtlasEntity ret = context.getEntity(tblQualifiedName); - - if (ret != null) { - return ret; - } - - // a table created in Impala still uses HIVE_TYPE_TABLE to allow both Impala and Hive operate - // on the same table - ret = new AtlasEntity(HIVE_TYPE_TABLE); - - // Impala hook should not send meta data entity to Atlas. set 'guid' to null - which will: - // - result in this entity to be not included in 'referredEntities' - // - cause Atlas server to resolve the entity by its qualifiedName - // TODO: enable this once HMS hook is in. Disable this before that. - ret.setGuid(null); - - long createTime = getTableCreateTime(table); - long lastAccessTime = createTime; - - ret.setAttribute(ATTRIBUTE_DB, dbId); - ret.setAttribute(ATTRIBUTE_QUALIFIED_NAME, tblQualifiedName); - ret.setAttribute(ATTRIBUTE_NAME, table.getNodeName().toLowerCase()); - - // just fake it. It should not be sent to Atlas once HMS hook is in - ret.setAttribute(ATTRIBUTE_OWNER, getUserName()); - - ret.setAttribute(ATTRIBUTE_CREATE_TIME, createTime); - ret.setAttribute(ATTRIBUTE_LAST_ACCESS_TIME, lastAccessTime); - - AtlasObjectId tableId = getObjectId(ret); - List columns = getColumnEntities(tableId, table); - - if (entityExtInfo != null) { - if (columns != null) { - for (AtlasEntity column : columns) { - entityExtInfo.addReferredEntity(column); - } - } - } - - ret.setAttribute(ATTRIBUTE_COLUMNS, getObjectIds(columns)); - - - context.putEntity(tblQualifiedName, ret); - - return ret; - } - - public static AtlasObjectId getObjectId(AtlasEntity entity) { - String qualifiedName = (String) entity.getAttribute(ATTRIBUTE_QUALIFIED_NAME); - AtlasObjectId ret = new AtlasObjectId(entity.getGuid(), entity.getTypeName(), Collections - .singletonMap(ATTRIBUTE_QUALIFIED_NAME, qualifiedName)); - - return ret; - } - - public static List getObjectIds(List entities) { - final List ret; - - if (CollectionUtils.isNotEmpty(entities)) { - ret = new ArrayList<>(entities.size()); - - for (AtlasEntity entity : entities) { - ret.add(getObjectId(entity)); - } - } else { - ret = Collections.emptyList(); - } - - return ret; - } - - /** - * return the createTime of the table. - * @param table - * @return the createTime of the table. Its unit is in milliseconds. - */ - public static long getTableCreateTime(ImpalaNode table) { - return getTableCreateTime(table.getOwnVertex()); - } - - public static long getTableCreateTime(LineageVertex tableVertex) { - Long createTime = tableVertex.getCreateTime(); - if (createTime != null) { - // the time unit of vertex is in seconds. Convert to milliseconds before sending to Atlas. - return createTime.longValue() * MILLIS_CONVERT_FACTOR; - } else { - return System.currentTimeMillis(); - } - } - - protected List getColumnEntities(AtlasObjectId tableId, ImpalaNode table) { - List ret = new ArrayList<>(); - - for (ImpalaNode childNode : table.getChildren().values()) { - String colQualifiedName = getQualifiedName(childNode); - AtlasEntity column = context.getEntity(colQualifiedName); - - if (column == null) { - column = new AtlasEntity(HIVE_TYPE_COLUMN); - - // if column's table was sent in an earlier notification, set 'guid' to null - which will: - // - result in this entity to be not included in 'referredEntities' - // - cause Atlas server to resolve the entity by its qualifiedName - // TODO: enable this once HMS hook is in. Disable this before that. - column.setGuid(null); - - column.setAttribute(ATTRIBUTE_TABLE, tableId); - column.setAttribute(ATTRIBUTE_QUALIFIED_NAME, colQualifiedName); - column.setAttribute(ATTRIBUTE_NAME, context.getColumnNameOnly(childNode.getNodeName())); - - // just fake it. It should not be sent to Atlas once HMS hook is in - column.setAttribute(ATTRIBUTE_OWNER, getUserName()); - - context.putEntity(colQualifiedName, column); - } - - ret.add(column); - } - - return ret; - } - - protected AtlasEntity getImpalaProcessEntity(List inputs, List outputs) throws Exception { - AtlasEntity ret = new AtlasEntity(ImpalaDataType.IMPALA_PROCESS.getName()); - String queryStr = context.getQueryStr(); - - if (queryStr != null) { - queryStr = queryStr.toLowerCase().trim(); - } - - Long startTime = getQueryStartTime(); - Long endTime = getQueryEndTime(); - - ret.setAttribute(ATTRIBUTE_QUALIFIED_NAME, getQualifiedName(inputs, outputs)); - ret.setAttribute(ATTRIBUTE_INPUTS, getObjectIds(inputs)); - ret.setAttribute(ATTRIBUTE_OUTPUTS, getObjectIds(outputs)); - ret.setAttribute(ATTRIBUTE_NAME, queryStr); - ret.setAttribute(ATTRIBUTE_OPERATION_TYPE, context.getImpalaOperationType()); - - // We are setting an empty value to these attributes, since now we have a new entity type called impala process - // execution which captures these values. We have to set empty values here because these attributes are - // mandatory attributes for impala process entity type. - ret.setAttribute(ATTRIBUTE_START_TIME, startTime); - ret.setAttribute(ATTRIBUTE_END_TIME, endTime); - ret.setAttribute(ATTRIBUTE_USER_NAME, EMPTY_ATTRIBUTE_VALUE); - ret.setAttribute(ATTRIBUTE_QUERY_TEXT, EMPTY_ATTRIBUTE_VALUE); - ret.setAttribute(ATTRIBUTE_QUERY_ID, EMPTY_ATTRIBUTE_VALUE); - ret.setAttribute(ATTRIBUTE_QUERY_PLAN, "Not Supported"); - ret.setAttribute(ATTRIBUTE_RECENT_QUERIES, Collections.singletonList(queryStr)); - - return ret; - } - - protected AtlasEntity getImpalaProcessExecutionEntity(AtlasEntity impalaProcess) throws Exception { - AtlasEntity ret = new AtlasEntity(ImpalaDataType.IMPALA_PROCESS_EXECUTION.getName()); - String queryStr = context.getQueryStr(); - - if (queryStr != null) { - queryStr = queryStr.toLowerCase().trim(); - } - - Long startTime = getQueryStartTime(); - Long endTime = getQueryEndTime(); - - ret.setAttribute(ATTRIBUTE_QUALIFIED_NAME, impalaProcess.getAttribute(ATTRIBUTE_QUALIFIED_NAME).toString() + - QNAME_SEP_PROCESS + startTime.toString() + - QNAME_SEP_PROCESS + endTime.toString()); - ret.setAttribute(ATTRIBUTE_NAME, queryStr + QNAME_SEP_PROCESS + startTime); - ret.setAttribute(ATTRIBUTE_START_TIME, startTime); - ret.setAttribute(ATTRIBUTE_END_TIME, endTime); - ret.setAttribute(ATTRIBUTE_USER_NAME, getUserName()); - ret.setAttribute(ATTRIBUTE_QUERY_TEXT, queryStr); - ret.setAttribute(ATTRIBUTE_QUERY_ID, context.getLineageQuery().getQueryId()); - ret.setAttribute(ATTRIBUTE_QUERY_PLAN, "Not Supported"); - ret.setAttribute(ATTRIBUTE_HOSTNAME, context.getHostName()); - ret.setRelationshipAttribute(ATTRIBUTE_PROCESS, AtlasTypeUtil.toAtlasRelatedObjectId(impalaProcess)); - - return ret; - } - - protected Long getQueryStartTime() { - return context.getLineageQuery().getTimestamp() * BaseImpalaEvent.MILLIS_CONVERT_FACTOR; - } - - protected Long getQueryEndTime() { - return context.getLineageQuery().getEndTime() * BaseImpalaEvent.MILLIS_CONVERT_FACTOR; - } - - protected void addProcessedEntities(AtlasEntitiesWithExtInfo entitiesWithExtInfo) { - for (AtlasEntity entity : context.getEntities()) { - entitiesWithExtInfo.addReferredEntity(entity); - } - - entitiesWithExtInfo.compact(); - } - - // The unit of createTime in vertex is in seconds. So the returned value is - // time in seconds. - protected Long getCreateTimeInVertex(LineageVertex vertex) { - if (vertex == null) { - return System.currentTimeMillis() / MILLIS_CONVERT_FACTOR; - } - - Long createTime = vertex.getCreateTime(); - - if (createTime != null) { - return createTime; - } - - if (vertex.getVertexType() == ImpalaVertexType.COLUMN) { - LineageVertexMetadata metadata = vertex.getMetadata(); - - if (metadata != null) { - return metadata.getTableCreateTime(); - } - } - - return System.currentTimeMillis() / MILLIS_CONVERT_FACTOR; - } - - protected ImpalaNode createTableNode(String tableName, Long createTime) { - // the created table vertex does not have its Id set as it is not referred in edge - LineageVertex tableVertex = new LineageVertex(); - tableVertex.setVertexType(ImpalaVertexType.TABLE); - tableVertex.setVertexId(tableName); - tableVertex.setCreateTime(createTime); - return new ImpalaNode(tableVertex); - } - - protected AtlasEntity createHiveDDLEntity(AtlasEntity dbOrTable) { - return createHiveDDLEntity(dbOrTable, true); - } - - protected AtlasEntity createHiveDDLEntity(AtlasEntity dbOrTable, boolean excludeEntityGuid) { - AtlasObjectId objId = BaseImpalaEvent.getObjectId(dbOrTable); - AtlasEntity hiveDDL = null; - - if (excludeEntityGuid) { - objId.setGuid(null); - } - - if (StringUtils.equals(objId.getTypeName(), HIVE_TYPE_DB)) { - hiveDDL = new AtlasEntity(ImpalaDataType.HIVE_DB_DDL.getName(), ATTRIBUTE_DB, objId); - } else if (StringUtils.equals(objId.getTypeName(), HIVE_TYPE_TABLE)) { - hiveDDL = new AtlasEntity(ImpalaDataType.HIVE_TABLE_DDL.getName(), ATTRIBUTE_TABLE, objId); - } - - if (hiveDDL != null) { - hiveDDL.setAttribute(ATTRIBUTE_SERVICE_TYPE, "impala"); - hiveDDL.setAttribute(ATTRIBUTE_EXEC_TIME, getQueryStartTime()); - hiveDDL.setAttribute(ATTRIBUTE_QUERY_TEXT, context.getQueryStr()); - hiveDDL.setAttribute(ATTRIBUTE_USER_NAME, getUserName()); - hiveDDL.setAttribute(ATTRIBUTE_NAME, context.getQueryStr() + QNAME_SEP_PROCESS + getQueryStartTime().toString()); - hiveDDL.setAttribute(ATTRIBUTE_QUALIFIED_NAME, hiveDDL.getAttribute(ATTRIBUTE_NAME)); - } - - return hiveDDL; - } - - protected boolean isDdlOperation() { - return (context.getImpalaOperationType().equals(ImpalaOperationType.CREATEVIEW) - || context.getImpalaOperationType().equals(ImpalaOperationType.ALTERVIEW_AS) - || context.getImpalaOperationType().equals(ImpalaOperationType.CREATETABLE_AS_SELECT)); - } -} diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/events/CreateImpalaProcess.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/events/CreateImpalaProcess.java deleted file mode 100644 index 5e6ea5a55f4..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/hook/events/CreateImpalaProcess.java +++ /dev/null @@ -1,361 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.hook.events; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.apache.atlas.impala.hook.AtlasImpalaHookContext; -import org.apache.atlas.impala.model.ImpalaDataType; -import org.apache.atlas.impala.model.ImpalaDependencyType; -import org.apache.atlas.impala.model.ImpalaNode; -import org.apache.atlas.impala.model.ImpalaVertexType; -import org.apache.atlas.impala.model.LineageEdge; -import org.apache.atlas.impala.model.ImpalaQuery; -import org.apache.atlas.impala.model.LineageVertex; -import org.apache.atlas.impala.model.LineageVertexMetadata; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.model.notification.HookNotification.EntityCreateRequestV2; -import org.apache.commons.collections.CollectionUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class CreateImpalaProcess extends BaseImpalaEvent { - private static final Logger LOG = LoggerFactory.getLogger(CreateImpalaProcess.class); - - public CreateImpalaProcess(AtlasImpalaHookContext context) { - super(context); - } - - public List getNotificationMessages() throws Exception { - List ret = null; - AtlasEntitiesWithExtInfo entities = getEntities(); - - if (entities != null && CollectionUtils.isNotEmpty(entities.getEntities())) { - ret = Collections.singletonList(new EntityCreateRequestV2(getUserName(), entities)); - } - - return ret; - } - - public AtlasEntitiesWithExtInfo getEntities() throws Exception { - AtlasEntitiesWithExtInfo ret = null; - List inputNodes = new ArrayList<>(); - List outputNodes = new ArrayList<>(); - List inputs = new ArrayList<>(); - List outputs = new ArrayList<>(); - Set processedNames = new HashSet<>(); - - getInputOutList(context.getLineageQuery(), inputNodes, outputNodes); - - if (skipProcess(inputNodes, outputNodes)) { - return ret; - } - - ret = new AtlasEntitiesWithExtInfo(); - - if (!inputNodes.isEmpty()) { - for (ImpalaNode input : inputNodes) { - String qualifiedName = getQualifiedName(input); - - if (qualifiedName == null || !processedNames.add(qualifiedName)) { - continue; - } - - AtlasEntity entity = getInputOutputEntity(input, ret); - - if (entity != null) { - inputs.add(entity); - } - } - } - - if (outputNodes != null) { - for (ImpalaNode output : outputNodes) { - String qualifiedName = getQualifiedName(output); - - if (qualifiedName == null || !processedNames.add(qualifiedName)) { - continue; - } - - AtlasEntity entity = getInputOutputEntity(output, ret); - - if (entity != null) { - outputs.add(entity); - - if (isDdlOperation()) { - AtlasEntity ddlEntity = createHiveDDLEntity(entity); - if (ddlEntity != null) { - ret.addEntity(ddlEntity); - } - } - } - } - } - - if (!inputs.isEmpty() || !outputs.isEmpty()) { - AtlasEntity process = getImpalaProcessEntity(inputs, outputs); - if (process!= null) { - if (LOG.isDebugEnabled()) { - LOG.debug("get process entity with qualifiedName: {}", - process.getAttribute(ATTRIBUTE_QUALIFIED_NAME)); - } - - ret.addEntity(process); - - AtlasEntity processExecution = getImpalaProcessExecutionEntity(process); - if (processExecution != null) { - if (LOG.isDebugEnabled()) { - LOG.debug("get process executition entity with qualifiedName: {}", - processExecution.getAttribute(ATTRIBUTE_QUALIFIED_NAME)); - } - - ret.addEntity(processExecution); - } - - processColumnLineage(process, ret); - - addProcessedEntities(ret); - } - } else { - ret = null; - } - - - return ret; - } - - private void processColumnLineage(AtlasEntity impalaProcess, AtlasEntitiesWithExtInfo entities) { - List edges = context.getLineageQuery().getEdges(); - - if (CollectionUtils.isEmpty(edges)) { - return; - } - - final List columnLineages = new ArrayList<>(); - final Set processedOutputCols = new HashSet<>(); - - for (LineageEdge edge : edges) { - - if (!edge.getEdgeType().equals(ImpalaDependencyType.PROJECTION)) { - // Impala dependency type can only be predicate or projection. - // Impala predicate dependency: This is a dependency between a set of target - // columns (or exprs) and a set of source columns (base table columns). It - // indicates that the source columns restrict the values of their targets (e.g. - // by participating in WHERE clause predicates). It should not be part of lineage - continue; - } - - List outputColumns = new ArrayList<>(); - for (Long targetId : edge.getTargets()) { - LineageVertex columnVertex = verticesMap.get(targetId); - String outputColName = getQualifiedName(columnVertex); - AtlasEntity outputColumn = context.getEntity(outputColName); - - if (LOG.isDebugEnabled()) { - LOG.debug("processColumnLineage(): target id = {}, target column name = {}", - targetId, outputColName); - } - - if (outputColumn == null) { - LOG.warn("column-lineage: non-existing output-column {}", outputColName); - continue; - } - - if (processedOutputCols.contains(outputColName)) { - LOG.warn("column-lineage: duplicate for output-column {}", outputColName); - continue; - } else { - processedOutputCols.add(outputColName); - } - - outputColumns.add(outputColumn); - } - - List inputColumns = new ArrayList<>(); - - for (Long sourceId : edge.getSources()) { - LineageVertex columnVertex = verticesMap.get(sourceId); - String inputColName = getQualifiedName(columnVertex); - AtlasEntity inputColumn = context.getEntity(inputColName); - - if (inputColumn == null) { - LOG.warn("column-lineage: non-existing input-column {} with id ={}", inputColName, sourceId); - continue; - } - - inputColumns.add(inputColumn); - } - - if (inputColumns.isEmpty()) { - continue; - } - - AtlasEntity columnLineageProcess = new AtlasEntity(ImpalaDataType.IMPALA_COLUMN_LINEAGE.getName()); - - String columnQualifiedName = (String)impalaProcess.getAttribute(ATTRIBUTE_QUALIFIED_NAME) + - AtlasImpalaHookContext.QNAME_SEP_PROCESS + outputColumns.get(0).getAttribute(ATTRIBUTE_NAME); - columnLineageProcess.setAttribute(ATTRIBUTE_NAME, columnQualifiedName); - columnLineageProcess.setAttribute(ATTRIBUTE_QUALIFIED_NAME, columnQualifiedName); - columnLineageProcess.setAttribute(ATTRIBUTE_INPUTS, getObjectIds(inputColumns)); - columnLineageProcess.setAttribute(ATTRIBUTE_OUTPUTS, getObjectIds(outputColumns)); - columnLineageProcess.setAttribute(ATTRIBUTE_QUERY, getObjectId(impalaProcess)); - - // based on https://github.com/apache/impala/blob/master/fe/src/main/java/org/apache/impala/analysis/ColumnLineageGraph.java#L267 - // There are two types of dependencies that are represented as edges in the column - // lineage graph: - // a) Projection dependency: This is a dependency between a set of source - // columns (base table columns) and a single target (result expr or table column). - // This dependency indicates that values of the target depend on the values of the source - // columns. - // b) Predicate dependency: This is a dependency between a set of target - // columns (or exprs) and a set of source columns (base table columns). It indicates that - // the source columns restrict the values of their targets (e.g. by participating in - // WHERE clause predicates). - columnLineageProcess.setAttribute(ATTRIBUTE_DEPENDENCY_TYPE, ImpalaDependencyType.PROJECTION.getName()); - - columnLineages.add(columnLineageProcess); - } - - for (AtlasEntity columnLineage : columnLineages) { - String columnQualifiedName = (String)columnLineage.getAttribute(ATTRIBUTE_QUALIFIED_NAME); - if (LOG.isDebugEnabled()) { - LOG.debug("get column lineage entity with qualifiedName: {}", columnQualifiedName); - } - - entities.addEntity(columnLineage); - } - } - - // Process the impala query, classify the vertices as input or output based on LineageEdge - // Then organize the vertices into hierarchical structure: put all column vertices of a table - // as children of a ImpalaNode representing that table. - private void getInputOutList(ImpalaQuery lineageQuery, List inputNodes, - List outputNodes) { - // get vertex map with key being its id and - // ImpalaNode map with its own vertex's vertexId as its key - for (LineageVertex vertex : lineageQuery.getVertices()) { - updateVertexMap(vertex); - } - - // get set of source ID and set of target Id - Set sourceIds = new HashSet<>(); - Set targetIds = new HashSet<>(); - for (LineageEdge edge : lineageQuery.getEdges()) { - if (ImpalaDependencyType.PROJECTION.equals(edge.getEdgeType())) { - sourceIds.addAll(edge.getSources()); - targetIds.addAll(edge.getTargets()); - } - } - - Map inputMap = buildInputOutputList(sourceIds, verticesMap, vertexNameMap); - Map outputMap = buildInputOutputList(targetIds, verticesMap, vertexNameMap); - - inputNodes.addAll(inputMap.values()); - outputNodes.addAll(outputMap.values()); - } - - // Update internal maps using this vertex. - private void updateVertexMap(LineageVertex vertex) { - verticesMap.put(vertex.getId(), vertex); - vertexNameMap.put(vertex.getVertexId(), new ImpalaNode(vertex)); - - if (vertex.getVertexType() == ImpalaVertexType.COLUMN) { - LineageVertexMetadata metadata = vertex.getMetadata(); - - if (metadata == null) { - return; - } - - // if the vertex is column and contains metadata, create a vertex for its table - String tableName = metadata.getTableName(); - ImpalaNode tableNode = vertexNameMap.get(tableName); - - if (tableNode == null) { - tableNode = createTableNode(tableName, metadata.getTableCreateTime()); - vertexNameMap.put(tableName, tableNode); - } - } - } - - /** - * From the list of Ids and Id to Vertices map, generate the Table name to ImpalaNode map. - * @param idSet the list of Ids. They are from lineage edges - * @param vertexMap the Id to Vertex map - * @param vertexNameMap the vertexId to ImpalaNode map. - * @return the table name to ImpalaNode map, whose table node contains its columns - */ - private Map buildInputOutputList(Set idSet, Map vertexMap, - Map vertexNameMap) { - Map returnTableMap = new HashMap<>(); - - for (Long id : idSet) { - LineageVertex vertex = vertexMap.get(id); - if (vertex == null) { - LOG.warn("cannot find vertex with id: {}", id); - continue; - } - - if (ImpalaVertexType.COLUMN.equals(vertex.getVertexType())) { - // add column to its table node - String tableName = getTableNameFromVertex(vertex); - if (tableName == null) { - LOG.warn("cannot find tableName for vertex with id: {}, column name : {}", - id, vertex.getVertexId() == null? "null" : vertex.getVertexId()); - - continue; - } - - ImpalaNode tableNode = returnTableMap.get(tableName); - - if (tableNode == null) { - tableNode = vertexNameMap.get(tableName); - - if (tableNode == null) { - LOG.warn("cannot find table node for vertex with id: {}, column name : {}", - id, vertex.getVertexId()); - - tableNode = createTableNode(tableName, getCreateTimeInVertex(null)); - vertexNameMap.put(tableName, tableNode); - } - - returnTableMap.put(tableName, tableNode); - } - - tableNode.addChild(vertex); - } - } - - return returnTableMap; - } - - private boolean skipProcess(List inputNodes, List ouputNodes) { - if (inputNodes.isEmpty() || ouputNodes.isEmpty()) { - return true; - } - - return false; - } -} diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaDataType.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaDataType.java deleted file mode 100644 index 4e0d4787067..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaDataType.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.model; - -/** - * Data types used for Impala bridge - */ -public enum ImpalaDataType { - - IMPALA_PROCESS, - IMPALA_PROCESS_EXECUTION, - IMPALA_COLUMN_LINEAGE, - HIVE_DB_DDL, - HIVE_TABLE_DDL; - - public String getName() { - return name().toLowerCase(); - } -} diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaDependencyType.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaDependencyType.java deleted file mode 100644 index 892ee9b2fba..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaDependencyType.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.model; - -public enum ImpalaDependencyType { - PROJECTION("PROJECTION"), - PREDICATE("PREDICATE"); - - private final String name; - - ImpalaDependencyType(String name) { - this.name = name; - } - - public String getName() { - return name.toUpperCase(); - } -} diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaNode.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaNode.java deleted file mode 100644 index a3ddf537299..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaNode.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.model; - -import java.util.HashMap; -import java.util.Map; - -/** - * Contain vertex info of this node and its children. It is used only internally - */ -public class ImpalaNode { - LineageVertex ownVertex; - Map children; - - public ImpalaNode(LineageVertex ownVertex) { - this.ownVertex = ownVertex; - children = new HashMap<>(); - } - - public String getNodeName() { return ownVertex.getVertexId(); } - public ImpalaVertexType getNodeType() { return ownVertex.getVertexType(); } - public LineageVertex getOwnVertex() { return ownVertex; } - public Map getChildren() { return children; } - - /** - * Add child to this node - * @param child - * @return the node corresponding to the input child vertex - */ - public ImpalaNode addChild(LineageVertex child) { - ImpalaNode exitingChild = children.get(child.getId()); - if (exitingChild != null) { - return exitingChild; - } - - ImpalaNode newChild = new ImpalaNode(child); - return children.put(child.getId(), newChild); - } -} diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaOperationType.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaOperationType.java deleted file mode 100644 index a893b8845c0..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaOperationType.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.model; - -public enum ImpalaOperationType{ - // main operation type - CREATEVIEW ("CREATEVIEW"), - CREATETABLE_AS_SELECT ("CREATETABLE_AS_SELECT"), - ALTERVIEW_AS ("ALTERVIEW_AS"), - QUERY ("QUERY"), - - // sub operation type, which is associated with output - INSERT ("INSERT"), - INSERT_OVERWRITE ("INSERT_OVERWRITE"), - - // default type - UNKNOWN ("UNKNOWN"); - - private final String name; - - ImpalaOperationType(String s) { - name = s; - } - - public boolean equalsName(String otherName) { - return name.equals(otherName); - } - - public String toString() { - return this.name; - } -} \ No newline at end of file diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaQuery.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaQuery.java deleted file mode 100644 index 27bdc72e9da..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaQuery.java +++ /dev/null @@ -1,110 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.model; - -import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; -import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import java.util.List; - -/** - * Represent an Impala lineage record in lineage log. - */ -@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) -@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) -@JsonIgnoreProperties(ignoreUnknown=true) -public class ImpalaQuery { - private String queryText; - private String queryId; - private String hash; - private String user; - - // the time stamp is in seconds. It is Unix epoch, which is the number of seconds that have - // elapsed since January 1, 1970 (midnight UTC/GMT), not counting leap seconds - private Long timestamp; - private Long endTime; - private List edges; - private List vertices; - - public List getEdges() { - return edges; - } - - public List getVertices() { - return vertices; - } - - public Long getEndTime() { - return endTime; - } - - public String getHash() { - return hash; - } - - public String getQueryId() { - return queryId; - } - - public String getQueryText() { - return queryText; - } - - public Long getTimestamp() { - return timestamp; - } - - public String getUser() { - return user; - } - - public void setEdges(List edges) { - this.edges = edges; - } - - public void setEndTime(Long endTime) { - this.endTime = endTime; - } - - public void setHash(String hash) { - this.hash = hash; - } - - public void setQueryId(String queryId) { - this.queryId = queryId; - } - - public void setQueryText(String queryText) { - this.queryText = queryText; - } - - public void setTimestamp(Long timestamp) { this.timestamp = timestamp; } - - public void setUser(String user) { - this.user = user; - } - - public void setVertices(List vertices) { - this.vertices = vertices; - } - -} diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaVertexType.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaVertexType.java deleted file mode 100644 index 8ec3f857ad6..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/ImpalaVertexType.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.model; - -public enum ImpalaVertexType { - DFS_DIR("DFS_DIR"), - PARTITION("PARTITION"), - COLUMN("COLUMN"), - TABLE("TABLE"), - DATABASE("DATABASE"); - - private final String name; - - ImpalaVertexType(String name) { - this.name = name; - } - - public String getName() { - return name.toUpperCase(); - } -} diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/LineageEdge.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/LineageEdge.java deleted file mode 100644 index 251507e9e17..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/LineageEdge.java +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.model; - -import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; -import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; -import java.util.List; - -/** - * This represents an edge in Impala's lineage record that connects two entities - */ -@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) -@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) -@JsonIgnoreProperties(ignoreUnknown=true) -public class LineageEdge { - private List sources; - private List targets; - private ImpalaDependencyType edgeType; - - public List getSources() { - return sources; - } - - public List getTargets() { - return targets; - } - - public ImpalaDependencyType getEdgeType() { - return edgeType; - } - - public void setSources(List sources) { - this.sources = sources; - } - - public void setTargets(List targets) { - this.targets = targets; - } - - public void setEdgeType(ImpalaDependencyType edgeType) { - this.edgeType = edgeType; - } -} diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/LineageVertex.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/LineageVertex.java deleted file mode 100644 index 0a664fc8b69..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/LineageVertex.java +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.model; - -import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; -import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; - -/** - * This represents an entity in Impala's lineage record. - */ -@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) -@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) -@JsonIgnoreProperties(ignoreUnknown=true) -public class LineageVertex { - // id is used to reference this entity. It is used in LineageEdge to specify source and target - // https://github.com/apache/impala/blob/master/be/src/util/lineage-util.h#L40 - // Impala id is int64. Therefore, define this field as Long - private Long id; - - // specify the type of the entity, it could be "TABLE", "COLUMN" etc. - private ImpalaVertexType vertexType; - - // specify the name of the entity - private String vertexId; - - // It is optional, and could be null. It is only set if the entity is a column, and this field contains metadata of its table. - private LineageVertexMetadata metadata; - - // It is optional. Its unit in seconds. - private Long createTime; - - public Long getId() { return id; } - - public ImpalaVertexType getVertexType() { - return vertexType; - } - - public String getVertexId() { - return vertexId; - } - - public LineageVertexMetadata getMetadata() { - return metadata; - } - - public Long getCreateTime() { return createTime; } - - public void setId(Long id) { - this.id = id; - } - - public void setVertexType(ImpalaVertexType vertexType) { - this.vertexType = vertexType; - } - - public void setVertexId(String vertexId) { - this.vertexId = vertexId; - } - - public void setMetadata(LineageVertexMetadata metadata) { this.metadata = metadata; } - - public void setCreateTime(Long createTime) { this.createTime = createTime; } -} \ No newline at end of file diff --git a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/LineageVertexMetadata.java b/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/LineageVertexMetadata.java deleted file mode 100644 index 2b3226c21dd..00000000000 --- a/addons/impala-bridge/src/main/java/org/apache/atlas/impala/model/LineageVertexMetadata.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.model; - -import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; -import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY; - -import com.fasterxml.jackson.annotation.JsonAutoDetect; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.databind.annotation.JsonSerialize; - -/** - * This represents optional metadata in Impala's lineage vertex entity. - */ -@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) -@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) -@JsonIgnoreProperties(ignoreUnknown=true) -public class LineageVertexMetadata { - // specify the name of the table - private String tableName; - - // the create time of the table. Its unit is in seconds. - private Long tableCreateTime; - - public String getTableName() { return tableName; } - - public Long getTableCreateTime() { return tableCreateTime; } - - public void setTableName(String tableName) { this.tableName = tableName; } - - public void setTableCreateTime(Long createTime) { this.tableCreateTime = createTime; } -} diff --git a/addons/impala-bridge/src/main/resources/atlas-log4j.xml b/addons/impala-bridge/src/main/resources/atlas-log4j.xml deleted file mode 100644 index 97317a87548..00000000000 --- a/addons/impala-bridge/src/main/resources/atlas-log4j.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/addons/impala-bridge/src/main/resources/import-impala.sh b/addons/impala-bridge/src/main/resources/import-impala.sh deleted file mode 100644 index b440f2d0566..00000000000 --- a/addons/impala-bridge/src/main/resources/import-impala.sh +++ /dev/null @@ -1,114 +0,0 @@ -#!/bin/bash -# -# 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. See accompanying LICENSE file. -# -# resolve links - $0 may be a softlink -PRG="${0}" - -[[ `uname -s` == *"CYGWIN"* ]] && CYGWIN=true - -while [ -h "${PRG}" ]; do - ls=`ls -ld "${PRG}"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "${PRG}"`/"$link" - fi -done - -BASEDIR=`dirname ${PRG}` - -if test -z "${JAVA_HOME}" -then - JAVA_BIN=`which java` - JAR_BIN=`which jar` -else - JAVA_BIN="${JAVA_HOME}/bin/java" - JAR_BIN="${JAVA_HOME}/bin/jar" -fi -export JAVA_BIN - -if [ ! -e "${JAVA_BIN}" ] || [ ! -e "${JAR_BIN}" ]; then - echo "$JAVA_BIN and/or $JAR_BIN not found on the system. Please make sure java and jar commands are available." - exit 1 -fi - -# Construct ATLAS_CONF where atlas-properties reside -# assume the hive-server2 is installed and contains Atlas configuration -# Otherwise, need to setup Atlas required properties and libraries before running this tool -if [ ! -z "$HIVE_CONF_DIR" ]; then - HIVE_CONF=$HIVE_CONF_DIR -elif [ ! -z "$HIVE_HOME" ]; then - HIVE_CONF="$HIVE_HOME/conf" -elif [ -e /etc/hive/conf ]; then - HIVE_CONF="/etc/hive/conf" -else - echo "Could not find a valid HIVE configuration for ATLAS" - exit 1 -fi -if [ -z "$ATLAS_CONF" ]; then - export ATLAS_CONF=$HIVE_CONF -fi - -# log dir for applications -ATLAS_LOG_DIR="/var/log/atlas" -ATLAS_LOG_FILE="impala-bridge.log" -LOG_CONFIG="${BASEDIR}/atlas-log4j.xml" - -# Construct Atlas classpath. -DIR=$PWD -PARENT="$(dirname "$DIR")" -GRANDPARENT="$(dirname "$PARENT")" -LIB_PATH="$GRANDPARENT/server/webapp/atlas/WEB-INF/lib" -echo "$LIB_PATH" -# Construct Atlas classpath. -for i in "$LIB_PATH/"*.jar; do - ATLASCPPATH="${ATLASCPPATH}:$i" -done - -for i in "${BASEDIR}/"*.jar; do - ATLASCPPATH="${ATLASCPPATH}:$i" -done - -if [ -z "${ATLAS_CONF_DIR}" ] && [ -e /etc/atlas/conf ];then - ATLAS_CONF_DIR=/etc/atlas/conf -fi -ATLASCPPATH=${ATLASCPPATH}:${ATLAS_CONF_DIR} - -echo "Logging: ${ATLAS_LOG_DIR}/${ATLAS_LOG_FILE}" -echo "Log config: ${LOG_CONFIG}" - -TIME=`date %Y%m%d%H%M%s` -CP="${ATLASCPPATH}:${ATLAS_CONF}" - -# If running in cygwin, convert pathnames and classpath to Windows format. -if [ "${CYGWIN}" == "true" ] -then - ATLAS_LOG_DIR=`cygpath -w ${ATLAS_LOG_DIR}` - ATLAS_LOG_FILE=`cygpath -w ${ATLAS_LOG_FILE}` - CP=`cygpath -w -p ${CP}` -fi - -JAVA_PROPERTIES="$ATLAS_OPTS -Datlas.log.dir=$ATLAS_LOG_DIR -Datlas.log.file=$ATLAS_LOG_FILE -Dlog4j.configuration=file://$LOG_CONFIG" - -IMPORT_ARGS=$@ -JVM_ARGS= - -JAVA_PROPERTIES="${JAVA_PROPERTIES} ${JVM_ARGS}" -"${JAVA_BIN}" ${JAVA_PROPERTIES} -cp "${CP}" org.apache.atlas.impala.ImpalaLineageTool $IMPORT_ARGS - -RETVAL=$? -[ $RETVAL -eq 0 ] && echo Done! -[ $RETVAL -ne 0 ] && echo Failed! -exit $RETVAL \ No newline at end of file diff --git a/addons/impala-bridge/src/test/java/org/apache/atlas/impala/ImpalaLineageITBase.java b/addons/impala-bridge/src/test/java/org/apache/atlas/impala/ImpalaLineageITBase.java deleted file mode 100644 index ef23a26d106..00000000000 --- a/addons/impala-bridge/src/test/java/org/apache/atlas/impala/ImpalaLineageITBase.java +++ /dev/null @@ -1,495 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala; - -import static org.apache.atlas.impala.hook.events.BaseImpalaEvent.ATTRIBUTE_QUALIFIED_NAME; -import static org.apache.atlas.impala.hook.events.BaseImpalaEvent.ATTRIBUTE_QUERY_TEXT; -import static org.apache.atlas.impala.hook.events.BaseImpalaEvent.ATTRIBUTE_RECENT_QUERIES; -import static org.apache.atlas.impala.hook.events.BaseImpalaEvent.HIVE_TYPE_DB; -import static org.apache.atlas.impala.hook.events.BaseImpalaEvent.HIVE_TYPE_TABLE; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.fail; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.impala.hook.AtlasImpalaHookContext; -import org.apache.atlas.impala.hook.ImpalaLineageHook; -import org.apache.atlas.impala.hook.events.BaseImpalaEvent; -import org.apache.atlas.impala.model.ImpalaDataType; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.utils.AuthenticationUtil; -import org.apache.atlas.utils.ParamChecker; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.lang.RandomStringUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.hadoop.hive.conf.HiveConf; -import org.apache.hadoop.hive.ql.Driver; -import org.apache.hadoop.hive.ql.processors.CommandProcessorResponse; -import org.apache.hadoop.hive.ql.session.SessionState; -import org.testng.annotations.BeforeClass; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; - -public class ImpalaLineageITBase { - private static final Logger LOG = LoggerFactory.getLogger(ImpalaLineageITBase.class); - - public static final String DEFAULT_DB = "default"; - public static final String SEP = ":".intern(); - public static final String IO_SEP = "->".intern(); - protected static final String DGI_URL = "http://localhost:21000/"; - protected static final String CLUSTER_NAME = "primary"; - protected static final String PART_FILE = "2015-01-01"; - protected static final String INPUTS = "inputs"; - protected static final String OUTPUTS = "outputs"; - protected static AtlasClientV2 atlasClientV2; - - private static final String REFERENCEABLE_ATTRIBUTE_NAME = "qualifiedName"; - private static final String ATTR_NAME = "name"; - - // to push entity creation/update to HMS, so HMS hook can push the metadata notification - // to Atlas, then the lineage notification from this tool can be created at Atlas - protected static Driver driverWithoutContext; - protected static SessionState ss; - protected static HiveConf conf; - - - @BeforeClass - public void setUp() throws Exception { - //Set-up hive session - conf = new HiveConf(); - conf.setClassLoader(Thread.currentThread().getContextClassLoader()); - HiveConf conf = new HiveConf(); - SessionState ss = new SessionState(conf); - ss = SessionState.start(ss); - SessionState.setCurrentSessionState(ss); - driverWithoutContext = new Driver(conf); - - Configuration configuration = ApplicationProperties.get(); - - String[] atlasEndPoint = configuration.getStringArray(ImpalaLineageHook.ATLAS_ENDPOINT); - if (atlasEndPoint == null || atlasEndPoint.length == 0) { - atlasEndPoint = new String[]{DGI_URL}; - } - - if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { - atlasClientV2 = new AtlasClientV2(atlasEndPoint, new String[]{"admin", "admin"}); - } else { - atlasClientV2 = new AtlasClientV2(atlasEndPoint); - } - - } - - // return guid of the entity - protected String assertEntityIsRegistered(final String typeName, final String property, final String value, - final AssertPredicate assertPredicate) throws Exception { - waitFor(100000, new Predicate() { - @Override - public void evaluate() throws Exception { - AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfo = atlasClientV2.getEntityByAttribute(typeName, Collections - .singletonMap(property,value)); - AtlasEntity entity = atlasEntityWithExtInfo.getEntity(); - assertNotNull(entity); - if (assertPredicate != null) { - assertPredicate.assertOnEntity(entity); - } - } - }); - AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfo = atlasClientV2.getEntityByAttribute(typeName, Collections.singletonMap(property,value)); - AtlasEntity entity = atlasEntityWithExtInfo.getEntity(); - return (String) entity.getGuid(); - } - - protected String assertEntityIsRegistered(final String typeName, List processQFNames, - final AssertPredicates assertPredicates) throws Exception { - List> attributesList = new ArrayList<>(); - - for (String processName : processQFNames) { - attributesList.add(Collections.singletonMap(ATTRIBUTE_QUALIFIED_NAME, processName)); - } - - return waitForWithReturn(80000, new PredicateWithReturn() { - @Override - public String evaluate() throws Exception { - AtlasEntity.AtlasEntitiesWithExtInfo atlasEntitiesWithExtInfo = atlasClientV2.getEntitiesByAttribute(typeName, attributesList); - List entities = atlasEntitiesWithExtInfo.getEntities(); - assertNotNull(entities); - if (assertPredicates != null) { - return assertPredicates.assertOnEntities(entities); - } - - return null; - } - }); - } - - protected String assertEntityIsRegisteredViaGuid(String guid, - final AssertPredicate assertPredicate) throws Exception { - waitFor(80000, new Predicate() { - @Override - public void evaluate() throws Exception { - AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfo = atlasClientV2.getEntityByGuid(guid); - AtlasEntity entity = atlasEntityWithExtInfo.getEntity(); - assertNotNull(entity); - if (assertPredicate != null) { - assertPredicate.assertOnEntity(entity); - } - - } - }); - AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfo = atlasClientV2.getEntityByGuid(guid); - AtlasEntity entity = atlasEntityWithExtInfo.getEntity(); - return (String) entity.getGuid(); - } - - - protected String assertProcessIsRegistered(List processQFNames, String queryString) throws Exception { - try { - Thread.sleep(5000); - - LOG.debug("Searching for process with query {}", queryString); - - return assertEntityIsRegistered(ImpalaDataType.IMPALA_PROCESS.getName(), processQFNames, new AssertPredicates() { - @Override - public String assertOnEntities(final List entities) throws Exception { - for (AtlasEntity entity : entities) { - List recentQueries = (List) entity - .getAttribute(ATTRIBUTE_RECENT_QUERIES); - - if (queryString.equalsIgnoreCase(recentQueries.get(0))) - return entity.getGuid(); - - } - - throw new IllegalStateException("Not found entity with matching query"); - } - }); - } catch(Exception e) { - LOG.error("Exception : ", e); - throw e; - } - } - - protected String assertProcessIsRegistered(String processQFName, String queryString) throws Exception { - try { - Thread.sleep(5000); - - LOG.debug("Searching for process with qualified name {} and query {}", processQFName, queryString); - - return assertEntityIsRegistered(ImpalaDataType.IMPALA_PROCESS.getName(), ATTRIBUTE_QUALIFIED_NAME, processQFName, new AssertPredicate() { - @Override - public void assertOnEntity(final AtlasEntity entity) throws Exception { - List recentQueries = (List) entity.getAttribute(ATTRIBUTE_RECENT_QUERIES); - - Assert.assertEquals(recentQueries.get(0), lower(queryString)); - } - }); - } catch(Exception e) { - LOG.error("Exception : ", e); - throw e; - } - } - - private String assertProcessExecutionIsRegistered(AtlasEntity impalaProcess, final String queryString) throws Exception { - try { - Thread.sleep(5000); - - String guid = ""; - List processExecutions = toAtlasObjectIdList(impalaProcess.getRelationshipAttribute( - BaseImpalaEvent.ATTRIBUTE_PROCESS_EXECUTIONS)); - for (AtlasObjectId processExecution : processExecutions) { - AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfo = atlasClientV2. - getEntityByGuid(processExecution.getGuid()); - - AtlasEntity entity = atlasEntityWithExtInfo.getEntity(); - if (String.valueOf(entity.getAttribute(ATTRIBUTE_QUERY_TEXT)).equals(queryString.toLowerCase().trim())) { - guid = entity.getGuid(); - break; - } - } - - return assertEntityIsRegisteredViaGuid(guid, new AssertPredicate() { - @Override - public void assertOnEntity(final AtlasEntity entity) throws Exception { - String queryText = (String) entity.getAttribute(ATTRIBUTE_QUERY_TEXT); - Assert.assertEquals(queryText, queryString.toLowerCase().trim()); - } - }); - } catch(Exception e) { - LOG.error("Exception : ", e); - throw e; - } - } - - protected AtlasObjectId toAtlasObjectId(Object obj) { - final AtlasObjectId ret; - - if (obj instanceof AtlasObjectId) { - ret = (AtlasObjectId) obj; - } else if (obj instanceof Map) { - ret = new AtlasObjectId((Map) obj); - } else if (obj != null) { - ret = new AtlasObjectId(obj.toString()); // guid - } else { - ret = null; - } - - return ret; - } - - protected List toAtlasObjectIdList(Object obj) { - final List ret; - - if (obj instanceof Collection) { - Collection coll = (Collection) obj; - - ret = new ArrayList<>(coll.size()); - - for (Object item : coll) { - AtlasObjectId objId = toAtlasObjectId(item); - - if (objId != null) { - ret.add(objId); - } - } - } else { - AtlasObjectId objId = toAtlasObjectId(obj); - - if (objId != null) { - ret = new ArrayList<>(1); - - ret.add(objId); - } else { - ret = null; - } - } - - return ret; - } - - - protected String assertDatabaseIsRegistered(String dbName) throws Exception { - return assertDatabaseIsRegistered(dbName, null); - } - - protected String assertDatabaseIsRegistered(String dbName, AssertPredicate assertPredicate) throws Exception { - LOG.debug("Searching for database: {}", dbName); - - String dbQualifiedName = dbName + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE + - CLUSTER_NAME; - - dbQualifiedName = dbQualifiedName.toLowerCase(); - - return assertEntityIsRegistered(HIVE_TYPE_DB, REFERENCEABLE_ATTRIBUTE_NAME, dbQualifiedName, assertPredicate); - } - - protected String assertTableIsRegistered(String dbName, String tableName) throws Exception { - return assertTableIsRegistered(dbName, tableName, null, false); - } - - protected String assertTableIsRegistered(String fullTableName) throws Exception { - return assertTableIsRegistered(fullTableName, null, false); - } - - protected String assertTableIsRegistered(String dbName, String tableName, AssertPredicate assertPredicate, boolean isTemporary) throws Exception { - LOG.debug("Searching for table {}.{}", dbName, tableName); - - String fullTableName = dbName + AtlasImpalaHookContext.QNAME_SEP_ENTITY_NAME + tableName; - - return assertTableIsRegistered(fullTableName, assertPredicate, isTemporary); - } - - protected String assertTableIsRegistered(String fullTableName, AssertPredicate assertPredicate, boolean isTemporary) throws Exception { - LOG.debug("Searching for table {}", fullTableName); - - String tableQualifiedName = (fullTableName + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE).toLowerCase() + - CLUSTER_NAME; - - return assertEntityIsRegistered(HIVE_TYPE_TABLE, REFERENCEABLE_ATTRIBUTE_NAME, tableQualifiedName, - assertPredicate); - } - - protected String createDatabase() throws Exception { - String dbName = dbName(); - - return createDatabase(dbName); - } - - protected String createDatabase(String dbName) throws Exception { - runCommandWithDelay("CREATE DATABASE IF NOT EXISTS " + dbName, 3000); - - return dbName; - } - - protected String createTable(String dbName, String columnsString) throws Exception { - return createTable(dbName, columnsString, false); - } - - protected String createTable(String dbName, String columnsString, boolean isPartitioned) throws Exception { - String tableName = tableName(); - return createTable(dbName, tableName, columnsString, isPartitioned); - } - - protected String createTable(String dbName, String tableName, String columnsString, boolean isPartitioned) throws Exception { - runCommandWithDelay("CREATE TABLE IF NOT EXISTS " + dbName + "." + tableName + " " + columnsString + " comment 'table comment' " + (isPartitioned ? " partitioned by(dt string)" : ""), 3000); - - return dbName + "." + tableName; - } - - protected AtlasEntity validateProcess(String processQFName, String queryString) throws Exception { - String processId = assertProcessIsRegistered(processQFName, queryString); - AtlasEntity processEntity = atlasClientV2.getEntityByGuid(processId).getEntity(); - - return processEntity; - } - - protected AtlasEntity validateProcess(List processQFNames, String queryString) throws Exception { - String processId = assertProcessIsRegistered(processQFNames, queryString); - AtlasEntity processEntity = atlasClientV2.getEntityByGuid(processId).getEntity(); - - return processEntity; - } - - protected AtlasEntity validateProcessExecution(AtlasEntity impalaProcess, String queryString) throws Exception { - String processExecutionId = assertProcessExecutionIsRegistered(impalaProcess, queryString); - AtlasEntity processExecutionEntity = atlasClientV2.getEntityByGuid(processExecutionId).getEntity(); - return processExecutionEntity; - } - - protected int numberOfProcessExecutions(AtlasEntity impalaProcess) { - return toAtlasObjectIdList(impalaProcess.getRelationshipAttribute( - BaseImpalaEvent.ATTRIBUTE_PROCESS_EXECUTIONS)).size(); - } - - public interface AssertPredicate { - void assertOnEntity(AtlasEntity entity) throws Exception; - } - - public interface AssertPredicates { - String assertOnEntities(List entities) throws Exception; - } - - public interface PredicateWithReturn { - /** - * Perform a predicate evaluation. - * - * @return the boolean result of the evaluation. - * @throws Exception thrown if the predicate evaluation could not evaluate. - */ - String evaluate() throws Exception; - } - - public interface Predicate { - /** - * Perform a predicate evaluation. - * - * @return the boolean result of the evaluation. - * @throws Exception thrown if the predicate evaluation could not evaluate. - */ - void evaluate() throws Exception; - } - - /** - * Wait for a condition, expressed via a {@link Predicate} to become true. - * - * @param timeout maximum time in milliseconds to wait for the predicate to become true. - * @param predicate predicate waiting on. - */ - protected void waitFor(int timeout, Predicate predicate) throws Exception { - ParamChecker.notNull(predicate, "predicate"); - long mustEnd = System.currentTimeMillis() + timeout; - - while (true) { - try { - predicate.evaluate(); - return; - } catch(Error | Exception e) { - if (System.currentTimeMillis() >= mustEnd) { - fail("Assertions failed. Failing after waiting for timeout " + timeout + " msecs", e); - } - LOG.debug("Waiting up to {} msec as assertion failed", mustEnd - System.currentTimeMillis(), e); - Thread.sleep(5000); - } - } - } - - /** - * Wait for a condition, expressed via a {@link Predicate} to become true. - * - * @param timeout maximum time in milliseconds to wait for the predicate to become true. - * @param predicate predicate waiting on. - */ - protected String waitForWithReturn(int timeout, PredicateWithReturn predicate) throws Exception { - ParamChecker.notNull(predicate, "predicate"); - long mustEnd = System.currentTimeMillis() + timeout; - - while (true) { - try { - return predicate.evaluate(); - } catch(Error | Exception e) { - if (System.currentTimeMillis() >= mustEnd) { - fail("Assertions failed. Failing after waiting for timeout " + timeout + " msecs", e); - } - LOG.debug("Waiting up to {} msec as assertion failed", mustEnd - System.currentTimeMillis(), e); - Thread.sleep(5000); - } - } - } - - public static String lower(String str) { - if (StringUtils.isEmpty(str)) { - return null; - } - return str.toLowerCase().trim(); - } - - protected void runCommand(String cmd) throws Exception { - runCommandWithDelay(cmd, 0); - } - - protected void runCommandWithDelay(String cmd, int sleepMs) throws Exception { - runCommandWithDelay(driverWithoutContext, cmd, sleepMs); - } - - protected void runCommandWithDelay(Driver driver, String cmd, int sleepMs) throws Exception { - LOG.debug("Running command '{}'", cmd); - CommandProcessorResponse response = driver.run(cmd); - assertEquals(response.getResponseCode(), 0); - if (sleepMs != 0) { - Thread.sleep(sleepMs); - } - } - - protected String random() { - return RandomStringUtils.randomAlphanumeric(10); - } - - protected String tableName() { - return "table_" + random(); - } - protected String dbName() {return "db_" + random();} -} diff --git a/addons/impala-bridge/src/test/java/org/apache/atlas/impala/ImpalaLineageToolIT.java b/addons/impala-bridge/src/test/java/org/apache/atlas/impala/ImpalaLineageToolIT.java deleted file mode 100644 index 53e9b1224a4..00000000000 --- a/addons/impala-bridge/src/test/java/org/apache/atlas/impala/ImpalaLineageToolIT.java +++ /dev/null @@ -1,655 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala; - -import static org.apache.atlas.impala.hook.events.BaseImpalaEvent.ATTRIBUTE_QUERY_TEXT; - -import java.util.ArrayList; -import java.util.List; -import org.apache.atlas.impala.hook.AtlasImpalaHookContext; -import org.apache.atlas.impala.hook.ImpalaLineageHook; -import org.apache.atlas.impala.hook.events.BaseImpalaEvent; -import org.apache.atlas.impala.model.ImpalaQuery; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.testng.Assert; -import org.testng.annotations.Test; - -import static org.apache.atlas.impala.hook.events.BaseImpalaEvent.ATTRIBUTE_DDL_QUERIES; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; - -public class ImpalaLineageToolIT extends ImpalaLineageITBase { - public static final long TABLE_CREATE_TIME_SOURCE = 1554750070; - public static final long TABLE_CREATE_TIME = 1554750072; - private static String dir = System.getProperty("user.dir") + "/src/test/resources/"; - - /** - * This tests - * 1) ImpalaLineageTool can parse one lineage file that contains "create view" command lineage - * 2) Lineage is sent to Atlas - * 3) Atlas can get this lineage from Atlas - */ - @Test - public void testCreateViewFromFile() { - // this file contains a single lineage record for "create view". - // It has table vertex with createTime - String IMPALA = dir + "impalaCreateView.json"; - String IMPALA_WAL = dir + "WALimpala.wal"; - - List lineageList = new ArrayList<>(); - ImpalaLineageHook impalaLineageHook = new ImpalaLineageHook(); - - try { - // create database and tables to simulate Impala behavior that Impala updates metadata - // to HMS and HMSHook sends the metadata to Atlas, which has to happen before - // Atlas can handle lineage notification - String dbName = "db_1"; - createDatabase(dbName); - - String sourceTableName = "table_1"; - createTable(dbName, sourceTableName,"(id string, count int)", false); - - String targetTableName = "view_1"; - createTable(dbName, targetTableName,"(count int, id string)", false); - - // process lineage record, and send corresponding notification to Atlas - String[] args = new String[]{"-d", "./", "-p", "impala"}; - ImpalaLineageTool toolInstance = new ImpalaLineageTool(args); - toolInstance.importHImpalaEntities(impalaLineageHook, IMPALA, IMPALA_WAL); - - // verify the process is saved in Atlas - // the value is from info in IMPALA_3 - String createTime = new Long((long)(1554750072)*1000).toString(); - String processQFName = - "db_1.view_1" + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE + - CLUSTER_NAME + AtlasImpalaHookContext.QNAME_SEP_PROCESS + createTime; - - processQFName = processQFName.toLowerCase(); - - String queryString = "create view db_1.view_1 as select count, id from db_1.table_1"; - AtlasEntity processEntity1 = validateProcess(processQFName, queryString); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, queryString); - AtlasObjectId process1 = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseImpalaEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process1.getGuid(), processEntity1.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - - String guid = assertTableIsRegistered(dbName, targetTableName); - AtlasEntity entity = atlasClientV2.getEntityByGuid(guid).getEntity(); - List ddlQueries = (List) entity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - assertNotNull(ddlQueries); - assertEquals(ddlQueries.size(), 1); - } catch (Exception e) { - System.out.print("Appending file error"); - } - } - - /** - * This tests is for create view query with extra comment and spaces added in between: - * 1) ImpalaLineageTool can parse one lineage file that contains " create view" command lineage - * 2) Lineage is sent to Atlas - * 3) Atlas can get this lineage from Atlas - */ - @Test - public void testCreateViewWithCommentSpacesFromFile() { - // this file contains a single lineage record for "create view". - // It has table vertex with createTime - String IMPALA = dir + "impalaCreateViewWithCommentSpaces.json"; - String IMPALA_WAL = dir + "WALimpala.wal"; - - List lineageList = new ArrayList<>(); - ImpalaLineageHook impalaLineageHook = new ImpalaLineageHook(); - - try { - // create database and tables to simulate Impala behavior that Impala updates metadata - // to HMS and HMSHook sends the metadata to Atlas, which has to happen before - // Atlas can handle lineage notification - String dbName = "db_8"; - createDatabase(dbName); - - String sourceTableName = "table_1"; - createTable(dbName, sourceTableName,"(id string, count int)", false); - - String targetTableName = "view_1"; - createTable(dbName, targetTableName,"(count int, id string)", false); - - // process lineage record, and send corresponding notification to Atlas - String[] args = new String[]{"-d", "./", "-p", "impala"}; - ImpalaLineageTool toolInstance = new ImpalaLineageTool(args); - toolInstance.importHImpalaEntities(impalaLineageHook, IMPALA, IMPALA_WAL); - - // verify the process is saved in Atlas - // the value is from info in IMPALA_3 - String createTime = new Long((long)(1554750072)*1000).toString(); - String processQFName = - "db_8.view_1" + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE + - CLUSTER_NAME + AtlasImpalaHookContext.QNAME_SEP_PROCESS + createTime; - - processQFName = processQFName.toLowerCase(); - - String queryString = " create /* comment1 */ view db_8.view_1 as select /* comment2 */ count, id from db_8.table_1"; - AtlasEntity processEntity1 = validateProcess(processQFName, queryString); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, queryString); - AtlasObjectId process1 = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseImpalaEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process1.getGuid(), processEntity1.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - - String guid = assertTableIsRegistered(dbName, targetTableName); - AtlasEntity entity = atlasClientV2.getEntityByGuid(guid).getEntity(); - List ddlQueries = (List) entity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - assertNotNull(ddlQueries); - assertEquals(ddlQueries.size(), 1); - } catch (Exception e) { - System.out.print("Appending file error"); - } - } - - /** - * This tests - * 1) ImpalaLineageTool can parse one lineage file that contains "create view" command lineage, - * but there is no table vertex with createTime. - * 2) Lineage is sent to Atlas - * 3) Atlas can get this lineage from Atlas - */ - @Test - public void testCreateViewNoCreateTimeFromFile() { - // this file contains a single lineage record for "create view". - // there is no table vertex with createTime, which is lineage record generated by Impala - // originally. The table create time is hard-coded before Impala fixes this issue. - String IMPALA = dir + "impalaCreateViewNoCreateTime.json"; - String IMPALA_WAL = dir + "WALimpala.wal"; - - List lineageList = new ArrayList<>(); - ImpalaLineageHook impalaLineageHook = new ImpalaLineageHook(); - - try { - // create database and tables to simulate Impala behavior that Impala updates metadata - // to HMS and HMSHook sends the metadata to Atlas, which has to happen before - // Atlas can handle lineage notification - String dbName = "db_2"; - createDatabase(dbName); - - String sourceTableName = "table_1"; - createTable(dbName, sourceTableName,"(id string, count int)", false); - - String targetTableName = "view_1"; - createTable(dbName, targetTableName,"(count int, id string)", false); - - // process lineage record, and send corresponding notification to Atlas - String[] args = new String[]{"-d", "./", "-p", "impala"}; - ImpalaLineageTool toolInstance = new ImpalaLineageTool(args); - Long beforeCreateTime = System.currentTimeMillis() / BaseImpalaEvent.MILLIS_CONVERT_FACTOR; - toolInstance.importHImpalaEntities(impalaLineageHook, IMPALA, IMPALA_WAL); - Long afterCreateTime = System.currentTimeMillis() / BaseImpalaEvent.MILLIS_CONVERT_FACTOR; - - String processQFNameWithoutTime = - dbName + "." + targetTableName + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE + - CLUSTER_NAME + AtlasImpalaHookContext.QNAME_SEP_PROCESS; - processQFNameWithoutTime = processQFNameWithoutTime.toLowerCase(); - - List processQFNames = new ArrayList<>(); - String createTime = new Long(beforeCreateTime.longValue()*1000).toString(); - processQFNames.add(processQFNameWithoutTime + createTime); - - if (beforeCreateTime != afterCreateTime) { - createTime = new Long(afterCreateTime.longValue() * 1000).toString(); - processQFNames.add(processQFNameWithoutTime + createTime); - } - - // verify the process is saved in Atlas. the value is from info in IMPALA_4. - // There is no createTime in lineage record, so we don't know the process qualified name - // And can only verify the process is created for the given query. - String queryString = "create view " + dbName + "." + targetTableName + " as select count, id from " + dbName + "." + sourceTableName; - AtlasEntity processEntity1 = validateProcess(processQFNames, queryString); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, queryString); - AtlasObjectId process1 = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseImpalaEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process1.getGuid(), processEntity1.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - - String guid = assertTableIsRegistered(dbName, targetTableName); - AtlasEntity entity = atlasClientV2.getEntityByGuid(guid).getEntity(); - List ddlQueries = (List) entity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - assertNotNull(ddlQueries); - assertEquals(ddlQueries.size(), 1); - } catch (Exception e) { - System.out.print("Appending file error"); - } - } - - /** - * This tests - * 1) ImpalaLineageTool can parse one lineage file that contains "create table as select" command lineage, - * there is table vertex with createTime. - * 2) Lineage is sent to Atlas - * 3) Atlas can get this lineage from Atlas - */ - @Test - public void testCreateTableAsSelectFromFile() throws Exception { - String IMPALA = dir + "impalaCreateTableAsSelect.json"; - String IMPALA_WAL = dir + "WALimpala.wal"; - - ImpalaLineageHook impalaLineageHook = new ImpalaLineageHook(); - - // create database and tables to simulate Impala behavior that Impala updates metadata - // to HMS and HMSHook sends the metadata to Atlas, which has to happen before - // Atlas can handle lineage notification - String dbName = "db_3"; - createDatabase(dbName); - - String sourceTableName = "table_1"; - createTable(dbName, sourceTableName,"(id string, count int)", false); - - String targetTableName = "table_2"; - createTable(dbName, targetTableName,"(count int, id string)", false); - - // process lineage record, and send corresponding notification to Atlas - String[] args = new String[]{"-d", "./", "-p", "impala"}; - ImpalaLineageTool toolInstance = new ImpalaLineageTool(args); - toolInstance.importHImpalaEntities(impalaLineageHook, IMPALA, IMPALA_WAL); - - // verify the process is saved in Atlas - // the value is from info in IMPALA_4. - String createTime = new Long(TABLE_CREATE_TIME*1000).toString(); - String processQFName = - dbName + "." + targetTableName + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE + - CLUSTER_NAME + AtlasImpalaHookContext.QNAME_SEP_PROCESS + createTime; - - processQFName = processQFName.toLowerCase(); - - String queryString = "create table " + dbName + "." + targetTableName + " as select count, id from " + dbName + "." + sourceTableName; - AtlasEntity processEntity1 = validateProcess(processQFName, queryString); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, queryString); - AtlasObjectId process1 = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseImpalaEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process1.getGuid(), processEntity1.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - - String guid = assertTableIsRegistered(dbName, targetTableName); - AtlasEntity entity = atlasClientV2.getEntityByGuid(guid).getEntity(); - List ddlQueries = (List) entity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - assertNotNull(ddlQueries); - assertEquals(ddlQueries.size(), 1); - } - - /** - * This tests is based on extra comment and spaces adding to create table as select query - * 1) ImpalaLineageTool can parse one lineage file that contains "create table as select" command lineage, - * there is table vertex with createTime. - * 2) Lineage is sent to Atlas - * 3) Atlas can get this lineage from Atlas - */ - @Test - public void testCreateTableAsSelectWithCommentSpacesFromFile() throws Exception { - String IMPALA = dir + "impalaCreateTableAsSelectWithCommentSpaces.json"; - String IMPALA_WAL = dir + "WALimpala.wal"; - - ImpalaLineageHook impalaLineageHook = new ImpalaLineageHook(); - - // create database and tables to simulate Impala behavior that Impala updates metadata - // to HMS and HMSHook sends the metadata to Atlas, which has to happen before - // Atlas can handle lineage notification - String dbName = "db_9"; - createDatabase(dbName); - - String sourceTableName = "table_1"; - createTable(dbName, sourceTableName,"(id string, count int)", false); - - String targetTableName = "table_2"; - createTable(dbName, targetTableName,"(count int, id string)", false); - - // process lineage record, and send corresponding notification to Atlas - String[] args = new String[]{"-d", "./", "-p", "impala"}; - ImpalaLineageTool toolInstance = new ImpalaLineageTool(args); - toolInstance.importHImpalaEntities(impalaLineageHook, IMPALA, IMPALA_WAL); - - // verify the process is saved in Atlas - // the value is from info in IMPALA_4. - String createTime = new Long(TABLE_CREATE_TIME*1000).toString(); - String processQFName = - dbName + "." + targetTableName + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE + - CLUSTER_NAME + AtlasImpalaHookContext.QNAME_SEP_PROCESS + createTime; - - processQFName = processQFName.toLowerCase(); - - String queryString = "create /* Test */ table " + dbName + "." - + targetTableName + " as /* Test */ select count, id from " + dbName + "." + sourceTableName; - AtlasEntity processEntity1 = validateProcess(processQFName, queryString); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, queryString); - AtlasObjectId process1 = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseImpalaEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process1.getGuid(), processEntity1.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - - String guid = assertTableIsRegistered(dbName, targetTableName); - AtlasEntity entity = atlasClientV2.getEntityByGuid(guid).getEntity(); - List ddlQueries = (List) entity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - assertNotNull(ddlQueries); - assertEquals(ddlQueries.size(), 1); - } - - /** - * This tests - * 1) ImpalaLineageTool can parse one lineage file that contains "alter view as select" command lineage, - * there is table vertex with createTime. - * 2) Lineage is sent to Atlas - * 3) Atlas can get this lineage from Atlas - */ - @Test - public void testAlterViewAsSelectFromFile() throws Exception { - String IMPALA = dir + "impalaAlterViewAsSelect.json"; - String IMPALA_WAL = dir + "WALimpala.wal"; - - ImpalaLineageHook impalaLineageHook = new ImpalaLineageHook(); - - // create database and tables to simulate Impala behavior that Impala updates metadata - // to HMS and HMSHook sends the metadata to Atlas, which has to happen before - // Atlas can handle lineage notification - String dbName = "db_4"; - createDatabase(dbName); - - String sourceTableName = "table_1"; - createTable(dbName, sourceTableName,"(id string, count int)", false); - - String targetTableName = "view_1"; - createTable(dbName, targetTableName,"(count int, id string)", false); - - // process lineage record, and send corresponding notification to Atlas - String[] args = new String[]{"-d", "./", "-p", "impala"}; - ImpalaLineageTool toolInstance = new ImpalaLineageTool(args); - toolInstance.importHImpalaEntities(impalaLineageHook, IMPALA, IMPALA_WAL); - - // verify the process is saved in Atlas - // the value is from info in IMPALA_4. - String createTime = new Long(TABLE_CREATE_TIME*1000).toString(); - String processQFName = - dbName + "." + targetTableName + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE + - CLUSTER_NAME + AtlasImpalaHookContext.QNAME_SEP_PROCESS + createTime; - - processQFName = processQFName.toLowerCase(); - - String queryString = "alter view " + dbName + "." + targetTableName + " as select count, id from " + dbName + "." + sourceTableName; - AtlasEntity processEntity1 = validateProcess(processQFName, queryString); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, queryString); - AtlasObjectId process1 = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseImpalaEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process1.getGuid(), processEntity1.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - - String guid = assertTableIsRegistered(dbName, targetTableName); - AtlasEntity entity = atlasClientV2.getEntityByGuid(guid).getEntity(); - List ddlQueries = (List) entity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - assertNotNull(ddlQueries); - assertEquals(ddlQueries.size(), 1); - } - - /** - * This tests is for extra comment and spaces present in alter view as select query - * 1) ImpalaLineageTool can parse one lineage file that contains "alter view as select" command lineage, - * there is table vertex with createTime. - * 2) Lineage is sent to Atlas - * 3) Atlas can get this lineage from Atlas - */ - @Test - public void testAlterViewAsSelectWithCommentSpacesFromFile() throws Exception { - String IMPALA = dir + "impalaAlterViewAsSelectWithCommentSpaces.json"; - String IMPALA_WAL = dir + "WALimpala.wal"; - - ImpalaLineageHook impalaLineageHook = new ImpalaLineageHook(); - - // create database and tables to simulate Impala behavior that Impala updates metadata - // to HMS and HMSHook sends the metadata to Atlas, which has to happen before - // Atlas can handle lineage notification - String dbName = "db_10"; - createDatabase(dbName); - - String sourceTableName = "table_1"; - createTable(dbName, sourceTableName,"(id string, count int)", false); - - String targetTableName = "view_1"; - createTable(dbName, targetTableName,"(count int, id string)", false); - - // process lineage record, and send corresponding notification to Atlas - String[] args = new String[]{"-d", "./", "-p", "impala"}; - ImpalaLineageTool toolInstance = new ImpalaLineageTool(args); - toolInstance.importHImpalaEntities(impalaLineageHook, IMPALA, IMPALA_WAL); - - // verify the process is saved in Atlas - // the value is from info in IMPALA_4. - String createTime = new Long(TABLE_CREATE_TIME*1000).toString(); - String processQFName = - dbName + "." + targetTableName + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE + - CLUSTER_NAME + AtlasImpalaHookContext.QNAME_SEP_PROCESS + createTime; - - processQFName = processQFName.toLowerCase(); - - String queryString = "alter /* comment1 */ view " + dbName + "." + targetTableName - + " as select /* comment1 */ count, id from " + dbName + "." + sourceTableName; - AtlasEntity processEntity1 = validateProcess(processQFName, queryString); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, queryString); - AtlasObjectId process1 = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseImpalaEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process1.getGuid(), processEntity1.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - - String guid = assertTableIsRegistered(dbName, targetTableName); - AtlasEntity entity = atlasClientV2.getEntityByGuid(guid).getEntity(); - List ddlQueries = (List) entity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - assertNotNull(ddlQueries); - assertEquals(ddlQueries.size(), 1); - } - - /** - * This tests - * 1) ImpalaLineageTool can parse one lineage file that contains "insert into" command lineage, - * there is table vertex with createTime. - * 2) Lineage is sent to Atlas - * 3) Atlas can get this lineage from Atlas - */ - @Test - public void testInsertIntoAsSelectFromFile() throws Exception { - String IMPALA = dir + "impalaInsertIntoAsSelect.json"; - String IMPALA_WAL = dir + "WALimpala.wal"; - - ImpalaLineageHook impalaLineageHook = new ImpalaLineageHook(); - - // create database and tables to simulate Impala behavior that Impala updates metadata - // to HMS and HMSHook sends the metadata to Atlas, which has to happen before - // Atlas can handle lineage notification - String dbName = "db_5"; - createDatabase(dbName); - - String sourceTableName = "table_1"; - createTable(dbName, sourceTableName,"(id string, count int)", false); - - String targetTableName = "table_2"; - createTable(dbName, targetTableName,"(count int, id string, int_col int)", false); - - // process lineage record, and send corresponding notification to Atlas - String[] args = new String[]{"-d", "./", "-p", "impala"}; - ImpalaLineageTool toolInstance = new ImpalaLineageTool(args); - toolInstance.importHImpalaEntities(impalaLineageHook, IMPALA, IMPALA_WAL); - - // verify the process is saved in Atlas - // the value is from info in IMPALA_4. - String createTime1 = new Long(TABLE_CREATE_TIME_SOURCE*1000).toString(); - String createTime2 = new Long(TABLE_CREATE_TIME*1000).toString(); - String sourceQFName = dbName + "." + sourceTableName + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE + - CLUSTER_NAME + AtlasImpalaHookContext.QNAME_SEP_PROCESS + createTime1; - String targetQFName = dbName + "." + targetTableName + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE + - CLUSTER_NAME + AtlasImpalaHookContext.QNAME_SEP_PROCESS + createTime2; - String processQFName = "QUERY:" + sourceQFName.toLowerCase() + "->:INSERT:" + targetQFName.toLowerCase(); - - String queryString = "insert into table " + dbName + "." + targetTableName + " (count, id) select count, id from " + dbName + "." + sourceTableName; - AtlasEntity processEntity1 = validateProcess(processQFName, queryString); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, queryString); - AtlasObjectId process1 = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseImpalaEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process1.getGuid(), processEntity1.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - - String guid = assertTableIsRegistered(dbName, targetTableName); - AtlasEntity entity = atlasClientV2.getEntityByGuid(guid).getEntity(); - List ddlQueries = (List) entity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - assertNotNull(ddlQueries); - assertEquals(ddlQueries.size(), 0); - } - - /** - * This tests - * 1) ImpalaLineageTool can parse one lineage file that contains multiple "insert into" command lineages, - * there is table vertex with createTime. - * 2) Lineage is sent to Atlas - * 3) Atlas can get these lineages from Atlas - */ - @Test - public void testMultipleInsertIntoAsSelectFromFile() throws Exception { - String IMPALA = dir + "impalaMultipleInsertIntoAsSelect1.json"; - String IMPALA_WAL = dir + "WALimpala.wal"; - - ImpalaLineageHook impalaLineageHook = new ImpalaLineageHook(); - - // create database and tables to simulate Impala behavior that Impala updates metadata - // to HMS and HMSHook sends the metadata to Atlas, which has to happen before - // Atlas can handle lineage notification - String dbName = "db_6"; - createDatabase(dbName); - - String sourceTableName = "table_1"; - createTable(dbName, sourceTableName,"(id string, count int)", false); - - String targetTableName = "table_2"; - createTable(dbName, targetTableName,"(count int, id string, int_col int)", false); - - // process lineage record, and send corresponding notification to Atlas - String[] args = new String[]{"-d", "./", "-p", "impala"}; - ImpalaLineageTool toolInstance = new ImpalaLineageTool(args); - toolInstance.importHImpalaEntities(impalaLineageHook, IMPALA, IMPALA_WAL); - - // re-run the same lineage record, should have the same process entity and another process execution entity - Thread.sleep(5000); - IMPALA = dir + "impalaMultipleInsertIntoAsSelect2.json"; - toolInstance.importHImpalaEntities(impalaLineageHook, IMPALA, IMPALA_WAL); - Thread.sleep(5000); - - // verify the process is saved in Atlas - // the value is from info in IMPALA_4. - String createTime1 = new Long(TABLE_CREATE_TIME_SOURCE*1000).toString(); - String createTime2 = new Long(TABLE_CREATE_TIME*1000).toString(); - String sourceQFName = dbName + "." + sourceTableName + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE + - CLUSTER_NAME + AtlasImpalaHookContext.QNAME_SEP_PROCESS + createTime1; - String targetQFName = dbName + "." + targetTableName + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE + - CLUSTER_NAME + AtlasImpalaHookContext.QNAME_SEP_PROCESS + createTime2; - String processQFName = "QUERY:" + sourceQFName.toLowerCase() + "->:INSERT:" + targetQFName.toLowerCase(); - - String queryString = "insert into table " + dbName + "." + targetTableName + " (count, id) select count, id from " + dbName + "." + sourceTableName; - queryString = queryString.toLowerCase().trim(); - String queryString2 = queryString; - - Thread.sleep(5000); - AtlasEntity processEntity1 = validateProcess(processQFName, queryString); - - List processExecutions = toAtlasObjectIdList(processEntity1.getRelationshipAttribute( - BaseImpalaEvent.ATTRIBUTE_PROCESS_EXECUTIONS)); - Assert.assertEquals(processExecutions.size(), 2); - for (AtlasObjectId processExecutionId : processExecutions) { - AtlasEntity.AtlasEntityWithExtInfo atlasEntityWithExtInfo = atlasClientV2. - getEntityByGuid(processExecutionId.getGuid()); - - AtlasEntity processExecutionEntity = atlasEntityWithExtInfo.getEntity(); - String entityQueryText = String.valueOf(processExecutionEntity.getAttribute(ATTRIBUTE_QUERY_TEXT)).toLowerCase().trim(); - if (!(queryString.equalsIgnoreCase(entityQueryText) || queryString2.equalsIgnoreCase(entityQueryText))) { - String errorMessage = String.format("process query text '%s' does not match expected value of '%s' or '%s'", entityQueryText, queryString, queryString2); - Assert.assertTrue(false, errorMessage); - } - } - - String guid = assertTableIsRegistered(dbName, targetTableName); - AtlasEntity entity = atlasClientV2.getEntityByGuid(guid).getEntity(); - List ddlQueries = (List) entity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - assertNotNull(ddlQueries); - assertEquals(ddlQueries.size(), 0); - } - - /** - * This tests - * 1) ImpalaLineageTool can parse one lineage file that contains "create table as select" command lineage, - * there is table vertex with createTime. The target vertex's vertexId does not contain db name and table name - * 2) Lineage is sent to Atlas - * 3) Atlas can get this lineage from Atlas - */ - @Test - public void testCreateTableAsSelectVertexIdNoTableNameFromFile() throws Exception { - String IMPALA = dir + "impalaCreateTableAsSelectVertexIdNoTableName.json"; - String IMPALA_WAL = dir + "WALimpala.wal"; - - ImpalaLineageHook impalaLineageHook = new ImpalaLineageHook(); - - // create database and tables to simulate Impala behavior that Impala updates metadata - // to HMS and HMSHook sends the metadata to Atlas, which has to happen before - // Atlas can handle lineage notification - String dbName = "sales_db"; - createDatabase(dbName); - - String sourceTableName = "sales_asia"; - createTable(dbName, sourceTableName,"(id string, name string)", false); - - String targetTableName = "sales_china"; - createTable(dbName, targetTableName,"(id string, name string)", false); - - // process lineage record, and send corresponding notification to Atlas - String[] args = new String[]{"-d", "./", "-p", "impala"}; - ImpalaLineageTool toolInstance = new ImpalaLineageTool(args); - toolInstance.importHImpalaEntities(impalaLineageHook, IMPALA, IMPALA_WAL); - - // verify the process is saved in Atlas - // the value is from info in IMPALA_4. - String createTime = new Long((long)1560885039*1000).toString(); - String processQFName = - dbName + "." + targetTableName + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE + - CLUSTER_NAME + AtlasImpalaHookContext.QNAME_SEP_PROCESS + createTime; - - processQFName = processQFName.toLowerCase(); - - String queryString = "create table " + targetTableName + " as select * from " + sourceTableName; - AtlasEntity processEntity1 = validateProcess(processQFName, queryString); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, queryString); - AtlasObjectId process1 = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseImpalaEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process1.getGuid(), processEntity1.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - - String guid = assertTableIsRegistered(dbName, targetTableName); - AtlasEntity entity = atlasClientV2.getEntityByGuid(guid).getEntity(); - List ddlQueries = (List) entity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - assertNotNull(ddlQueries); - assertEquals(ddlQueries.size(), 1); - } -} \ No newline at end of file diff --git a/addons/impala-bridge/src/test/java/org/apache/atlas/impala/hook/ImpalaLineageHookIT.java b/addons/impala-bridge/src/test/java/org/apache/atlas/impala/hook/ImpalaLineageHookIT.java deleted file mode 100644 index 56d74fee3de..00000000000 --- a/addons/impala-bridge/src/test/java/org/apache/atlas/impala/hook/ImpalaLineageHookIT.java +++ /dev/null @@ -1,165 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.impala.hook; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import org.apache.atlas.impala.ImpalaLineageITBase; -import org.apache.atlas.impala.hook.events.BaseImpalaEvent; -import org.apache.atlas.impala.model.ImpalaDependencyType; -import org.apache.atlas.impala.model.ImpalaVertexType; -import org.apache.atlas.impala.model.LineageEdge; -import org.apache.atlas.impala.model.ImpalaQuery; -import org.apache.atlas.impala.model.LineageVertex; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.testng.Assert; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.AfterClass; -import org.testng.annotations.Test; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotNull; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static org.apache.atlas.impala.hook.events.BaseImpalaEvent.ATTRIBUTE_DDL_QUERIES; -import static org.testng.Assert.assertFalse; - -public class ImpalaLineageHookIT extends ImpalaLineageITBase { - private static final Logger LOG = LoggerFactory.getLogger(ImpalaLineageHookIT.class); - private static ImpalaLineageHook impalaHook; - - @BeforeClass - public void setUp() throws Exception { - super.setUp(); - impalaHook = new ImpalaLineageHook(); - } - - @AfterClass - public void testClean() { - impalaHook = null; - } - - @Test - public void testCreateView() throws Exception { - // first trigger HMS hook to create related entities - String dbName = createDatabase(); - assertDatabaseIsRegistered(dbName); - - String tableName = createTable(dbName, "(id string, count int)"); - String viewName = createTable(dbName, "(count int, id string)"); - - // then process lineage record to push lineage to Atlas - ImpalaQuery queryObj = new ImpalaQuery(); - List edges = new ArrayList<>(); - List vertices = new ArrayList<>(); - - queryObj.setQueryText("create view " + viewName + " as select count, id from " + tableName); - queryObj.setQueryId("3a441d0c130962f8:7f634aec00000000"); - queryObj.setHash("64ff0425ccdfaada53e3f2fd76f566f7"); - queryObj.setUser("admin"); - queryObj.setTimestamp((long)1554750072); - queryObj.setEndTime((long)1554750554); - - LineageEdge edge1 = new LineageEdge(); - edge1.setSources( Arrays.asList((long)1)); - edge1.setTargets( Arrays.asList((long)0)); - edge1.setEdgeType(ImpalaDependencyType.PROJECTION); - edges.add(edge1); - - LineageEdge edge2 = new LineageEdge(); - edge2.setSources( Arrays.asList((long)3)); - edge2.setTargets( Arrays.asList((long)2)); - edge2.setEdgeType(ImpalaDependencyType.PROJECTION); - edges.add(edge2); - - queryObj.setEdges(edges); - - LineageVertex vertex1 = new LineageVertex(); - vertex1.setId((long)0); - vertex1.setVertexType(ImpalaVertexType.COLUMN); - vertex1.setVertexId(viewName + ".count"); - vertices.add(vertex1); - - LineageVertex vertex2 = new LineageVertex(); - vertex2.setId((long)1); - vertex2.setVertexType(ImpalaVertexType.COLUMN); - vertex2.setVertexId(tableName + ".count"); - vertices.add(vertex2); - - LineageVertex vertex3 = new LineageVertex(); - vertex3.setId((long)2); - vertex3.setVertexType(ImpalaVertexType.COLUMN); - vertex3.setVertexId(viewName + ".id"); - vertices.add(vertex3); - - LineageVertex vertex4 = new LineageVertex(); - vertex4.setId((long)3); - vertex4.setVertexType(ImpalaVertexType.COLUMN); - vertex4.setVertexId(tableName + ".id"); - vertices.add(vertex4); - - LineageVertex vertex5 = new LineageVertex(); - vertex5.setId((long)4); - vertex5.setVertexType(ImpalaVertexType.TABLE); - vertex5.setVertexId(viewName); - vertex5.setCreateTime(System.currentTimeMillis() / 1000); - vertices.add(vertex5); - - LineageVertex vertex6 = new LineageVertex(); - vertex6.setId((long)5); - vertex6.setVertexType(ImpalaVertexType.TABLE); - vertex6.setVertexId(tableName); - vertex6.setCreateTime(System.currentTimeMillis() / 1000); - vertices.add(vertex6); - - queryObj.setVertices(vertices); - - try { - impalaHook.process(queryObj); - String createTime = new Long(BaseImpalaEvent.getTableCreateTime(vertex5)).toString(); - String processQFName = - vertex5.getVertexId() + AtlasImpalaHookContext.QNAME_SEP_METADATA_NAMESPACE + - CLUSTER_NAME + AtlasImpalaHookContext.QNAME_SEP_PROCESS + createTime; - - processQFName = processQFName.toLowerCase(); - - // check process and process execution entities - AtlasEntity processEntity1 = validateProcess(processQFName, queryObj.getQueryText()); - AtlasEntity processExecutionEntity1 = validateProcessExecution(processEntity1, queryObj.getQueryText()); - AtlasObjectId process1 = toAtlasObjectId(processExecutionEntity1.getRelationshipAttribute( - BaseImpalaEvent.ATTRIBUTE_PROCESS)); - Assert.assertEquals(process1.getGuid(), processEntity1.getGuid()); - Assert.assertEquals(numberOfProcessExecutions(processEntity1), 1); - - // check DDL entity - String viewId = assertTableIsRegistered(viewName); - AtlasEntity entity = atlasClientV2.getEntityByGuid(viewId).getEntity(); - List ddlQueries = (List) entity.getRelationshipAttribute(ATTRIBUTE_DDL_QUERIES); - - assertNotNull(ddlQueries); - assertEquals(ddlQueries.size(), 1); - } catch (Exception ex) { - LOG.error("process create_view failed: ", ex); - assertFalse(true); - } - } -} diff --git a/addons/impala-bridge/src/test/resources/atlas-application.properties b/addons/impala-bridge/src/test/resources/atlas-application.properties deleted file mode 100644 index 898b69c999e..00000000000 --- a/addons/impala-bridge/src/test/resources/atlas-application.properties +++ /dev/null @@ -1,124 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# - -######### Atlas Server Configs ######### -atlas.rest.address=http://localhost:31000 - -######### Graph Database Configs ######### - - -# Graph database implementation. Value inserted by maven. -atlas.graphdb.backend=org.apache.atlas.repository.graphdb.janus.AtlasJanusGraphDatabase - -# Graph Storage -atlas.graph.storage.backend=berkeleyje - -# Entity repository implementation -atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.InMemoryEntityAuditRepository - -# Graph Search Index Backend -atlas.graph.index.search.backend=solr - -#Berkeley storage directory -atlas.graph.storage.directory=${sys:atlas.data}/berkley - -#hbase -#For standalone mode , specify localhost -#for distributed mode, specify zookeeper quorum here - -atlas.graph.storage.hostname=${graph.storage.hostname} -atlas.graph.storage.hbase.regions-per-server=1 -atlas.graph.storage.lock.wait-time=10000 - -#ElasticSearch -atlas.graph.index.search.directory=${sys:atlas.data}/es -atlas.graph.index.search.elasticsearch.client-only=false -atlas.graph.index.search.elasticsearch.local-mode=true -atlas.graph.index.search.elasticsearch.create.sleep=2000 - -# Solr cloud mode properties -atlas.graph.index.search.solr.mode=cloud -atlas.graph.index.search.solr.zookeeper-url=${solr.zk.address} -atlas.graph.index.search.solr.embedded=true -atlas.graph.index.search.max-result-set-size=150 - - -######### Notification Configs ######### -atlas.notification.embedded=true - -atlas.kafka.zookeeper.connect=localhost:19026 -atlas.kafka.bootstrap.servers=localhost:19027 -atlas.kafka.data=${sys:atlas.data}/kafka -atlas.kafka.zookeeper.session.timeout.ms=4000 -atlas.kafka.zookeeper.sync.time.ms=20 -atlas.kafka.consumer.timeout.ms=4000 -atlas.kafka.auto.commit.interval.ms=100 -atlas.kafka.hook.group.id=atlas -atlas.kafka.entities.group.id=atlas_entities -#atlas.kafka.auto.commit.enable=false - -atlas.kafka.enable.auto.commit=false -atlas.kafka.auto.offset.reset=earliest -atlas.kafka.session.timeout.ms=30000 -atlas.kafka.offsets.topic.replication.factor=1 - - - -######### Entity Audit Configs ######### -atlas.audit.hbase.tablename=ATLAS_ENTITY_AUDIT_EVENTS -atlas.audit.zookeeper.session.timeout.ms=1000 -atlas.audit.hbase.zookeeper.quorum=localhost -atlas.audit.hbase.zookeeper.property.clientPort=19026 - -######### Security Properties ######### - -# SSL config -atlas.enableTLS=false -atlas.server.https.port=31443 - -######### Security Properties ######### - -hbase.security.authentication=simple - -atlas.hook.falcon.synchronous=true - -######### JAAS Configuration ######## - -atlas.jaas.KafkaClient.loginModuleName = com.sun.security.auth.module.Krb5LoginModule -atlas.jaas.KafkaClient.loginModuleControlFlag = required -atlas.jaas.KafkaClient.option.useKeyTab = true -atlas.jaas.KafkaClient.option.storeKey = true -atlas.jaas.KafkaClient.option.serviceName = kafka -atlas.jaas.KafkaClient.option.keyTab = /etc/security/keytabs/atlas.service.keytab -atlas.jaas.KafkaClient.option.principal = atlas/_HOST@EXAMPLE.COM - -######### High Availability Configuration ######## -atlas.server.ha.enabled=false -#atlas.server.ids=id1 -#atlas.server.address.id1=localhost:21000 - -######### Atlas Authorization ######### -atlas.authorizer.impl=none -# atlas.authorizer.impl=simple -# atlas.authorizer.simple.authz.policy.file=atlas-simple-authz-policy.json - -######### Atlas Authentication ######### -atlas.authentication.method.file=true -atlas.authentication.method.ldap.type=none -atlas.authentication.method.kerberos=false -# atlas.authentication.method.file.filename=users-credentials.properties diff --git a/addons/impala-bridge/src/test/resources/atlas-log4j.xml b/addons/impala-bridge/src/test/resources/atlas-log4j.xml deleted file mode 100644 index c661d36f814..00000000000 --- a/addons/impala-bridge/src/test/resources/atlas-log4j.xml +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/impala-bridge/src/test/resources/hive-site.xml b/addons/impala-bridge/src/test/resources/hive-site.xml deleted file mode 100644 index edd0c543139..00000000000 --- a/addons/impala-bridge/src/test/resources/hive-site.xml +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - hive.exec.submit.local.task.via.child - false - - - - mapreduce.framework.name - local - - - - fs.default.name - file:/// - - - - hive.metastore.event.listeners - org.apache.atlas.hive.hook.HiveMetastoreHookImpl - - - - hive.support.concurrency - false - - - - hive.metastore.warehouse.dir - ${project.basedir}/target/metastore - - - - javax.jdo.option.ConnectionURL - jdbc:derby:;databaseName=${project.basedir}/target/metastore_db;create=true - - - - atlas.hook.hive.synchronous - true - - - - fs.pfile.impl - org.apache.hadoop.fs.ProxyLocalFileSystem - - - - hive.in.test - true - - - - hive.zookeeper.quorum - localhost:19026 - - - - hive.metastore.schema.verification - false - - - - hive.metastore.disallow.incompatible.col.type.changes - false - - - - datanucleus.schema.autoCreateAll - true - - - - hive.exec.scratchdir - ${project.basedir}/target/scratchdir - - - \ No newline at end of file diff --git a/addons/impala-bridge/src/test/resources/impalaAlterViewAsSelect.json b/addons/impala-bridge/src/test/resources/impalaAlterViewAsSelect.json deleted file mode 100644 index aca2661e814..00000000000 --- a/addons/impala-bridge/src/test/resources/impalaAlterViewAsSelect.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "queryText":"alter view db_4.view_1 as select count, id from db_4.table_1", - "queryId":"3a441d0c130962f8:7f634aec00000000", - "hash":"64ff0425ccdfaada53e3f2fd76f566f7", - "user":"admin", - "timestamp":1554750072, - "endTime":1554750554, - "edges":[ - { - "sources":[ - 1 - ], - "targets":[ - 0 - ], - "edgeType":"PROJECTION" - }, - { - "sources":[ - 3 - ], - "targets":[ - 2 - ], - "edgeType":"PROJECTION" - } - ], - "vertices":[ - { - "id":0, - "vertexType":"COLUMN", - "vertexId":"db_4.view_1.count", - "metadata": { - "tableName": "db_4.view_1", - "tableCreateTime": 1554750072 - } - }, - { - "id":1, - "vertexType":"COLUMN", - "vertexId":"db_4.table_1.count", - "metadata": { - "tableName": "db_4.table_1", - "tableCreateTime": 1554750070 - } - }, - { - "id":2, - "vertexType":"COLUMN", - "vertexId":"db_4.view_1.id", - "metadata": { - "tableName": "db_4.view_1", - "tableCreateTime": 1554750072 - } - }, - { - "id":3, - "vertexType":"COLUMN", - "vertexId":"db_4.table_1.id", - "metadata": { - "tableName": "db_4.table_1", - "tableCreateTime": 1554750070 - } - } - ] -} \ No newline at end of file diff --git a/addons/impala-bridge/src/test/resources/impalaAlterViewAsSelectWithCommentSpaces.json b/addons/impala-bridge/src/test/resources/impalaAlterViewAsSelectWithCommentSpaces.json deleted file mode 100644 index 322abb5ea60..00000000000 --- a/addons/impala-bridge/src/test/resources/impalaAlterViewAsSelectWithCommentSpaces.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "queryText":"alter /* comment1 */ view db_10.view_1 as select /* comment1 */ count, id from db_10.table_1", - "queryId":"3a441d0c130962f8:7f634aec00000000", - "hash":"64ff0425ccdfaada53e3f2fd76f566f7", - "user":"admin", - "timestamp":1554750072, - "endTime":1554750554, - "edges":[ - { - "sources":[ - 1 - ], - "targets":[ - 0 - ], - "edgeType":"PROJECTION" - }, - { - "sources":[ - 3 - ], - "targets":[ - 2 - ], - "edgeType":"PROJECTION" - } - ], - "vertices":[ - { - "id":0, - "vertexType":"COLUMN", - "vertexId":"db_10.view_1.count", - "metadata": { - "tableName": "db_10.view_1", - "tableCreateTime": 1554750072 - } - }, - { - "id":1, - "vertexType":"COLUMN", - "vertexId":"db_10.table_1.count", - "metadata": { - "tableName": "db_10.table_1", - "tableCreateTime": 1554750070 - } - }, - { - "id":2, - "vertexType":"COLUMN", - "vertexId":"db_10.view_1.id", - "metadata": { - "tableName": "db_10.view_1", - "tableCreateTime": 1554750072 - } - }, - { - "id":3, - "vertexType":"COLUMN", - "vertexId":"db_10.table_1.id", - "metadata": { - "tableName": "db_10.table_1", - "tableCreateTime": 1554750070 - } - } - ] -} \ No newline at end of file diff --git a/addons/impala-bridge/src/test/resources/impalaCreateTableAsSelect.json b/addons/impala-bridge/src/test/resources/impalaCreateTableAsSelect.json deleted file mode 100644 index 7bf361c7676..00000000000 --- a/addons/impala-bridge/src/test/resources/impalaCreateTableAsSelect.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "queryText":"create table db_3.table_2 as select count, id from db_3.table_1", - "queryId":"3a441d0c130962f8:7f634aec00000000", - "hash":"64ff0425ccdfaada53e3f2fd76f566f7", - "user":"admin", - "timestamp":1554750072, - "endTime":1554750554, - "edges":[ - { - "sources":[ - 1 - ], - "targets":[ - 0 - ], - "edgeType":"PROJECTION" - }, - { - "sources":[ - 3 - ], - "targets":[ - 2 - ], - "edgeType":"PROJECTION" - } - ], - "vertices":[ - { - "id":0, - "vertexType":"COLUMN", - "vertexId":"db_3.table_2.count", - "metadata": { - "tableName": "db_3.table_2", - "tableCreateTime": 1554750072 - } - }, - { - "id":1, - "vertexType":"COLUMN", - "vertexId":"db_3.table_1.count", - "metadata": { - "tableName": "db_3.table_1", - "tableCreateTime": 1554750070 - } - }, - { - "id":2, - "vertexType":"COLUMN", - "vertexId":"db_3.table_2.id", - "metadata": { - "tableName": "db_3.table_2", - "tableCreateTime": 1554750072 - } - }, - { - "id":3, - "vertexType":"COLUMN", - "vertexId":"db_3.table_1.id", - "metadata": { - "tableName": "db_3.table_1", - "tableCreateTime": 1554750070 - } - } - ] -} \ No newline at end of file diff --git a/addons/impala-bridge/src/test/resources/impalaCreateTableAsSelectVertexIdNoTableName.json b/addons/impala-bridge/src/test/resources/impalaCreateTableAsSelectVertexIdNoTableName.json deleted file mode 100644 index 0fadcc89339..00000000000 --- a/addons/impala-bridge/src/test/resources/impalaCreateTableAsSelectVertexIdNoTableName.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "queryText":"create table sales_china as select * from sales_asia", - "queryId":"2940d0b242de53ea:e82ba8d300000000", - "hash":"a705a9ec851a5440afca0dfb8df86cd5", - "user":"root", - "timestamp":1560885032, - "endTime":1560885040, - "edges":[ - { - "sources":[ - 1 - ], - "targets":[ - 0 - ], - "edgeType":"PROJECTION" - }, - { - "sources":[ - 3 - ], - "targets":[ - 2 - ], - "edgeType":"PROJECTION" - } - ], - "vertices":[ - { - "id":0, - "vertexType":"COLUMN", - "vertexId":"id", - "metadata":{ - "tableName":"sales_db.sales_china", - "tableCreateTime":1560885039 - } - }, - { - "id":1, - "vertexType":"COLUMN", - "vertexId":"sales_db.sales_asia.id", - "metadata":{ - "tableName":"sales_db.sales_asia", - "tableCreateTime":1560884919 - } - }, - { - "id":2, - "vertexType":"COLUMN", - "vertexId":"name", - "metadata":{ - "tableName":"sales_db.sales_china", - "tableCreateTime":1560885039 - } - }, - { - "id":3, - "vertexType":"COLUMN", - "vertexId":"sales_db.sales_asia.name", - "metadata":{ - "tableName":"sales_db.sales_asia", - "tableCreateTime":1560884919 - } - } - ] -} \ No newline at end of file diff --git a/addons/impala-bridge/src/test/resources/impalaCreateTableAsSelectWithCommentSpaces.json b/addons/impala-bridge/src/test/resources/impalaCreateTableAsSelectWithCommentSpaces.json deleted file mode 100644 index f588190b09d..00000000000 --- a/addons/impala-bridge/src/test/resources/impalaCreateTableAsSelectWithCommentSpaces.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "queryText":"create /* Test */ table db_9.table_2 as /* Test */ select count, id from db_9.table_1", - "queryId":"3a441d0c130962f8:7f634aec00000000", - "hash":"64ff0425ccdfaada53e3f2fd76f566f7", - "user":"admin", - "timestamp":1554750072, - "endTime":1554750554, - "edges":[ - { - "sources":[ - 1 - ], - "targets":[ - 0 - ], - "edgeType":"PROJECTION" - }, - { - "sources":[ - 3 - ], - "targets":[ - 2 - ], - "edgeType":"PROJECTION" - } - ], - "vertices":[ - { - "id":0, - "vertexType":"COLUMN", - "vertexId":"db_9.table_2.count", - "metadata": { - "tableName": "db_9.table_2", - "tableCreateTime": 1554750072 - } - }, - { - "id":1, - "vertexType":"COLUMN", - "vertexId":"db_9.table_1.count", - "metadata": { - "tableName": "db_9.table_1", - "tableCreateTime": 1554750070 - } - }, - { - "id":2, - "vertexType":"COLUMN", - "vertexId":"db_9.table_2.id", - "metadata": { - "tableName": "db_9.table_2", - "tableCreateTime": 1554750072 - } - }, - { - "id":3, - "vertexType":"COLUMN", - "vertexId":"db_9.table_1.id", - "metadata": { - "tableName": "db_9.table_1", - "tableCreateTime": 1554750070 - } - } - ] -} \ No newline at end of file diff --git a/addons/impala-bridge/src/test/resources/impalaCreateView.json b/addons/impala-bridge/src/test/resources/impalaCreateView.json deleted file mode 100644 index bf55d9f7251..00000000000 --- a/addons/impala-bridge/src/test/resources/impalaCreateView.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "queryText":"create view db_1.view_1 as select count, id from db_1.table_1", - "queryId":"3a441d0c130962f8:7f634aec00000000", - "hash":"64ff0425ccdfaada53e3f2fd76f566f7", - "user":"admin", - "timestamp":1554750072, - "endTime":1554750554, - "edges":[ - { - "sources":[ - 1 - ], - "targets":[ - 0 - ], - "edgeType":"PROJECTION" - }, - { - "sources":[ - 3 - ], - "targets":[ - 2 - ], - "edgeType":"PROJECTION" - } - ], - "vertices":[ - { - "id":0, - "vertexType":"COLUMN", - "vertexId":"db_1.view_1.count", - "metadata": { - "tableName": "db_1.view_1", - "tableCreateTime": 1554750072 - } - }, - { - "id":1, - "vertexType":"COLUMN", - "vertexId":"db_1.table_1.count", - "metadata": { - "tableName": "db_1.table_1", - "tableCreateTime": 1554750070 - } - }, - { - "id":2, - "vertexType":"COLUMN", - "vertexId":"db_1.view_1.id", - "metadata": { - "tableName": "db_1.view_1", - "tableCreateTime": 1554750072 - } - }, - { - "id":3, - "vertexType":"COLUMN", - "vertexId":"db_1.table_1.id", - "metadata": { - "tableName": "db_1.table_1", - "tableCreateTime": 1554750070 - } - } - ] -} \ No newline at end of file diff --git a/addons/impala-bridge/src/test/resources/impalaCreateViewNoCreateTime.json b/addons/impala-bridge/src/test/resources/impalaCreateViewNoCreateTime.json deleted file mode 100644 index b825a386c90..00000000000 --- a/addons/impala-bridge/src/test/resources/impalaCreateViewNoCreateTime.json +++ /dev/null @@ -1,50 +0,0 @@ -{ - "queryText":"create view db_2.view_1 as select count, id from db_2.table_1", - "queryId":"5a441d0c130962f8:7f634aec00000000", - "hash":"64ff0425ccdfaada53e3f2fd76f566f7", - "user":"admin", - "timestamp":1554750072, - "endTime":1554750554, - "edges":[ - { - "sources":[ - 1 - ], - "targets":[ - 0 - ], - "edgeType":"PROJECTION" - }, - { - "sources":[ - 3 - ], - "targets":[ - 2 - ], - "edgeType":"PROJECTION" - } - ], - "vertices":[ - { - "id":0, - "vertexType":"COLUMN", - "vertexId":"db_2.view_1.count" - }, - { - "id":1, - "vertexType":"COLUMN", - "vertexId":"db_2.table_1.count" - }, - { - "id":2, - "vertexType":"COLUMN", - "vertexId":"db_2.view_1.id" - }, - { - "id":3, - "vertexType":"COLUMN", - "vertexId":"db_2.table_1.id" - } - ] -} \ No newline at end of file diff --git a/addons/impala-bridge/src/test/resources/impalaCreateViewWithCommentSpaces.json b/addons/impala-bridge/src/test/resources/impalaCreateViewWithCommentSpaces.json deleted file mode 100644 index e49b6b7c408..00000000000 --- a/addons/impala-bridge/src/test/resources/impalaCreateViewWithCommentSpaces.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "queryText":" create /* comment1 */ view db_8.view_1 as select /* comment2 */ count, id from db_8.table_1", - "queryId":"3a441d0c130962f8:7f634aec00000000", - "hash":"64ff0425ccdfaada53e3f2fd76f566f7", - "user":"admin", - "timestamp":1554750072, - "endTime":1554750554, - "edges":[ - { - "sources":[ - 1 - ], - "targets":[ - 0 - ], - "edgeType":"PROJECTION" - }, - { - "sources":[ - 3 - ], - "targets":[ - 2 - ], - "edgeType":"PROJECTION" - } - ], - "vertices":[ - { - "id":0, - "vertexType":"COLUMN", - "vertexId":"db_8.view_1.count", - "metadata": { - "tableName": "db_8.view_1", - "tableCreateTime": 1554750072 - } - }, - { - "id":1, - "vertexType":"COLUMN", - "vertexId":"db_8.table_1.count", - "metadata": { - "tableName": "db_8.table_1", - "tableCreateTime": 1554750070 - } - }, - { - "id":2, - "vertexType":"COLUMN", - "vertexId":"db_8.view_1.id", - "metadata": { - "tableName": "db_8.view_1", - "tableCreateTime": 1554750072 - } - }, - { - "id":3, - "vertexType":"COLUMN", - "vertexId":"db_8.table_1.id", - "metadata": { - "tableName": "db_8.table_1", - "tableCreateTime": 1554750070 - } - } - ] -} \ No newline at end of file diff --git a/addons/impala-bridge/src/test/resources/impalaInsertIntoAsSelect.json b/addons/impala-bridge/src/test/resources/impalaInsertIntoAsSelect.json deleted file mode 100644 index deb14669c92..00000000000 --- a/addons/impala-bridge/src/test/resources/impalaInsertIntoAsSelect.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "queryText":"insert into table db_5.table_2 (count, id) select count, id from db_5.table_1", - "queryId":"3a441d0c130962f8:7f634aec00000000", - "hash":"64ff0425ccdfaada53e3f2fd76f566f7", - "user":"admin", - "timestamp":1554750072, - "endTime":1554750554, - "edges":[ - { - "sources":[ - 1 - ], - "targets":[ - 0 - ], - "edgeType":"PROJECTION" - }, - { - "sources":[ - 3 - ], - "targets":[ - 2 - ], - "edgeType":"PROJECTION" - }, - { - "sources":[ - ], - "targets":[ - 4 - ], - "edgeType":"PROJECTION" - } - ], - "vertices":[ - { - "id":0, - "vertexType":"COLUMN", - "vertexId":"db_5.table_2.count", - "metadata": { - "tableName": "db_5.table_2", - "tableCreateTime": 1554750072 - } - }, - { - "id":1, - "vertexType":"COLUMN", - "vertexId":"db_5.table_1.count", - "metadata": { - "tableName": "db_5.table_1", - "tableCreateTime": 1554750070 - } - }, - { - "id":2, - "vertexType":"COLUMN", - "vertexId":"db_5.table_2.id", - "metadata": { - "tableName": "db_5.table_2", - "tableCreateTime": 1554750072 - } - }, - { - "id":3, - "vertexType":"COLUMN", - "vertexId":"db_5.table_1.id", - "metadata": { - "tableName": "db_5.table_1", - "tableCreateTime": 1554750070 - } - }, - { - "id":4, - "vertexType":"COLUMN", - "vertexId":"db_5.table_2.int_col", - "metadata": { - "tableName": "db_5.table_2", - "tableCreateTime": 1554750072 - } - } - ] -} \ No newline at end of file diff --git a/addons/impala-bridge/src/test/resources/impalaMultipleInsertIntoAsSelect1.json b/addons/impala-bridge/src/test/resources/impalaMultipleInsertIntoAsSelect1.json deleted file mode 100644 index 4e2783783f1..00000000000 --- a/addons/impala-bridge/src/test/resources/impalaMultipleInsertIntoAsSelect1.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "queryText":"insert into table db_6.table_2 (count, id) select count, id from db_6.table_1", - "queryId":"3a441d0c130962f8:7f634aec00000000", - "hash":"64ff0425ccdfaada53e3f2fd76f566f7", - "user":"admin", - "timestamp":1554750072, - "endTime":1554750554, - "edges":[ - { - "sources":[ - 1 - ], - "targets":[ - 0 - ], - "edgeType":"PROJECTION" - }, - { - "sources":[ - 3 - ], - "targets":[ - 2 - ], - "edgeType":"PROJECTION" - }, - { - "sources":[ - ], - "targets":[ - 4 - ], - "edgeType":"PROJECTION" - } - ], - "vertices":[ - { - "id":0, - "vertexType":"COLUMN", - "vertexId":"db_6.table_2.count", - "metadata": { - "tableName": "db_6.table_2", - "tableCreateTime": 1554750072 - } - }, - { - "id":1, - "vertexType":"COLUMN", - "vertexId":"db_6.table_1.count", - "metadata": { - "tableName": "db_6.table_1", - "tableCreateTime": 1554750070 - } - }, - { - "id":2, - "vertexType":"COLUMN", - "vertexId":"db_6.table_2.id", - "metadata": { - "tableName": "db_6.table_2", - "tableCreateTime": 1554750072 - } - }, - { - "id":3, - "vertexType":"COLUMN", - "vertexId":"db_6.table_1.id", - "metadata": { - "tableName": "db_6.table_1", - "tableCreateTime": 1554750070 - } - }, - { - "id":4, - "vertexType":"COLUMN", - "vertexId":"db_6.table_2.int_col", - "metadata": { - "tableName": "db_6.table_2", - "tableCreateTime": 1554750072 - } - } - ] -} diff --git a/addons/impala-bridge/src/test/resources/impalaMultipleInsertIntoAsSelect2.json b/addons/impala-bridge/src/test/resources/impalaMultipleInsertIntoAsSelect2.json deleted file mode 100644 index ece6535d992..00000000000 --- a/addons/impala-bridge/src/test/resources/impalaMultipleInsertIntoAsSelect2.json +++ /dev/null @@ -1,83 +0,0 @@ -{ - "queryText":"insert into table db_6.table_2 (count, id) select count, id from db_6.table_1", - "queryId":"3a441d0c130962f8:7f634aec00000000", - "hash":"64ff0425ccdfaada53e3f2fd76f566f7", - "user":"admin", - "timestamp":1554750082, - "endTime":1554750584, - "edges":[ - { - "sources":[ - 1 - ], - "targets":[ - 0 - ], - "edgeType":"PROJECTION" - }, - { - "sources":[ - 3 - ], - "targets":[ - 2 - ], - "edgeType":"PROJECTION" - }, - { - "sources":[ - ], - "targets":[ - 4 - ], - "edgeType":"PROJECTION" - } - ], - "vertices":[ - { - "id":0, - "vertexType":"COLUMN", - "vertexId":"db_6.table_2.count", - "metadata": { - "tableName": "db_6.table_2", - "tableCreateTime": 1554750072 - } - }, - { - "id":1, - "vertexType":"COLUMN", - "vertexId":"db_6.table_1.count", - "metadata": { - "tableName": "db_6.table_1", - "tableCreateTime": 1554750070 - } - }, - { - "id":2, - "vertexType":"COLUMN", - "vertexId":"db_6.table_2.id", - "metadata": { - "tableName": "db_6.table_2", - "tableCreateTime": 1554750072 - } - }, - { - "id":3, - "vertexType":"COLUMN", - "vertexId":"db_6.table_1.id", - "metadata": { - "tableName": "db_6.table_1", - "tableCreateTime": 1554750070 - } - }, - { - "id":4, - "vertexType":"COLUMN", - "vertexId":"db_6.table_2.int_col", - "metadata": { - "tableName": "db_6.table_2", - "tableCreateTime": 1554750072 - } - } - ] -} \ No newline at end of file diff --git a/addons/impala-bridge/src/test/resources/users-credentials.properties b/addons/impala-bridge/src/test/resources/users-credentials.properties deleted file mode 100644 index 5046dbaf646..00000000000 --- a/addons/impala-bridge/src/test/resources/users-credentials.properties +++ /dev/null @@ -1,3 +0,0 @@ -#username=group::sha256-password -admin=ADMIN::a4a88c0872bf652bb9ed803ece5fd6e82354838a9bf59ab4babb1dab322154e1 -rangertagsync=RANGER_TAG_SYNC::0afe7a1968b07d4c3ff4ed8c2d809a32ffea706c66cd795ead9048e81cfaf034 diff --git a/addons/impala-hook-api/pom.xml b/addons/impala-hook-api/pom.xml deleted file mode 100644 index fd970675a5b..00000000000 --- a/addons/impala-hook-api/pom.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - impala-hook-api - Apache Atlas Impala Hook API Module - Apache Atlas Impala Hook API - jar - - \ No newline at end of file diff --git a/addons/impala-hook-api/src/main/java/org/apache/impala/hooks/QueryCompleteContext.java b/addons/impala-hook-api/src/main/java/org/apache/impala/hooks/QueryCompleteContext.java deleted file mode 100644 index dc8e31716b9..00000000000 --- a/addons/impala-hook-api/src/main/java/org/apache/impala/hooks/QueryCompleteContext.java +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.impala.hooks; - -import java.util.Objects; - -/** - * {@link QueryCompleteContext} encapsulates immutable information sent from the - * BE to a post-query hook. - */ -public class QueryCompleteContext { - private final String lineageGraph_; - - public QueryCompleteContext(String lineageGraph) { - lineageGraph_ = Objects.requireNonNull(lineageGraph); - } - - /** - * Returns the lineage graph sent from the backend during - * {@link QueryEventHook#onQueryComplete(QueryCompleteContext)}. This graph - * object will generally contain more information than it did when it was - * first constructed in the frontend, because the backend will have filled - * in additional information. - *

- * The returned object is a JSON representation of the lineage graph object - * for the query. The details of the JSON translation are not provided here - * as this is meant to be a temporary feature, and the String format will - * be changed to something more strongly-typed in the future. - *

- * - * @return lineage graph from the query that executed - */ - public String getLineageGraph() { return lineageGraph_; } - - @Override - public String toString() { - return "QueryCompleteContext{" + - "lineageGraph='" + lineageGraph_ + '\'' + - '}'; - } -} diff --git a/addons/impala-hook-api/src/main/java/org/apache/impala/hooks/QueryEventHook.java b/addons/impala-hook-api/src/main/java/org/apache/impala/hooks/QueryEventHook.java deleted file mode 100644 index cd4d2ec080d..00000000000 --- a/addons/impala-hook-api/src/main/java/org/apache/impala/hooks/QueryEventHook.java +++ /dev/null @@ -1,116 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.impala.hooks; - -/** - * {@link QueryEventHook} is the interface for implementations that - * can hook into supported events in Impala query execution. - */ -public interface QueryEventHook { - /** - * Hook method invoked when the Impala daemon starts up. - *

- * This method will block completion of daemon startup, so you should - * execute any long-running actions asynchronously. - *

- *

Error-Handling

- *

- * Any {@link Exception} thrown from this method will effectively fail - * Impala startup with an error. Implementations should handle all - * exceptions as gracefully as they can, even if the end result is to - * throw them. - *

- */ - void onImpalaStartup(); - - /** - * Hook method invoked asynchronously when a (qualifying) Impala query - * has executed, but before it has returned. - *

- * This method will not block the invoking or subsequent queries, - * but may block future hook invocations if it runs for too long - *

- *

Error-Handling

- *

- * Any {@link Throwable} thrown from this method will only be caught - * and logged and will not affect the result of any query. Hook implementations - * should make a best-effort to handle their own exceptions. - *

- *

Important:

- *

- * This hook is actually invoked when the query is unregistered, - * which may happen a long time after the query has executed. - * e.g. the following sequence is possible: - *

    - *
  1. User executes query from Hue. - *
  2. User goes home for weekend, leaving Hue tab open in browser - *
  3. If we're lucky, the session timeout expires after some amount of idle time. - *
  4. The query gets unregistered, lineage record gets logged - *
- *

- *

Service Guarantees

- * - * Impala makes the following guarantees about how this method is executed - * with respect to other implementations that may be registered: - * - *

Hooks are executed asynchronously

- * - * All hook execution happens asynchronously of the query that triggered - * them. Hooks may still be executing after the query response has returned - * to the caller. Additionally, hooks may execute concurrently if the - * hook executor thread size is configured appropriately. - * - *

Hook Invocation is in Configuration Order

- * - * The submission of the hook execution tasks occurs in the order - * that the hooks were defined in configuration. This generally means that - * hooks will start executing in order, but there are no guarantees - * about finishing order. - *

- * For example, if configured with {@code query_event_hook_classes=hook1,hook2,hook3}, - * then hook1 will start before hook2, and hook2 will start before hook3. - * If you need to guarantee that hook1 completes before hook2 starts, then - * you should specify {@code query_event_hook_nthreads=1} for serial hook - * execution. - *

- * - *

Hook Execution Blocks

- * - * A hook will block the thread it executes on until it completes. If a hook hangs, - * then the thread also hangs. Impala (currently) will not check for hanging hooks to - * take any action. This means that if you have {@code query_event_hook_nthreads} - * less than the number of hooks, then 1 hook may effectively block others from - * executing. - * - *

Hook Exceptions are non-fatal

- * - * Any exception thrown from this hook method will be logged and ignored. Therefore, - * an exception in 1 hook will not affect another hook (when no shared resources are - * involved). - * - *

Hook Execution may end abruptly at Impala shutdown

- * - * If a hook is still executing when Impala is shutdown, there are no guarantees - * that it will complete execution before being killed. - * - * - * @param context object containing the post execution context - * of the query - */ - void onQueryComplete(QueryCompleteContext context); -} diff --git a/addons/kafka-bridge/pom.xml b/addons/kafka-bridge/pom.xml deleted file mode 100644 index 30fb53d27c1..00000000000 --- a/addons/kafka-bridge/pom.xml +++ /dev/null @@ -1,406 +0,0 @@ - - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - kafka-bridge - Apache Atlas Kafka Bridge Module - Apache Atlas Kafka Bridge - jar - - - org.apache.atlas - atlas-client-v1 - - - - org.apache.atlas - atlas-client-v2 - - - - - com.sun.jersey - jersey-bundle - ${jersey.version} - test - - - - org.apache.atlas - atlas-webapp - war - test - - - - org.apache.hadoop - hadoop-hdfs - test - - - javax.servlet - servlet-api - - - - - - org.apache.hadoop - hadoop-annotations - test - - - - org.apache.hadoop - hadoop-minicluster - ${hadoop.version} - test - - - javax.servlet - servlet-api - - - - - - org.testng - testng - - - - org.mockito - mockito-all - - - - org.apache.httpcomponents - httpcore - ${httpcomponents-httpcore.version} - - - - org.eclipse.jetty - jetty-webapp - ${jetty.version} - compile - - - - org.eclipse.jetty - jetty-server - test - - - com.google.guava - guava - 12.0.1 - - - org.apache.hadoop - hadoop-common - ${hadoop.version} - compile - - - javax.servlet - servlet-api - - - - - org.apache.hadoop - hadoop-auth - ${hadoop.version} - compile - - - - - - dist - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-hook - package - - copy - - - ${project.build.directory}/dependency/hook/kafka/atlas-kafka-plugin-impl - false - false - true - - - ${project.groupId} - ${project.artifactId} - ${project.version} - - - ${project.groupId} - atlas-client-v1 - ${project.version} - - - ${project.groupId} - atlas-client-common - ${project.version} - - - ${project.groupId} - atlas-client-v2 - ${project.version} - - - ${project.groupId} - atlas-intg - ${project.version} - - - ${project.groupId} - atlas-common - ${project.version} - - - org.apache.kafka - kafka-clients - ${kafka.version} - - - com.sun.jersey.contribs - jersey-multipart - ${jersey.version} - - - commons-configuration - commons-configuration - ${commons-conf.version} - - - - - - - - - - - - - - org.eclipse.jetty - jetty-maven-plugin - ${jetty.version} - - true - - - 31000 - 60000 - - ../../webapp/target/atlas-webapp-${project.version}.war - true - ../../webapp/src/main/webapp - - / - ${project.basedir}/../../webapp/src/main/webapp/WEB-INF/web.xml - ${project.basedir}/../../webapp/target/test-classes/ - - true - - true - - atlas.home - ${project.build.directory} - - - atlas.conf - ${project.build.directory}/test-classes - - - atlas.data - ${project.build.directory}/data - - - atlas.log.dir - ${project.build.directory}/logs - - - atlas.log.file - application.log - - - log4j.configuration - file:///${project.build.directory}/test-classes/atlas-log4j.xml - - - atlas.graphdb.backend - ${graphdb.backend.impl} - - - embedded.solr.directory - ${project.build.directory} - - - solr.log.dir - ${project.build.directory}/logs - - - org.eclipse.jetty.annotations.maxWait - 5000 - - - atlas-stop - 31001 - ${jetty-maven-plugin.stopWait} - jar - - - - org.apache.curator - curator-client - ${curator.version} - - - - org.apache.zookeeper - zookeeper - ${zookeeper.version} - - - - - start-jetty - pre-integration-test - - - stop - deploy-war - - - true - - - - stop-jetty - post-integration-test - - stop - - - - - - - org.apache.maven.plugins - maven-site-plugin - - - org.apache.maven.doxia - doxia-module-twiki - ${doxia.version} - - - org.apache.maven.doxia - doxia-core - ${doxia.version} - - - - - - site - - prepare-package - - - - false - false - - - - - org.codehaus.mojo - exec-maven-plugin - 1.2.1 - false - - - - - - org.apache.maven.plugins - maven-resources-plugin - - - copy-resources - validate - - copy-resources - - - ${basedir}/target/models - - - ${basedir}/../models - true - - - - - - - - - maven-resources-plugin - - - copy-solr-resources - validate - - copy-resources - - - ${project.build.directory}/solr - - - ${basedir}/../../test-tools/src/main/resources/solr - - - - - - - - - diff --git a/addons/kafka-bridge/src/bin/import-kafka.sh b/addons/kafka-bridge/src/bin/import-kafka.sh deleted file mode 100644 index fbc16f0d03b..00000000000 --- a/addons/kafka-bridge/src/bin/import-kafka.sh +++ /dev/null @@ -1,150 +0,0 @@ -#!/bin/bash -# -# 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. See accompanying LICENSE file. -# - -# resolve links - $0 may be a softlink -PRG="${0}" - -[[ `uname -s` == *"CYGWIN"* ]] && CYGWIN=true - -while [ -h "${PRG}" ]; do - ls=`ls -ld "${PRG}"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "${PRG}"`/"$link" - fi -done - -echo ">>>>> $PRG" - -BASEDIR=`dirname ${PRG}` -BASEDIR=`cd ${BASEDIR}/..;pwd` - -echo ">>>>> $BASEDIR" - -allargs=$@ - -if test -z "${JAVA_HOME}" -then - JAVA_BIN=`which java` - JAR_BIN=`which jar` -else - JAVA_BIN="${JAVA_HOME}/bin/java" - JAR_BIN="${JAVA_HOME}/bin/jar" -fi -export JAVA_BIN - -if [ ! -e "${JAVA_BIN}" ] || [ ! -e "${JAR_BIN}" ]; then - echo "$JAVA_BIN and/or $JAR_BIN not found on the system. Please make sure java and jar commands are available." - exit 1 -fi - -# Construct Atlas classpath using jars from hook/kafka/atlas-kafka-plugin-impl/ directory. -for i in "${BASEDIR}/hook/kafka/atlas-kafka-plugin-impl/"*.jar; do - ATLASCPPATH="${ATLASCPPATH}:$i" -done - -if [ -z "${ATLAS_CONF_DIR}" ] && [ -e /etc/atlas/conf ];then - ATLAS_CONF_DIR=/etc/atlas/conf -fi -ATLASCPPATH=${ATLASCPPATH}:${ATLAS_CONF_DIR} - -# log dir for applications -ATLAS_LOG_DIR="${ATLAS_LOG_DIR:-/var/log/atlas}" -export ATLAS_LOG_DIR -LOGFILE="$ATLAS_LOG_DIR/import-kafka.log" - -TIME=`date +%Y%m%d%H%M%s` - -#Add Kafka conf in classpath -if [ ! -z "$KAFKA_CONF_DIR" ]; then - KAFKA_CONF=$KAFKA_CONF_DIR -elif [ ! -z "$KAFKA_HOME" ]; then - KAFKA_CONF="$KAFKA_HOME/conf" -elif [ -e /etc/kafka/conf ]; then - KAFKA_CONF="/etc/kafka/conf" -else - echo "Could not find a valid KAFKA configuration" - exit 1 -fi - -echo Using Kafka configuration directory "[$KAFKA_CONF]" - - -if [ -f "${KAFKA_CONF}/kafka-env.sh" ]; then - . "${KAFKA_CONF}/kafka-env.sh" -fi - -if [ -z "$KAFKA_HOME" ]; then - if [ -d "${BASEDIR}/../kafka" ]; then - KAFKA_HOME=${BASEDIR}/../kafka - else - echo "Please set KAFKA_HOME to the root of Kafka installation" - exit 1 - fi -fi - -KAFKA_CP="${KAFKA_CONF}" - -for i in "${KAFKA_HOME}/libs/"*.jar; do - KAFKA_CP="${KAFKA_CP}:$i" -done - - -#Add hadoop conf in classpath -if [ ! -z "$HADOOP_CLASSPATH" ]; then - HADOOP_CP=$HADOOP_CLASSPATH -elif [ ! -z "$HADOOP_HOME" ]; then - HADOOP_CP=`$HADOOP_HOME/bin/hadoop classpath` -elif [ $(command -v hadoop) ]; then - HADOOP_CP=`hadoop classpath` - #echo $HADOOP_CP -else - echo "Environment variable HADOOP_CLASSPATH or HADOOP_HOME need to be set" - exit 1 -fi - -CP="${ATLASCPPATH}:${HADOOP_CP}:${KAFKA_CP}" - -# If running in cygwin, convert pathnames and classpath to Windows format. -if [ "${CYGWIN}" == "true" ] -then - ATLAS_LOG_DIR=`cygpath -w ${ATLAS_LOG_DIR}` - LOGFILE=`cygpath -w ${LOGFILE}` - KAFKA_CP=`cygpath -w ${KAFKA_CP}` - HADOOP_CP=`cygpath -w ${HADOOP_CP}` - CP=`cygpath -w -p ${CP}` -fi - -JAVA_PROPERTIES="$ATLAS_OPTS -Datlas.log.dir=$ATLAS_LOG_DIR -Datlas.log.file=import-kafka.log --Dlog4j.configuration=atlas-kafka-import-log4j.xml" -shift - -while [[ ${1} =~ ^\-D ]]; do - JAVA_PROPERTIES="${JAVA_PROPERTIES} ${1}" - shift -done - -echo "Log file for import is $LOGFILE" - -"${JAVA_BIN}" ${JAVA_PROPERTIES} -cp "${CP}" org.apache.atlas.kafka.bridge.KafkaBridge $allargs - -RETVAL=$? -[ $RETVAL -eq 0 ] && echo Kafka Data Model imported successfully!!! -[ $RETVAL -ne 0 ] && echo Failed to import Kafka Data Model!!! - -exit $RETVAL - diff --git a/addons/kafka-bridge/src/main/java/org/apache/atlas/kafka/bridge/KafkaBridge.java b/addons/kafka-bridge/src/main/java/org/apache/atlas/kafka/bridge/KafkaBridge.java deleted file mode 100644 index f9548244364..00000000000 --- a/addons/kafka-bridge/src/main/java/org/apache/atlas/kafka/bridge/KafkaBridge.java +++ /dev/null @@ -1,361 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.kafka.bridge; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.kafka.model.KafkaDataTypes; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; -import org.apache.atlas.model.instance.AtlasEntityHeader; -import org.apache.atlas.model.instance.EntityMutationResponse; -import org.apache.atlas.utils.AtlasConfigurationUtil; -import org.apache.atlas.utils.AuthenticationUtil; -import org.apache.atlas.utils.KafkaUtils; -import org.apache.commons.cli.BasicParser; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.CommandLineParser; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.lang.StringUtils; -import org.apache.hadoop.security.UserGroupInformation; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.regex.Pattern; - -public class KafkaBridge { - private static final Logger LOG = LoggerFactory.getLogger(KafkaBridge.class); - private static final int EXIT_CODE_SUCCESS = 0; - private static final int EXIT_CODE_FAILED = 1; - private static final String ATLAS_ENDPOINT = "atlas.rest.address"; - private static final String DEFAULT_ATLAS_URL = "http://localhost:21000/"; - private static final String CLUSTER_NAME_KEY = "atlas.cluster.name"; - private static final String KAFKA_METADATA_NAMESPACE = "atlas.metadata.namespace"; - private static final String DEFAULT_CLUSTER_NAME = "primary"; - private static final String ATTRIBUTE_QUALIFIED_NAME = "qualifiedName"; - private static final String DESCRIPTION_ATTR = "description"; - private static final String PARTITION_COUNT = "partitionCount"; - private static final String REPLICATION_FACTOR = "replicationFactor"; - private static final String NAME = "name"; - private static final String URI = "uri"; - private static final String CLUSTERNAME = "clusterName"; - private static final String TOPIC = "topic"; - private static final String FORMAT_KAFKA_TOPIC_QUALIFIED_NAME = "%s@%s"; - - private final List availableTopics; - private final String metadataNamespace; - private final AtlasClientV2 atlasClientV2; - private final KafkaUtils kafkaUtils; - - - public static void main(String[] args) { - int exitCode = EXIT_CODE_FAILED; - AtlasClientV2 atlasClientV2 = null; - KafkaUtils kafkaUtils = null; - - try { - Options options = new Options(); - options.addOption("t","topic", true, "topic"); - options.addOption("f", "filename", true, "filename"); - - CommandLineParser parser = new BasicParser(); - CommandLine cmd = parser.parse(options, args); - String topicToImport = cmd.getOptionValue("t"); - String fileToImport = cmd.getOptionValue("f"); - Configuration atlasConf = ApplicationProperties.get(); - String[] urls = atlasConf.getStringArray(ATLAS_ENDPOINT); - - if (urls == null || urls.length == 0) { - urls = new String[] { DEFAULT_ATLAS_URL }; - } - - - if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { - String[] basicAuthUsernamePassword = AuthenticationUtil.getBasicAuthenticationInput(); - - atlasClientV2 = new AtlasClientV2(urls, basicAuthUsernamePassword); - } else { - UserGroupInformation ugi = UserGroupInformation.getCurrentUser(); - - atlasClientV2 = new AtlasClientV2(ugi, ugi.getShortUserName(), urls); - } - - kafkaUtils = new KafkaUtils(atlasConf); - - KafkaBridge importer = new KafkaBridge(atlasConf, atlasClientV2, kafkaUtils); - - if (StringUtils.isNotEmpty(fileToImport)) { - File f = new File(fileToImport); - - if (f.exists() && f.canRead()) { - BufferedReader br = new BufferedReader(new FileReader(f)); - String line; - - while ((line = br.readLine()) != null) { - topicToImport = line.trim(); - - importer.importTopic(topicToImport); - } - - exitCode = EXIT_CODE_SUCCESS; - } else { - LOG.error("Failed to read the file"); - } - } else { - importer.importTopic(topicToImport); - - exitCode = EXIT_CODE_SUCCESS; - } - } catch(ParseException e) { - LOG.error("Failed to parse arguments. Error: ", e.getMessage()); - - printUsage(); - } catch(Exception e) { - System.out.println("ImportKafkaEntities failed. Please check the log file for the detailed error message"); - - e.printStackTrace(); - - LOG.error("ImportKafkaEntities failed", e); - } finally { - if (atlasClientV2 != null) { - atlasClientV2.close(); - } - - if (kafkaUtils != null) { - kafkaUtils.close(); - } - } - - System.exit(exitCode); - } - - public KafkaBridge(Configuration atlasConf, AtlasClientV2 atlasClientV2, KafkaUtils kafkaUtils) throws Exception { - this.atlasClientV2 = atlasClientV2; - this.metadataNamespace = getMetadataNamespace(atlasConf); - this.kafkaUtils = kafkaUtils; - this.availableTopics = this.kafkaUtils.listAllTopics(); - } - - private String getMetadataNamespace(Configuration config) { - return AtlasConfigurationUtil.getRecentString(config, KAFKA_METADATA_NAMESPACE, getClusterName(config)); - } - - private String getClusterName(Configuration config) { - return config.getString(CLUSTER_NAME_KEY, DEFAULT_CLUSTER_NAME); - } - - public void importTopic(String topicToImport) throws Exception { - List topics = availableTopics; - - if (StringUtils.isNotEmpty(topicToImport)) { - List topics_subset = new ArrayList<>(); - - for (String topic : topics) { - if (Pattern.compile(topicToImport).matcher(topic).matches()) { - topics_subset.add(topic); - } - } - - topics = topics_subset; - } - - if (CollectionUtils.isNotEmpty(topics)) { - for (String topic : topics) { - createOrUpdateTopic(topic); - } - } - } - - @VisibleForTesting - AtlasEntityWithExtInfo createOrUpdateTopic(String topic) throws Exception { - String topicQualifiedName = getTopicQualifiedName(metadataNamespace, topic); - AtlasEntityWithExtInfo topicEntity = findTopicEntityInAtlas(topicQualifiedName); - - if (topicEntity == null) { - System.out.println("Adding Kafka topic " + topic); - LOG.info("Importing Kafka topic: {}", topicQualifiedName); - - AtlasEntity entity = getTopicEntity(topic, null); - - topicEntity = createEntityInAtlas(new AtlasEntityWithExtInfo(entity)); - } else { - System.out.println("Updating Kafka topic " + topic); - LOG.info("Kafka topic {} already exists in Atlas. Updating it..", topicQualifiedName); - - AtlasEntity entity = getTopicEntity(topic, topicEntity.getEntity()); - - topicEntity.setEntity(entity); - - topicEntity = updateEntityInAtlas(topicEntity); - } - - return topicEntity; - } - - @VisibleForTesting - AtlasEntity getTopicEntity(String topic, AtlasEntity topicEntity) throws Exception { - final AtlasEntity ret; - - if (topicEntity == null) { - ret = new AtlasEntity(KafkaDataTypes.KAFKA_TOPIC.getName()); - } else { - ret = topicEntity; - } - - String qualifiedName = getTopicQualifiedName(metadataNamespace, topic); - - ret.setAttribute(ATTRIBUTE_QUALIFIED_NAME, qualifiedName); - ret.setAttribute(CLUSTERNAME, metadataNamespace); - ret.setAttribute(TOPIC, topic); - ret.setAttribute(NAME,topic); - ret.setAttribute(DESCRIPTION_ATTR, topic); - ret.setAttribute(URI, topic); - - try { - ret.setAttribute(PARTITION_COUNT, kafkaUtils.getPartitionCount(topic)); - ret.setAttribute(REPLICATION_FACTOR, kafkaUtils.getReplicationFactor(topic)); - } catch (ExecutionException | InterruptedException e) { - LOG.error("Error while getting partition data for topic :" + topic, e); - - throw new Exception("Error while getting partition data for topic :" + topic, e); - } - - return ret; - } - - @VisibleForTesting - static String getTopicQualifiedName(String metadataNamespace, String topic) { - return String.format(FORMAT_KAFKA_TOPIC_QUALIFIED_NAME, topic.toLowerCase(), metadataNamespace); - } - - private AtlasEntityWithExtInfo findTopicEntityInAtlas(String topicQualifiedName) { - AtlasEntityWithExtInfo ret = null; - - try { - ret = findEntityInAtlas(KafkaDataTypes.KAFKA_TOPIC.getName(), topicQualifiedName); - - clearRelationshipAttributes(ret); - } catch (Exception e) { - ret = null; // entity doesn't exist in Atlas - } - - return ret; - } - - @VisibleForTesting - AtlasEntityWithExtInfo findEntityInAtlas(String typeName, String qualifiedName) throws Exception { - Map attributes = Collections.singletonMap(ATTRIBUTE_QUALIFIED_NAME, qualifiedName); - - return atlasClientV2.getEntityByAttribute(typeName, attributes); - } - - @VisibleForTesting - AtlasEntityWithExtInfo createEntityInAtlas(AtlasEntityWithExtInfo entity) throws Exception { - AtlasEntityWithExtInfo ret = null; - EntityMutationResponse response = atlasClientV2.createEntity(entity); - List entities = response.getCreatedEntities(); - - if (CollectionUtils.isNotEmpty(entities)) { - AtlasEntityWithExtInfo getByGuidResponse = atlasClientV2.getEntityByGuid(entities.get(0).getGuid()); - - ret = getByGuidResponse; - - LOG.info("Created {} entity: name={}, guid={}", ret.getEntity().getTypeName(), ret.getEntity().getAttribute(ATTRIBUTE_QUALIFIED_NAME), ret.getEntity().getGuid()); - } - - return ret; - } - - @VisibleForTesting - AtlasEntityWithExtInfo updateEntityInAtlas(AtlasEntityWithExtInfo entity) throws Exception { - AtlasEntityWithExtInfo ret; - EntityMutationResponse response = atlasClientV2.updateEntity(entity); - - if (response != null) { - List entities = response.getUpdatedEntities(); - - if (CollectionUtils.isNotEmpty(entities)) { - AtlasEntityWithExtInfo getByGuidResponse = atlasClientV2.getEntityByGuid(entities.get(0).getGuid()); - - ret = getByGuidResponse; - - LOG.info("Updated {} entity: name={}, guid={} ", ret.getEntity().getTypeName(), ret.getEntity().getAttribute(ATTRIBUTE_QUALIFIED_NAME), ret.getEntity().getGuid()); - } else { - LOG.info("Entity: name={} ", entity.toString() + " not updated as it is unchanged from what is in Atlas" ); - - ret = entity; - } - } else { - LOG.info("Entity: name={} ", entity.toString() + " not updated as it is unchanged from what is in Atlas" ); - - ret = entity; - } - - return ret; - } - - private static void printUsage(){ - System.out.println("Usage 1: import-kafka.sh"); - System.out.println("Usage 2: import-kafka.sh [-t OR --topic ]"); - System.out.println("Usage 3: import-kafka.sh [-f ]" ); - System.out.println(" Format:"); - System.out.println(" topic1 OR topic1 regex"); - System.out.println(" topic2 OR topic2 regex"); - System.out.println(" topic3 OR topic3 regex"); - } - - - private void clearRelationshipAttributes(AtlasEntityWithExtInfo entity) { - if (entity != null) { - clearRelationshipAttributes(entity.getEntity()); - - if (entity.getReferredEntities() != null) { - clearRelationshipAttributes(entity.getReferredEntities().values()); - } - } - } - - private void clearRelationshipAttributes(Collection entities) { - if (entities != null) { - for (AtlasEntity entity : entities) { - clearRelationshipAttributes(entity); - } - } - } - - private void clearRelationshipAttributes(AtlasEntity entity) { - if (entity != null && entity.getRelationshipAttributes() != null) { - entity.getRelationshipAttributes().clear(); - } - } -} diff --git a/addons/kafka-bridge/src/main/java/org/apache/atlas/kafka/model/KafkaDataTypes.java b/addons/kafka-bridge/src/main/java/org/apache/atlas/kafka/model/KafkaDataTypes.java deleted file mode 100644 index 0f81b4c37a1..00000000000 --- a/addons/kafka-bridge/src/main/java/org/apache/atlas/kafka/model/KafkaDataTypes.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.kafka.model; - -/** - * HBASE Data Types for model and bridge. - */ -public enum KafkaDataTypes { - // Classes - KAFKA_TOPIC; - - public String getName() { - return name().toLowerCase(); - } -} diff --git a/addons/kafka-bridge/src/main/resources/atlas-kafka-import-log4j.xml b/addons/kafka-bridge/src/main/resources/atlas-kafka-import-log4j.xml deleted file mode 100644 index 3fc2dcf9c30..00000000000 --- a/addons/kafka-bridge/src/main/resources/atlas-kafka-import-log4j.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/kafka-bridge/src/test/java/org/apache/atlas/kafka/bridge/KafkaBridgeTest.java b/addons/kafka-bridge/src/test/java/org/apache/atlas/kafka/bridge/KafkaBridgeTest.java deleted file mode 100644 index f86ceb58fd2..00000000000 --- a/addons/kafka-bridge/src/test/java/org/apache/atlas/kafka/bridge/KafkaBridgeTest.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.kafka.bridge; - -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.kafka.model.KafkaDataTypes; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntityHeader; -import org.apache.atlas.model.instance.EntityMutationResponse; -import org.apache.atlas.utils.KafkaUtils; -import org.mockito.ArgumentCaptor; -import org.mockito.MockitoAnnotations; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import java.util.Collections; - - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.testng.Assert.assertEquals; - -public class KafkaBridgeTest { - - private static final String TEST_TOPIC_NAME = "test_topic"; - public static final AtlasEntity.AtlasEntityWithExtInfo TOPIC_WITH_EXT_INFO = new AtlasEntity.AtlasEntityWithExtInfo( - getTopicEntityWithGuid("0dd466a4-3838-4537-8969-6abb8b9e9185")); - private static final String CLUSTER_NAME = "primary"; - private static final String TOPIC_QUALIFIED_NAME = KafkaBridge.getTopicQualifiedName(CLUSTER_NAME, TEST_TOPIC_NAME); - - @BeforeMethod - public void initializeMocks() { - MockitoAnnotations.initMocks(this); - } - - private static AtlasEntity getTopicEntityWithGuid(String guid) { - AtlasEntity ret = new AtlasEntity(KafkaDataTypes.KAFKA_TOPIC.getName()); - ret.setGuid(guid); - return ret; - } - - @Test - public void testImportTopic() throws Exception { - KafkaUtils mockKafkaUtils = mock(KafkaUtils.class); - when(mockKafkaUtils.listAllTopics()) - .thenReturn(Collections.singletonList(TEST_TOPIC_NAME)); - when(mockKafkaUtils.getPartitionCount(TEST_TOPIC_NAME)) - .thenReturn(3); - - EntityMutationResponse mockCreateResponse = mock(EntityMutationResponse.class); - AtlasEntityHeader mockAtlasEntityHeader = mock(AtlasEntityHeader.class); - when(mockAtlasEntityHeader.getGuid()).thenReturn(TOPIC_WITH_EXT_INFO.getEntity().getGuid()); - when(mockCreateResponse.getCreatedEntities()) - .thenReturn(Collections.singletonList(mockAtlasEntityHeader)); - - AtlasClientV2 mockAtlasClientV2 = mock(AtlasClientV2.class); - when(mockAtlasClientV2.createEntity(any())) - .thenReturn(mockCreateResponse); - when(mockAtlasClientV2.getEntityByGuid(TOPIC_WITH_EXT_INFO.getEntity().getGuid())) - .thenReturn(TOPIC_WITH_EXT_INFO); - - KafkaBridge bridge = new KafkaBridge(ApplicationProperties.get(), mockAtlasClientV2, mockKafkaUtils); - bridge.importTopic(TEST_TOPIC_NAME); - - ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(AtlasEntity.AtlasEntityWithExtInfo.class); - verify(mockAtlasClientV2).createEntity(argumentCaptor.capture()); - AtlasEntity.AtlasEntityWithExtInfo entity = argumentCaptor.getValue(); - assertEquals(entity.getEntity().getAttribute("qualifiedName"), TOPIC_QUALIFIED_NAME); - } - - @Test - public void testCreateTopic() throws Exception { - KafkaUtils mockKafkaUtils = mock(KafkaUtils.class); - when(mockKafkaUtils.listAllTopics()) - .thenReturn(Collections.singletonList(TEST_TOPIC_NAME)); - when(mockKafkaUtils.getPartitionCount(TEST_TOPIC_NAME)) - .thenReturn(3); - - EntityMutationResponse mockCreateResponse = mock(EntityMutationResponse.class); - AtlasEntityHeader mockAtlasEntityHeader = mock(AtlasEntityHeader.class); - when(mockAtlasEntityHeader.getGuid()).thenReturn(TOPIC_WITH_EXT_INFO.getEntity().getGuid()); - when(mockCreateResponse.getCreatedEntities()) - .thenReturn(Collections.singletonList(mockAtlasEntityHeader)); - - AtlasClientV2 mockAtlasClientV2 = mock(AtlasClientV2.class); - when(mockAtlasClientV2.createEntity(any())) - .thenReturn(mockCreateResponse); - when(mockAtlasClientV2.getEntityByGuid(TOPIC_WITH_EXT_INFO.getEntity().getGuid())) - .thenReturn(TOPIC_WITH_EXT_INFO); - - KafkaBridge bridge = new KafkaBridge(ApplicationProperties.get(), mockAtlasClientV2, mockKafkaUtils); - AtlasEntity.AtlasEntityWithExtInfo ret = bridge.createOrUpdateTopic(TEST_TOPIC_NAME); - - assertEquals(TOPIC_WITH_EXT_INFO, ret); - } - - @Test - public void testUpdateTopic() throws Exception { - KafkaUtils mockKafkaUtils = mock(KafkaUtils.class); - when(mockKafkaUtils.listAllTopics()) - .thenReturn(Collections.singletonList(TEST_TOPIC_NAME)); - when(mockKafkaUtils.getPartitionCount(TEST_TOPIC_NAME)) - .thenReturn(3); - - EntityMutationResponse mockUpdateResponse = mock(EntityMutationResponse.class); - AtlasEntityHeader mockAtlasEntityHeader = mock(AtlasEntityHeader.class); - when(mockAtlasEntityHeader.getGuid()).thenReturn(TOPIC_WITH_EXT_INFO.getEntity().getGuid()); - when(mockUpdateResponse.getUpdatedEntities()) - .thenReturn(Collections.singletonList(mockAtlasEntityHeader)); - - AtlasClientV2 mockAtlasClientV2 = mock(AtlasClientV2.class); - when(mockAtlasClientV2.getEntityByAttribute(eq(KafkaDataTypes.KAFKA_TOPIC.getName()), any())) - .thenReturn(TOPIC_WITH_EXT_INFO); - when(mockAtlasClientV2.updateEntity(any())) - .thenReturn(mockUpdateResponse); - when(mockAtlasClientV2.getEntityByGuid(TOPIC_WITH_EXT_INFO.getEntity().getGuid())) - .thenReturn(TOPIC_WITH_EXT_INFO); - - KafkaBridge bridge = new KafkaBridge(ApplicationProperties.get(), mockAtlasClientV2, mockKafkaUtils); - AtlasEntity.AtlasEntityWithExtInfo ret = bridge.createOrUpdateTopic(TEST_TOPIC_NAME); - - assertEquals(TOPIC_WITH_EXT_INFO, ret); - } -} \ No newline at end of file diff --git a/addons/kafka-bridge/src/test/resources/atlas-application.properties b/addons/kafka-bridge/src/test/resources/atlas-application.properties deleted file mode 100644 index 4a12cf6c834..00000000000 --- a/addons/kafka-bridge/src/test/resources/atlas-application.properties +++ /dev/null @@ -1,125 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# - -######### Atlas Server Configs ######### -atlas.rest.address=http://localhost:31000 - -######### Graph Database Configs ######### - - -# Graph database implementation. Value inserted by maven. -atlas.graphdb.backend=org.apache.atlas.repository.graphdb.janus.AtlasJanusGraphDatabase -atlas.graph.index.search.solr.wait-searcher=true - -# Graph Storage -atlas.graph.storage.backend=berkeleyje - -# Entity repository implementation -atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.InMemoryEntityAuditRepository - -# Graph Search Index Backend -atlas.graph.index.search.backend=solr - -#Berkeley storage directory -atlas.graph.storage.directory=${sys:atlas.data}/berkley - -#hbase -#For standalone mode , specify localhost -#for distributed mode, specify zookeeper quorum here - For more information refer http://s3.thinkaurelius.com/docs/titan/current/hbase.html#_remote_server_mode_2 - -atlas.graph.storage.hostname=${graph.storage.hostname} -atlas.graph.storage.hbase.regions-per-server=1 -atlas.graph.storage.lock.wait-time=10000 - -#ElasticSearch -atlas.graph.index.search.directory=${sys:atlas.data}/es -atlas.graph.index.search.elasticsearch.client-only=false -atlas.graph.index.search.elasticsearch.local-mode=true -atlas.graph.index.search.elasticsearch.create.sleep=2000 - -# Solr cloud mode properties -atlas.graph.index.search.solr.mode=cloud -atlas.graph.index.search.solr.zookeeper-url=${solr.zk.address} -atlas.graph.index.search.solr.embedded=true -atlas.graph.index.search.max-result-set-size=150 - - -######### Notification Configs ######### -atlas.notification.embedded=true - -atlas.kafka.zookeeper.connect=localhost:19026 -atlas.kafka.bootstrap.servers=localhost:19027 -atlas.kafka.data=${sys:atlas.data}/kafka -atlas.kafka.zookeeper.session.timeout.ms=4000 -atlas.kafka.zookeeper.sync.time.ms=20 -atlas.kafka.consumer.timeout.ms=4000 -atlas.kafka.auto.commit.interval.ms=100 -atlas.kafka.hook.group.id=atlas -atlas.kafka.entities.group.id=atlas_entities -#atlas.kafka.auto.commit.enable=false - -atlas.kafka.enable.auto.commit=false -atlas.kafka.auto.offset.reset=earliest -atlas.kafka.session.timeout.ms=30000 -atlas.kafka.offsets.topic.replication.factor=1 - - - -######### Entity Audit Configs ######### -atlas.audit.hbase.tablename=ATLAS_ENTITY_AUDIT_EVENTS -atlas.audit.zookeeper.session.timeout.ms=1000 -atlas.audit.hbase.zookeeper.quorum=localhost -atlas.audit.hbase.zookeeper.property.clientPort=19026 - -######### Security Properties ######### - -# SSL config -atlas.enableTLS=false -atlas.server.https.port=31443 - -######### Security Properties ######### - -hbase.security.authentication=simple - -atlas.hook.falcon.synchronous=true - -######### JAAS Configuration ######## - -atlas.jaas.KafkaClient.loginModuleName = com.sun.security.auth.module.Krb5LoginModule -atlas.jaas.KafkaClient.loginModuleControlFlag = required -atlas.jaas.KafkaClient.option.useKeyTab = true -atlas.jaas.KafkaClient.option.storeKey = true -atlas.jaas.KafkaClient.option.serviceName = kafka -atlas.jaas.KafkaClient.option.keyTab = /etc/security/keytabs/atlas.service.keytab -atlas.jaas.KafkaClient.option.principal = atlas/_HOST@EXAMPLE.COM - -######### High Availability Configuration ######## -atlas.server.ha.enabled=false -#atlas.server.ids=id1 -#atlas.server.address.id1=localhost:21000 - -######### Atlas Authorization ######### -atlas.authorizer.impl=none -# atlas.authorizer.impl=simple -# atlas.authorizer.simple.authz.policy.file=atlas-simple-authz-policy.json - -######### Atlas Authentication ######### -atlas.authentication.method.file=true -atlas.authentication.method.ldap.type=none -atlas.authentication.method.kerberos=false -# atlas.authentication.method.file.filename=users-credentials.properties diff --git a/addons/kafka-bridge/src/test/resources/atlas-log4j.xml b/addons/kafka-bridge/src/test/resources/atlas-log4j.xml deleted file mode 100755 index 0b9b36e36b9..00000000000 --- a/addons/kafka-bridge/src/test/resources/atlas-log4j.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/kafka-bridge/src/test/resources/users-credentials.properties b/addons/kafka-bridge/src/test/resources/users-credentials.properties deleted file mode 100644 index 5046dbaf646..00000000000 --- a/addons/kafka-bridge/src/test/resources/users-credentials.properties +++ /dev/null @@ -1,3 +0,0 @@ -#username=group::sha256-password -admin=ADMIN::a4a88c0872bf652bb9ed803ece5fd6e82354838a9bf59ab4babb1dab322154e1 -rangertagsync=RANGER_TAG_SYNC::0afe7a1968b07d4c3ff4ed8c2d809a32ffea706c66cd795ead9048e81cfaf034 diff --git a/addons/models/0000-Area0/0010-base_model.json b/addons/models/0000-Area0/0010-base_model.json index 769d8859fbc..d75288cc3f5 100644 --- a/addons/models/0000-Area0/0010-base_model.json +++ b/addons/models/0000-Area0/0010-base_model.json @@ -47,182 +47,168 @@ "value": "SERVER_STATE_ACTIVE" } ] - } - ], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ + }, { - "name": "Referenceable", - "superTypes": [], + "category": "ENUM", + "name": "AuthPolicyType", + "description": "Policy Item type", "serviceType": "atlas_core", - "typeVersion": "1.0", - "attributeDefs": [ + "typeVersion": "1.1", + "elementDefs": + [ { - "name": "qualifiedName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": true + "value": "allow", + "ordinal": 0 + }, + { + "value": "deny", + "ordinal": 1 + }, + { + "value": "allowExceptions", + "ordinal": 2 + }, + { + "value": "denyExceptions", + "ordinal": 3 + }, + { + "value": "dataMask", + "ordinal": 4 + }, + { + "value": "rowFilter", + "ordinal": 5 } ] }, { - "name": "__internal", - "superTypes": [], + "category": "ENUM", + "name": "AuthPolicyCategory", + "description": "Policy category", "serviceType": "atlas_core", - "typeVersion": "1.0", - "attributeDefs": [] + "typeVersion": "1.1", + "elementDefs": [ + { + "value": "bootstrap", + "ordinal": 0 + }, + { + "value": "persona", + "ordinal": 1 + }, + { + "value": "purpose", + "ordinal": 2 + } + ] }, { - "name": "Asset", - "superTypes": [ - "Referenceable" - ], + "category": "ENUM", + "name": "AuthPolicyResourceCategory", + "description": "Policy resource category", "serviceType": "atlas_core", "typeVersion": "1.1", - "attributeDefs": [ + "elementDefs": + [ { - "name": "name", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false, - "indexType": "STRING" + "value": "ENTITY", + "ordinal": 0 }, { - "name": "displayName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "indexType": "STRING" + "value": "RELATIONSHIP", + "ordinal": 1 }, { - "name": "description", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false + "value": "TAG", + "ordinal": 2 }, { - "name": "userDescription", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "indexType": "STRING" + "value": "CUSTOM", + "ordinal": 3 }, { - "name": "owner", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "indexType": "STRING" + "value": "TYPEDEFS", + "ordinal": 4 + }, + { + "value": "ADMIN", + "ordinal": 5 } ] - }, + } + ], + "structDefs": [ { - "name": "ddl", - "superTypes": [ - "Referenceable" - ], - "serviceType": "atlas_core", - "typeVersion": "1.0", - "attributeDefs": [ + "name": "AuthPolicyValiditySchedule", + "description": "Validity schedule struct for policy", + "serviceType": "atlan", + "typeVersion": "1.1", + "attributeDefs": + [ { - "name": "queryText", + "name": "policyValidityScheduleStartTime", "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "execTime", - "typeName": "date", + "indexType": "STRING", "cardinality": "SINGLE", "isIndexable": false, "isOptional": false, "isUnique": false }, { - "name": "userName", + "name": "policyValidityScheduleEndTime", "typeName": "string", + "indexType": "STRING", "cardinality": "SINGLE", - "isIndexable": true, + "isIndexable": false, "isOptional": false, "isUnique": false }, { - "name": "serviceType", + "name": "policyValidityScheduleTimezone", "typeName": "string", + "indexType": "STRING", "cardinality": "SINGLE", - "isIndexable": true, + "isIndexable": false, "isOptional": false, "isUnique": false } ] }, { - "name": "DataSet", - "superTypes": [ - "Asset" - ], - "serviceType": "atlas_core", - "typeVersion": "1.1", - "attributeDefs": [] - }, - { - "name": "Infrastructure", - "description": "Infrastructure can be IT infrastructure, which contains hosts and servers. Infrastructure might not be IT orientated, such as 'Car' for IoT applications.", - "superTypes": [ - "Asset" - ], - "serviceType": "atlas_core", - "typeVersion": "1.1", - "attributeDefs": [] - }, - { - "name": "Process", - "superTypes": [ - "Asset" - ], - "serviceType": "atlas_core", + "name": "AuthPolicyCondition", + "description": "Policy condition schedule struct", + "serviceType": "atlan", "typeVersion": "1.1", - "attributeDefs": [ + "attributeDefs": + [ { - "name": "inputs", - "typeName": "array", - "cardinality": "SET", + "name": "policyConditionType", + "typeName": "string", + "cardinality": "SINGLE", "isIndexable": false, - "isOptional": true, + "isOptional": false, "isUnique": false }, { - "name": "outputs", - "typeName": "array", - "cardinality": "SET", + "name": "policyConditionValues", + "typeName": "array", + "cardinality": "SINGLE", "isIndexable": false, - "isOptional": true, + "isOptional": false, "isUnique": false } ] - }, + } + ], + "classificationDefs": [], + "entityDefs": [ { - "name": "Path", - "superTypes": [ - "DataSet" - ], + "name": "__internal", + "superTypes": [], "serviceType": "atlas_core", - "typeVersion": "1.0" + "typeVersion": "1.0", + "attributeDefs": [] }, { "name": "AtlasServer", @@ -232,7 +218,7 @@ ], "attributeDefs": [ { - "name": "name", + "name": "AtlasServer.name", "typeName": "string", "cardinality": "SINGLE", "isIndexable": true, @@ -240,7 +226,7 @@ "isUnique": false }, { - "name": "displayName", + "name": "AtlasServer.displayName", "typeName": "string", "cardinality": "SINGLE", "isIndexable": true, @@ -282,7 +268,7 @@ "typeVersion": "1.0", "attributeDefs": [ { - "name": "name", + "name": "__AtlasUserProfile.name", "typeName": "string", "cardinality": "SINGLE", "isIndexable": true, @@ -321,7 +307,7 @@ "typeVersion": "1.0", "attributeDefs": [ { - "name": "name", + "name": "__AtlasUserSavedSearch.name", "typeName": "string", "cardinality": "SINGLE", "isIndexable": false, @@ -519,75 +505,652 @@ ] }, { - "name": "ProcessExecution", - "superTypes": [ - "Asset" - ], - "serviceType": "atlas_core", - "typeVersion": "1.0", - "attributeDefs": [] - } - ], - "relationshipDefs": [ - { - "name": "dataset_process_inputs", + "name": "Referenceable", + "superTypes": [], "serviceType": "atlas_core", - "typeVersion": "1.0", - "relationshipCategory": "AGGREGATION", - "endDef1": { - "type": "Process", - "name": "inputs", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "DataSet", - "name": "inputToProcesses", - "isContainer": false, - "cardinality": "SET" - }, - "propagateTags": "TWO_TO_ONE" + "typeVersion": "1.01", + "attributeDefs": [ + { + "name": "qualifiedName", + "typeName": "string", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": false, + "isUnique": true, + "skipScrubbing": true, + "includeInNotification": true, + "indexTypeESFields": { + "text": { + "type": "text", + "analyzer": "atlan_text_analyzer" + } + } + } + ] }, { - "name": "process_dataset_outputs", + "name": "Asset", + "superTypes": [ + "Referenceable" + ], "serviceType": "atlas_core", - "typeVersion": "1.0", - "relationshipCategory": "AGGREGATION", - "endDef1": { - "type": "Process", - "name": "outputs", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "DataSet", - "name": "outputFromProcesses", - "isContainer": false, - "cardinality": "SET" - }, - "propagateTags": "ONE_TO_TWO" + "typeVersion": "1.01", + "attributeDefs": [ + { + "name": "name", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": false, + "isUnique": false, + "searchWeight": 10, + "skipScrubbing": true, + "indexTypeESConfig": { + "analyzer": "atlan_text_analyzer" + }, + "indexTypeESFields": { + "keyword": { + "type": "keyword", + "normalizer": "atlan_normalizer" + }, + "stemmed": { + "type": "text", + "analyzer": "atlan_text_stemmer" + } + } + }, + { + "name": "displayName", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true, + "isUnique": false, + "searchWeight": 10, + "skipScrubbing": true, + "indexTypeESConfig": { + "analyzer": "atlan_text_analyzer" + }, + "indexTypeESFields": { + "keyword": { + "type": "keyword" + } + } + }, + { + "name": "description", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "searchWeight": 9, + "skipScrubbing": true, + "includeInNotification": true, + "indexTypeESConfig": { + "analyzer": "atlan_text_analyzer" + }, + "indexTypeESFields": { + "keyword": { + "type": "keyword", + "normalizer": "atlan_normalizer" + } + } + }, + { + "name": "tenantId", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": true, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true + } + ] }, { - "name": "__AtlasUserProfile_savedsearches", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "__AtlasUserProfile", - "name": "savedSearches", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "__AtlasUserSavedSearch", - "name": "userProfile", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" + "name": "AuthService", + "superTypes": [ + "Asset" + ], + "description": "Model to store auth service in Atlas", + "serviceType": "atlan", + "typeVersion": "1.2", + "attributeDefs": [ + { + "name": "authServiceType", + "typeName": "string", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "tagService", + "typeName": "string", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "abacService", + "typeName": "string", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "authServiceIsEnabled", + "typeName": "boolean", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "defaultValue": true, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "authServiceConfig", + "typeName": "map", + "isOptional": true, + "cardinality": "SINGLE", + "isUnique": false, + "skipScrubbing": true, + "isIndexable": true, + "includeInNotification": true + }, + { + "name": "authServicePolicyLastSync", + "typeName": "long", + "isOptional": true, + "defaultValue": 0, + "cardinality": "SINGLE", + "isUnique": false, + "skipScrubbing": true, + "isIndexable": true, + "includeInNotification": true + } + ] + }, + { + "name": "AuthPolicy", + "description": "Model to store an accesscontrol policy in Atlas", + "superTypes": [ + "Asset" + ], + "serviceType": "atlan", + "typeVersion": "1.2", + "attributeDefs": + [ + { + "name": "policyFilterCriteria", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "policyType", + "typeName": "AuthPolicyType", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "policyServiceName", + "typeName": "string", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "policyCategory", + "typeName": "string", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "policySubCategory", + "typeName": "string", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "policyUsers", + "typeName": "array", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "policyGroups", + "typeName": "array", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "policyRoles", + "typeName": "array", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "policyActions", + "typeName": "array", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "policyResources", + "typeName": "array", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "policyResourceCategory", + "typeName": "string", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "policyPriority", + "typeName": "int", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "defaultValue": 0, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "isPolicyEnabled", + "typeName": "boolean", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "defaultValue": true, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "policyMaskType", + "typeName": "string", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "policyValiditySchedule", + "typeName": "array", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "defaultValue": true, + "skipScrubbing": true, + "includeInNotification": false + }, + { + "name": "policyResourceSignature", + "typeName": "string", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + }, + { + "name": "policyDelegateAdmin", + "typeName": "boolean", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "defaultValue": false, + "skipScrubbing": true, + "includeInNotification": true + }, + { + "name": "policyConditions", + "typeName": "array", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + } + ] + }, + { + "name": "AccessControl", + "superTypes": [ + "Asset" + ], + "description": "Atlan Type representing parent model for Persona, Purpose", + "serviceType": "atlan", + "typeVersion": "1.6", + "attributeDefs": [ + { + "name": "isAccessControlEnabled", + "typeName": "boolean", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "defaultValue": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + }, + { + "name": "denySidebarTabs", + "typeName": "array", + "indexType": "STRING", + "cardinality": "SET", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + }, + { + "name": "denyCustomMetadataGuids", + "typeName": "array", + "indexType": "STRING", + "cardinality": "SET", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + }, + { + "name": "denyAssetMetadataTypes", + "typeName": "array", + "indexType": "STRING", + "cardinality": "SET", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + }, + { + "name": "denyAssetTabs", + "typeName": "array", + "indexType": "STRING", + "cardinality": "SET", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + }, + { + "name": "denyAssetFilters", + "typeName": "array", + "cardinality": "SET", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + }, + { + "name": "channelLink", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + }, + { + "name": "denyAssetTypes", + "typeName": "array", + "cardinality": "SET", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + }, + { + "name": "denyNavigationPages", + "typeName": "array", + "cardinality": "SET", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + }, + { + "name": "defaultNavigation", + "typeName": "string", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + }, + { + "name": "displayPreferences", + "typeName": "array", + "indexType": "STRING", + "cardinality": "SET", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + } + ] + }, + { + "name": "Persona", + "superTypes": [ + "AccessControl" + ], + "description": "Atlan Type representing a Persona model", + "serviceType": "atlan", + "typeVersion": "1.1", + "attributeDefs": [ + { + "name": "personaGroups", + "typeName": "array", + "indexType": "STRING", + "cardinality": "SET", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + }, + { + "name": "personaUsers", + "typeName": "array", + "indexType": "STRING", + "cardinality": "SET", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + }, + { + "name": "roleId", + "typeName": "string", + "indexType": "STRING", + "cardinality": "SINGLE", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "includeInNotification": false + } + ] + }, + { + "name": "Purpose", + "superTypes": [ + "AccessControl" + ], + "description": "Atlan Type representing a Purpose model", + "serviceType": "atlan", + "typeVersion": "1.2", + "attributeDefs": [ + { + "name": "purposeClassifications", + "typeName": "array", + "indexType": "STRING", + "cardinality": "SET", + "isIndexable": false, + "isOptional": true, + "isUnique": false, + "skipScrubbing": true, + "includeInNotification": false + } + ] + }, + { + "name": "StakeholderTitle", + "description": "Instance of a stakeholder title for Domains in Atlan", + "superTypes": [ + "Asset" + ], + "serviceType": "atlan", + "typeVersion": "1.0", + "attributeDefs": [ + { + "name": "stakeholderTitleDomainQualifiedNames", + "description": "qualified name array representing the Domains for which this StakeholderTitle is applicable", + "typeName": "array", + "indexType": "STRING", + "isOptional": true, + "cardinality": "SET", + "isUnique": false, + "isIndexable": false, + "skipScrubbing": true, + "includeInNotification": false + } + ] + } + ], + "relationshipDefs": [ + { + "name": "__AtlasUserProfile_savedsearches", + "serviceType": "atlas_core", + "typeVersion": "1.0", + "relationshipCategory": "COMPOSITION", + "endDef1": { + "type": "__AtlasUserProfile", + "name": "savedSearches", + "isContainer": true, + "cardinality": "SET", + "isLegacyAttribute": true + }, + "endDef2": { + "type": "__AtlasUserSavedSearch", + "name": "userProfile", + "isContainer": false, + "cardinality": "SINGLE" + }, + "propagateTags": "NONE" + }, + { + "name": "access_control_policies", + "typeVersion": "1.1", + "relationshipCategory": "AGGREGATION", + "relationshipLabel": "__AccessControl.policies", + "serviceType": "atlan", + "endDef1": + { + "type": "AccessControl", + "name": "policies", + "isContainer": true, + "cardinality": "SET" + }, + "endDef2": + { + "type": "AuthPolicy", + "name": "accessControl", + "isContainer": false, + "cardinality": "SINGLE" + }, + "propagateTags": "ONE_TO_TWO" } ] } diff --git a/addons/models/0000-Area0/0011-glossary_model.json b/addons/models/0000-Area0/0011-glossary_model.json deleted file mode 100644 index 3ea09bcf24c..00000000000 --- a/addons/models/0000-Area0/0011-glossary_model.json +++ /dev/null @@ -1,926 +0,0 @@ -{ - "enumDefs": [ - { - "name": "AtlasGlossaryTermRelationshipStatus", - "description": "TermRelationshipStatus defines how reliable the relationship is between two glossary terms", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "elementDefs": [ - { - "ordinal": 0, - "value": "DRAFT", - "description": "DRAFT means the relationship is under development." - }, - { - "ordinal": 1, - "value": "ACTIVE", - "description": "ACTIVE means the relationship is validated and in use." - }, - { - "ordinal": 2, - "value": "DEPRECATED", - "description": "DEPRECATED means the the relationship is being phased out." - }, - { - "ordinal": 3, - "value": "OBSOLETE", - "description": "OBSOLETE means that the relationship should not be used anymore." - }, - { - "ordinal": 99, - "value": "OTHER", - "description": "OTHER means that there is another status." - } - ] - }, - { - "name": "AtlasGlossaryTermAssignmentStatus", - "description": "TermAssignmentStatus defines how much the semantic assignment should be trusted.", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "elementDefs": [ - { - "value": "DISCOVERED", - "ordinal": 0, - "description": "DISCOVERED means that the semantic assignment was added by a discovery engine." - }, - { - "value": "PROPOSED", - "ordinal": 1, - "description": "PROPOSED means that the semantic assignment was proposed by person - they may be a subject matter expert, or consumer of the Referenceable asset" - }, - { - "value": "IMPORTED", - "ordinal": 2, - "description": "IMPORTED means that the semantic assignment has been imported from outside of the open metadata cluster" - }, - { - "value": "VALIDATED", - "ordinal": 3, - "description": "VALIDATED means that the semantic assignment has been reviewed and is highly trusted." - }, - { - "value": "DEPRECATED", - "ordinal": 4, - "description": "DEPRECATED means that the semantic assignment is being phased out. There may be another semantic assignment to the Referenceable that will ultimately replace this one." - }, - { - "value": "OBSOLETE", - "ordinal": 5, - "description": "OBSOLETE means that the semantic assignment is no longer in use," - }, - { - "value": "OTHER", - "ordinal": 6, - "description": "OTHER means that the semantic assignment value does not match any of the other Term Assignment Status values" - } - ] - } - ], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ - { - "name": "AtlasGlossary", - "superTypes": [ - "__internal" - ], - "serviceType": "atlas_core", - "typeVersion": "1.1", - "attributeDefs": [ - { - "name": "qualifiedName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": true - }, - { - "name": "name", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "shortDescription", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "longDescription", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "language", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "usage", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "additionalAttributes", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - - ] - - }, - { - "name": "AtlasGlossaryTerm", - "superTypes": [ - "__internal" - ], - "serviceType": "atlas_core", - "typeVersion": "1.1", - "attributeDefs": [ - { - "name": "qualifiedName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": true - }, - { - "name": "name", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "shortDescription", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "longDescription", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "examples", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "abbreviation", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "usage", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "additionalAttributes", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - - ] - - }, - { - "name": "AtlasGlossaryCategory", - "superTypes": [ - "__internal" - ], - "serviceType": "atlas_core", - "typeVersion": "1.1", - "attributeDefs": [ - { - "name": "qualifiedName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": true - }, - { - "name": "name", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "shortDescription", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "longDescription", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "additionalAttributes", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - } - ], - "relationshipDefs": [ - { - "name": "AtlasGlossarySemanticAssignment", - "description": "SemanticAssignment is a relationship used to assign a term to a referenceable object. This means that the term describes the meaning of the referenceable object. The semantic assignment needs to be a controlled relationship when glossary definitions are used to provide classifications for the data assets and hence define how the data is to be governed.", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "description", - "description": "The description field can be used to add details about the semantic assignment.", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": true - }, - { - "name": "expression", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": true - }, - { - "name": "status", - "typeName": "AtlasGlossaryTermRelationshipStatus", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": true - }, - { - "name": "confidence", - "description": "The confidence attribute in the semantic assignment stores the level of confidence (0-100%) in the correctness of the semantic assignment - it is typically used by discovery engines.", - "typeName": "int", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": true - }, - { - "name": "createdBy", - "description": "The semantic assignment is created by the user (person or engine) identified by the createdBy attribute.", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": true - }, - { - "name": "steward", - "description": "The steward is the person responsible for assessing the semantic assignment and deciding if it should be approved or not.", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": true - }, - { - "name": "source", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": true - } - ], - "relationshipCategory": "ASSOCIATION", - "propagateTags": "ONE_TO_TWO", - "endDef1": { - "type": "AtlasGlossaryTerm", - "name": "assignedEntities", - "isContainer": false, - "cardinality": "SET" - }, - "endDef2": { - "type": "Referenceable", - "name": "meanings", - "isContainer": false, - "cardinality": "SET" - } - }, - { - "name": "AtlasGlossaryTermAnchor", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "description": "TermAnchor links each term to exactly one Glossary object. This means that this is its home glossary. If the Glossary object is deleted, then so are all of the terms linked to it.", - "endDef1": { - "name": "terms", - "type": "AtlasGlossary", - "cardinality": "SET", - "isContainer": true - }, - "endDef2": { - "name": "anchor", - "type": "AtlasGlossaryTerm", - "cardinality": "SINGLE" - }, - "relationshipCategory": "COMPOSITION", - "propagateTags": "NONE" - }, - { - "name": "AtlasGlossaryTermCategorization", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "description": "TermCategorization is a relationship used to organize terms into categories. A term may be linked with many categories and a category may have many terms linked to it. This relationship may connect terms and categories both in the same glossary or in different glossaries.", - "endDef1": { - "name": "terms", - "type": "AtlasGlossaryCategory", - "cardinality": "SET", - "isContainer": true - }, - "endDef2": { - "name": "categories", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "relationshipCategory": "AGGREGATION", - "propagateTags": "NONE", - "attributeDefs": [ - { - "name": "description", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "status", - "typeName": "AtlasGlossaryTermRelationshipStatus", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "AtlasGlossaryCategoryAnchor", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "description": "CategoryAnchor links each category to exactly one Glossary object. This means that this is its home glossary. If the Glossary object is deleted then so are all of the categories linked to it.", - "endDef1": { - "name": "categories", - "type": "AtlasGlossary", - "cardinality": "SET", - "isContainer": true - }, - "endDef2": { - "name": "anchor", - "type": "AtlasGlossaryCategory", - "cardinality": "SINGLE" - }, - "relationshipCategory": "COMPOSITION", - "propagateTags": "NONE" - }, - { - "name": "AtlasGlossaryCategoryHierarchyLink", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "description": "CategoryHierarchyLink is a relationship used to organize categories into a hierarchy to, for example, create a structure for a taxonomy. A category may have none or one super-categories. This super-category may be in a different glossary.", - "endDef1": { - "name": "childrenCategories", - "type": "AtlasGlossaryCategory", - "cardinality": "SET", - "isContainer": true - }, - "endDef2": { - "name": "parentCategory", - "type": "AtlasGlossaryCategory", - "cardinality": "SINGLE" - }, - "relationshipCategory": "AGGREGATION", - "propagateTags": "NONE" - }, - { - "name": "AtlasGlossaryRelatedTerm", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "description": "RelatedTerm is a relationship used to say that the linked glossary term may also be of interest. It is like a 'see also' link in a dictionary.", - "endDef1": { - "name": "seeAlso", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "endDef2": { - "name": "seeAlso", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "relationshipCategory": "ASSOCIATION", - "propagateTags": "NONE", - "attributeDefs": [ - { - "name": "description", - "description": "The description field can be used to explain why the linked term is of interest.", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "expression", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "status", - "typeName": "AtlasGlossaryTermRelationshipStatus", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "steward", - "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "source", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - } - ] - }, - { - "name": "AtlasGlossarySynonym", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "description": "Synonym is a relationship between glossary terms that have the same, or a very similar meaning in the same language. Notice that both ends of this relationship have the same name and refer to the same type; this results in one Synonym attribute being added to GlossaryTerm.", - "endDef1": { - "name": "synonyms", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "endDef2": { - "name": "synonyms", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "relationshipCategory": "ASSOCIATION", - "propagateTags": "NONE", - "attributeDefs": [ - { - "name": "description", - "description": "The description field can be used to add details about the relationship.", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "expression", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "status", - "typeName": "AtlasGlossaryTermRelationshipStatus", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "steward", - "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not.", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "source", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - } - ] - }, - { - "name": "AtlasGlossaryAntonym", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "description": "Antonym is a relationship between glossary terms that have the opposite (or near opposite) meaning, in the same language. Notice that both ends of this relationship have the same name and refer to the same type; this results in one Antonym attribute being added to GlossaryTerm.", - "endDef1": { - "name": "antonyms", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "endDef2": { - "name": "antonyms", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "relationshipCategory": "ASSOCIATION", - "propagateTags": "NONE", - "attributeDefs": [ - { - "name": "description", - "description": "The description field can be used to add details about the relationship.", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "expression", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "status", - "typeName": "AtlasGlossaryTermRelationshipStatus", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "steward", - "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not.", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "source", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - } - ] - }, - { - "name": "AtlasGlossaryPreferredTerm", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "description": "PreferredTerm is a relationship that indicates that the preferredTerm should be used in place of the preferredToTerm. This relationship can be used to encourage adoption of newer vocabularies. This is a weaker version of ReplacementTerm.", - "endDef1": { - "name": "preferredTerms", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "endDef2": { - "name": "preferredToTerms", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "relationshipCategory": "ASSOCIATION", - "propagateTags": "NONE", - "attributeDefs": [ - { - "name": "description", - "description": "The description field can be used to add details about the relationship.", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "expression", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "status", - "typeName": "AtlasGlossaryTermRelationshipStatus", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "steward", - "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not.", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "source", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - } - ] - }, - { - "name": "AtlasGlossaryReplacementTerm", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "description": "ReplacementTerm is a relationship that indicates that the replacementTerm must be used instead of the replacedByTerm. This is stronger version of the PreferredTerm.", - "endDef1": { - "name": "replacedBy", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "endDef2": { - "name": "replacementTerms", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "relationshipCategory": "ASSOCIATION", - "propagateTags": "NONE", - "attributeDefs": [ - { - "name": "description", - "description": "The description field can be used to add details about the relationship.", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "expression", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "status", - "typeName": "AtlasGlossaryTermRelationshipStatus", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "steward", - "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "source", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - } - ] - }, - { - "name": "AtlasGlossaryTranslation", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "description": "Translation is a relationship that defines that the related terms represent the same meaning, but each are written in a different language. Hence one is a translation of the other. The language of each term is defined in the Glossary object that anchors the term.", - "endDef1": { - "name": "translatedTerms", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "endDef2": { - "name": "translationTerms", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "relationshipCategory": "ASSOCIATION", - "propagateTags": "NONE", - "attributeDefs": [ - { - "name": "description", - "description": "The description field can be used to add details about the relationship.", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "expression", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "status", - "typeName": "AtlasGlossaryTermRelationshipStatus", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "steward", - "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "source", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - } - ] - }, - { - "name": "AtlasGlossaryIsARelationship", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "description": "IsA is a relationship that defines that the 'isA' term is a more generic term than the 'isOf' term. For example, this relationship would be use to say that 'Cat' ISA 'Animal'.", - "endDef1": { - "name": "classifies", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "endDef2": { - "name": "isA", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "relationshipCategory": "ASSOCIATION", - "propagateTags": "NONE", - "attributeDefs": [ - { - "name": "description", - "description": "The description field can be used to add details about the relationship.", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "expression", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "status", - "typeName": "AtlasGlossaryTermRelationshipStatus", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "steward", - "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not.", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "source", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - } - ] - }, - { - "name": "AtlasGlossaryValidValue", - "serviceType": "atlas_core", - "typeVersion": "1.0", - "description": "ValidValue is a relationship that shows the validValue term represents one of the valid values that could be assigned to a data item that has the meaning described in the validValueFor term.", - "endDef1": { - "name": "validValuesFor", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "endDef2": { - "name": "validValues", - "type": "AtlasGlossaryTerm", - "cardinality": "SET" - }, - "relationshipCategory": "ASSOCIATION", - "propagateTags": "NONE", - "attributeDefs": [ - { - "name": "description", - "description": "The description field can be used to add details about the relationship.", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "expression", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "status", - "typeName": "AtlasGlossaryTermRelationshipStatus", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "steward", - "description": "The steward is the person responsible for assessing the relationship and deciding if it should be approved or not.", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "source", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - } - ] - } - ] -} \ No newline at end of file diff --git a/addons/models/0000-Area0/patches/001-base_model_replication_attributes.json b/addons/models/0000-Area0/patches/001-base_model_replication_attributes.json deleted file mode 100644 index 1bedea78d06..00000000000 --- a/addons/models/0000-Area0/patches/001-base_model_replication_attributes.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_0000_001", - "description": "Add 'replicatedFrom' and 'replicatedTo' attributes to Referenceable", - "action": "ADD_ATTRIBUTE", - "typeName": "Referenceable", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "params": null, - "attributeDefs": [ - { - "name": "replicatedFrom", - "typeName": "array", - "cardinality": "SET", - "isIndexable": false, - "isOptional": true, - "isUnique": false, - "options": { - "isSoftReference": "true" - } - }, - { - "name": "replicatedTo", - "typeName": "array", - "cardinality": "SET", - "isIndexable": false, - "isOptional": true, - "isUnique": false, - "options": { - "isSoftReference": "true" - } - } - ] - } - ] -} diff --git a/addons/models/0000-Area0/patches/002-base_model_add_service_type.json b/addons/models/0000-Area0/patches/002-base_model_add_service_type.json index 13e55fa0504..8e375f7c9e7 100644 --- a/addons/models/0000-Area0/patches/002-base_model_add_service_type.json +++ b/addons/models/0000-Area0/patches/002-base_model_add_service_type.json @@ -1,14 +1,5 @@ { "patches": [ - { - "id": "TYPEDEF_PATCH_0000_002", - "description": "Set serviceType 'atlas_core' to Referenceable", - "action": "SET_SERVICE_TYPE", - "typeName": "Referenceable", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "serviceType": "atlas_core" - }, { "id": "TYPEDEF_PATCH_0000_003", "description": "Set serviceType 'atlas_core' to __internal", @@ -18,42 +9,6 @@ "updateToVersion": "1.1", "serviceType": "atlas_core" }, - { - "id": "TYPEDEF_PATCH_0000_004", - "description": "Set serviceType 'atlas_core' to Asset", - "action": "SET_SERVICE_TYPE", - "typeName": "Asset", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_005", - "description": "Set serviceType 'atlas_core' to DataSet", - "action": "SET_SERVICE_TYPE", - "typeName": "DataSet", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_006", - "description": "Set serviceType 'atlas_core' to Infrastructure", - "action": "SET_SERVICE_TYPE", - "typeName": "Infrastructure", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_007", - "description": "Set serviceType 'atlas_core' to Process", - "action": "SET_SERVICE_TYPE", - "typeName": "Process", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "serviceType": "atlas_core" - }, { "id": "TYPEDEF_PATCH_0000_008", "description": "Set serviceType 'atlas_core' to AtlasServer", @@ -90,24 +45,6 @@ "updateToVersion": "1.1", "serviceType": "atlas_core" }, - { - "id": "TYPEDEF_PATCH_0000_012", - "description": "Set serviceType 'atlas_core' to dataset_process_inputs", - "action": "SET_SERVICE_TYPE", - "typeName": "dataset_process_inputs", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_013", - "description": "Set serviceType 'atlas_core' to process_dataset_outputs", - "action": "SET_SERVICE_TYPE", - "typeName": "process_dataset_outputs", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, { "id": "TYPEDEF_PATCH_0000_014", "description": "Set serviceType 'atlas_core' to __AtlasUserProfile_savedsearches", @@ -116,168 +53,6 @@ "applyToVersion": "1.0", "updateToVersion": "1.1", "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_015", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryTermRelationshipStatus", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryTermRelationshipStatus", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_016", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryTermAssignmentStatus", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryTermAssignmentStatus", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_017", - "description": "Set serviceType 'atlas_core' to AtlasGlossary", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossary", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_018", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryTerm", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryTerm", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_019", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryCategory", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryCategory", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_020", - "description": "Set serviceType 'atlas_core' to AtlasGlossarySemanticAssignment", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossarySemanticAssignment", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_021", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryTermAnchor", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryTermAnchor", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_022", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryTermCategorization", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryTermCategorization", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_023", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryCategoryAnchor", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryCategoryAnchor", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_024", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryCategoryHierarchyLink", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryCategoryHierarchyLink", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_025", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryRelatedTerm", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryRelatedTerm", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_026", - "description": "Set serviceType 'atlas_core' to AtlasGlossarySynonym", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossarySynonym", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_027", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryAntonym", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryAntonym", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_028", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryPreferredTerm", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryPreferredTerm", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_029", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryReplacementTerm", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryReplacementTerm", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_030", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryTranslation", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryTranslation", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_031", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryIsARelationship", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryIsARelationship", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" - }, - { - "id": "TYPEDEF_PATCH_0000_032", - "description": "Set serviceType 'atlas_core' to AtlasGlossaryValidValue", - "action": "SET_SERVICE_TYPE", - "typeName": "AtlasGlossaryValidValue", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "atlas_core" } ] } diff --git a/addons/models/0000-Area0/patches/003-base_model_add_searchWeight.json b/addons/models/0000-Area0/patches/003-base_model_add_searchWeight.json deleted file mode 100644 index 4c69fb56af4..00000000000 --- a/addons/models/0000-Area0/patches/003-base_model_add_searchWeight.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_0000_033", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "Referenceable", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "qualifiedName", - "params": { - "searchWeight": 10 - } - }, { - "id": "TYPEDEF_PATCH_0000_034", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "Asset", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "name", - "params": { - "searchWeight": 10 - } - }, { - "id": "TYPEDEF_PATCH_0000_035", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "Asset", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "description", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_0000_036", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "Asset", - "applyToVersion": "1.4", - "updateToVersion": "1.5", - "attributeName": "owner", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_0000_037", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "AtlasServer", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "name", - "params": { - "searchWeight": 10 - } - }, { - "id": "TYPEDEF_PATCH_0000_038", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "AtlasServer", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "displayName", - "params": { - "searchWeight": 10 - } - }, { - "id": "TYPEDEF_PATCH_0000_039", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "AtlasServer", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "fullName", - "params": { - "searchWeight": 10 - } - } - ] -} diff --git a/addons/models/0000-Area0/patches/004-glossary_model_add_additionalAttributes.json b/addons/models/0000-Area0/patches/004-glossary_model_add_additionalAttributes.json deleted file mode 100644 index 43a072c5c03..00000000000 --- a/addons/models/0000-Area0/patches/004-glossary_model_add_additionalAttributes.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_0001_004", - "description": "Add 'additionalAttributes' attribute to AtlasGlossary", - "action": "ADD_ATTRIBUTE", - "typeName": "AtlasGlossary", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": null, - "attributeDefs": [ - { - "name": "additionalAttributes", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - - ] - }, - { - "id": "TYPEDEF_PATCH_0002_004", - "description": "Add 'additionalAttributes' attribute to AtlasGlossaryTerm", - "action": "ADD_ATTRIBUTE", - "typeName": "AtlasGlossaryTerm", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": null, - "attributeDefs": [ - { - "name": "additionalAttributes", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - - ] - }, - { - "id": "TYPEDEF_PATCH_0003_004", - "description": "Add 'additionalAttributes' attribute to AtlasGlossaryCategory", - "action": "ADD_ATTRIBUTE", - "typeName": "AtlasGlossaryCategory", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": null, - "attributeDefs": [ - { - "name": "additionalAttributes", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - - ] - } - ] -} diff --git a/addons/models/0000-Area0/patches/005-base_model_add_display_attributes.json b/addons/models/0000-Area0/patches/005-base_model_add_display_attributes.json deleted file mode 100644 index 41c8c4d27d1..00000000000 --- a/addons/models/0000-Area0/patches/005-base_model_add_display_attributes.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_0005_001", - "description": "Add displayName and userDescription to Asset", - "action": "ADD_ATTRIBUTE", - "typeName": "Asset", - "applyToVersion": "1.5", - "updateToVersion": "1.6", - "params": null, - "attributeDefs": [ - { - "name": "displayName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "indexType": "STRING" - }, - { - "name": "userDescription", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "indexType": "STRING" - } - ] - } - ] -} diff --git a/addons/models/1000-Hadoop/1020-fs_model.json b/addons/models/1000-Hadoop/1020-fs_model.json deleted file mode 100644 index 6d7b95a6f20..00000000000 --- a/addons/models/1000-Hadoop/1020-fs_model.json +++ /dev/null @@ -1,207 +0,0 @@ -{ - "enumDefs": [ - { - "name": "file_action", - "typeVersion": "1.0", - "serviceType": "file_system", - "elementDefs": [ - { - "ordinal": 0, - "value": "NONE" - }, - { - "ordinal": 1, - "value": "EXECUTE" - }, - { - "ordinal": 2, - "value": "WRITE" - }, - { - "ordinal": 3, - "value": "WRITE_EXECUTE" - }, - { - "ordinal": 4, - "value": "READ" - }, - { - "ordinal": 5, - "value": "READ_EXECUTE" - }, - { - "ordinal": 6, - "value": "READ_WRITE" - }, - { - "ordinal": 7, - "value": "ALL" - } - ] - } - ], - "structDefs": [ - { - "name": "fs_permissions", - "serviceType": "file_system", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "group", - "typeName": "file_action", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "user", - "typeName": "file_action", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "sticky", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "others", - "typeName": "file_action", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - } - ] - } - ], - "classificationDefs": [], - "entityDefs": [ - { - "name": "fs_path", - "superTypes": [ - "DataSet", - "Path" - ], - "serviceType": "file_system", - "typeVersion": "1.1", - "attributeDefs": [ - { - "name": "path", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "includeInNotification": true, - "isUnique": false - }, - { - "name": "createTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "modifiedTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "isFile", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "isSymlink", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "fileSize", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "group", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "posixPermissions", - "typeName": "fs_permissions", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "hdfs_path", - "superTypes": [ - "fs_path" - ], - "serviceType": "file_system", - "typeVersion": "1.1", - "attributeDefs": [ - { - "name": "clusterName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "includeInNotification": true, - "isUnique": false - }, - { - "name": "numberOfReplicas", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "extendedAttributes", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "nameServiceId", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "includeInNotification": true, - "isUnique": false - } - ] - } - ] -} diff --git a/addons/models/1000-Hadoop/1030-hive_model.json b/addons/models/1000-Hadoop/1030-hive_model.json deleted file mode 100644 index 79beee84579..00000000000 --- a/addons/models/1000-Hadoop/1030-hive_model.json +++ /dev/null @@ -1,740 +0,0 @@ -{ - "enumDefs": [ - { - "name": "hive_principal_type", - "serviceType": "hive", - "typeVersion": "1.0", - "elementDefs": [ - { - "ordinal": 1, - "value": "USER" - }, - { - "ordinal": 2, - "value": "ROLE" - }, - { - "ordinal": 3, - "value": "GROUP" - } - ] - } - ], - "structDefs": [ - { - "name": "hive_order", - "serviceType": "hive", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "order", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "col", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - } - ] - }, - { - "name": "hive_serde", - "serviceType": "hive", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "name", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "serializationLib", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "parameters", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - } - ], - "classificationDefs": [], - "entityDefs": [ - { - "name": "hive_process", - "superTypes": [ - "Process" - ], - "serviceType": "hive", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "startTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "endTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "userName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "operationType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "queryText", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "queryPlan", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "queryId", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "recentQueries", - "typeName": "array", - "cardinality": "LIST", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "clusterName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "includeInNotification": true, - "isUnique": false - }, - { - "name": "queryGraph", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "hive_table", - "superTypes": [ - "DataSet" - ], - "serviceType": "hive", - "typeVersion": "1.1", - "options": { - "schemaElementsAttribute": "columns" - }, - "attributeDefs": [ - { - "name": "createTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "lastAccessTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "comment", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "retention", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "aliases", - "typeName": "array", - "cardinality": "SET", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "parameters", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "viewOriginalText", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "viewExpandedText", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "tableType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "temporary", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "hive_storagedesc", - "superTypes": [ - "Referenceable" - ], - "serviceType": "hive", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "location", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "inputFormat", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "outputFormat", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "compressed", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "numBuckets", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "serdeInfo", - "typeName": "hive_serde", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "bucketCols", - "typeName": "array", - "cardinality": "SET", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "sortCols", - "typeName": "array", - "cardinality": "SET", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "parameters", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "storedAsSubDirectories", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "hive_db", - "superTypes": [ - "Asset" - ], - "serviceType": "hive", - "typeVersion": "1.1", - "attributeDefs": [ - { - "name": "clusterName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "includeInNotification": true, - "isUnique": false - }, - { - "name": "location", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "parameters", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "ownerType", - "typeName": "hive_principal_type", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "hive_column", - "superTypes": [ - "DataSet" - ], - "serviceType": "hive", - "typeVersion": "1.3", - "options": { - "schemaAttributes": "[\"name\", \"description\", \"owner\", \"type\", \"comment\", \"position\"]" - }, - "attributeDefs": [ - { - "name": "type", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "comment", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "position", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name" : "hive_column_lineage", - "superTypes" : [ - "Process" - ], - "serviceType": "hive", - "typeVersion" : "1.0", - "attributeDefs" : [ - { - "name": "depenendencyType", - "typeName": "string", - "cardinality" : "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "expression", - "typeName": "string", - "cardinality" : "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name" : "hive_process_execution", - "superTypes" : [ - "ProcessExecution" - ], - "serviceType": "hive", - "typeVersion" : "1.1", - "attributeDefs" : [ - { - "name": "startTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "endTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "userName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "queryText", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "queryGraph", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "queryId", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "queryPlan", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "hostName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - } - ], - "options": { - "displayTextAttribute": "queryText" - } - }, - { - "name": "hive_db_ddl", - "superTypes": [ - "ddl" - ], - "serviceType": "hive", - "typeVersion": "1.0", - "attributeDefs": [] - }, - { - "name": "hive_table_ddl", - "superTypes": [ - "ddl" - ], - "serviceType": "hive", - "typeVersion": "1.0", - "attributeDefs": [] - } - ], - "relationshipDefs": [ - { - "name": "hive_table_db", - "serviceType": "hive", - "typeVersion": "1.2", - "relationshipCategory": "AGGREGATION", - "relationshipLabel": "__hive_table.db", - "endDef1": { - "type": "hive_table", - "name": "db", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "hive_db", - "name": "tables", - "isContainer": true, - "cardinality": "SET" - }, - "propagateTags": "NONE" - }, - { - "name": "hive_table_columns", - "serviceType": "hive", - "typeVersion": "1.2", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__hive_table.columns", - "endDef1": { - "type": "hive_table", - "name": "columns", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "hive_column", - "name": "table", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "propagateTags": "NONE" - }, - { - "name": "hive_table_partitionkeys", - "serviceType": "hive", - "typeVersion": "1.2", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__hive_table.partitionKeys", - "endDef1": { - "type": "hive_table", - "name": "partitionKeys", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "hive_column", - "name": "table", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "propagateTags": "NONE" - }, - { - "name": "hive_table_storagedesc", - "serviceType": "hive", - "typeVersion": "1.2", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__hive_table.sd", - "endDef1": { - "type": "hive_table", - "name": "sd", - "isContainer": true, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "hive_storagedesc", - "name": "table", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "propagateTags": "NONE" - }, - { - "name": "hive_process_column_lineage", - "serviceType": "hive", - "typeVersion": "1.2", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__hive_column_lineage.query", - "endDef1": { - "type": "hive_column_lineage", - "name": "query", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "hive_process", - "name": "columnLineages", - "isContainer": true, - "cardinality": "SET" - }, - "propagateTags": "NONE" - }, - { - "name": "hive_process_process_executions", - "serviceType": "hive", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "hive_process", - "name": "processExecutions", - "cardinality": "SET", - "isContainer": true - }, - "endDef2": { - "type": "hive_process_execution", - "name": "process", - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - }, - { - "name": "hive_table_ddl_queries", - "serviceType": "hive", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "hive_table", - "name": "ddlQueries", - "isContainer": true, - "cardinality": "SET" - }, - "endDef2": { - "type": "hive_table_ddl", - "name": "table", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - }, - { - "name": "hive_db_ddl_queries", - "serviceType": "hive", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "hive_db", - "name": "ddlQueries", - "isContainer": true, - "cardinality": "SET" - }, - "endDef2": { - "type": "hive_db_ddl", - "name": "db", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - }, - { - "name": "hive_db_location", - "serviceType": "hive", - "typeVersion": "1.0", - "relationshipCategory": "ASSOCIATION", - "endDef1": { - "type": "hive_db", - "name": "locationPath", - "cardinality": "SINGLE" - }, - "endDef2": { - "type": "Path", - "name": "hiveDb", - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - } - ] -} diff --git a/addons/models/1000-Hadoop/1040-sqoop_model.json b/addons/models/1000-Hadoop/1040-sqoop_model.json deleted file mode 100644 index 928c6f1b947..00000000000 --- a/addons/models/1000-Hadoop/1040-sqoop_model.json +++ /dev/null @@ -1,99 +0,0 @@ -{ - "enumDefs": [], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ - { - "name": "sqoop_process", - "superTypes": [ - "Process" - ], - "serviceType": "sqoop", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "operation", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "commandlineOpts", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "startTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "endTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "userName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "sqoop_dbdatastore", - "superTypes": [ - "DataSet" - ], - "serviceType": "sqoop", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "dbStoreType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "storeUse", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "storeUri", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "source", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - } - ] -} diff --git a/addons/models/1000-Hadoop/1050-falcon_model.json b/addons/models/1000-Hadoop/1050-falcon_model.json deleted file mode 100644 index e2044706bf7..00000000000 --- a/addons/models/1000-Hadoop/1050-falcon_model.json +++ /dev/null @@ -1,192 +0,0 @@ -{ - "enumDefs": [], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ - { - "name": "falcon_feed_replication", - "superTypes": [ - "Process" - ], - "serviceType": "falcon", - "typeVersion": "1.0", - "attributeDefs": [] - }, - { - "name": "falcon_cluster", - "superTypes": [ - "Infrastructure" - ], - "serviceType": "falcon", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "colo", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "tags", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "falcon_feed", - "superTypes": [ - "DataSet" - ], - "serviceType": "falcon", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "frequency", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "groups", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "tags", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "falcon_process", - "superTypes": [ - "Process" - ], - "serviceType": "falcon", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "frequency", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "tags", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "pipelines", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "workflow-properties", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "falcon_feed_creation", - "superTypes": [ - "Process" - ], - "serviceType": "falcon", - "typeVersion": "1.0", - "attributeDefs": [] - } - ], - "relationshipDefs": [ - { - "name": "falcon_feed_cluster", - "serviceType": "falcon", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__falcon_feed.stored-in", - "endDef1": { - "type": "falcon_feed", - "name": "stored-in", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "falcon_cluster", - "name": "feeds", - "isContainer": true, - "cardinality": "SET" - }, - "propagateTags": "NONE" - }, - { - "name": "falcon_cluster_process", - "serviceType": "falcon", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__falcon_cluster.processes", - "endDef1": { - "type": "falcon_cluster", - "name": "processes", - "isContainer": true, - "cardinality": "SET" - }, - "endDef2": { - "type": "falcon_process", - "name": "runs-on", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "propagateTags": "NONE" - }, - { - "name": "falcon_cluster_feed_creation", - "serviceType": "falcon", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__falcon_cluster.feedCreations", - "endDef1": { - "type": "falcon_cluster", - "name": "feedCreations", - "isContainer": true, - "cardinality": "SET" - }, - "endDef2": { - "type": "falcon_feed_creation", - "name": "stored-in", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "propagateTags": "NONE" - } - ] -} \ No newline at end of file diff --git a/addons/models/1000-Hadoop/1060-hbase_model.json b/addons/models/1000-Hadoop/1060-hbase_model.json deleted file mode 100644 index d19fed22c6b..00000000000 --- a/addons/models/1000-Hadoop/1060-hbase_model.json +++ /dev/null @@ -1,153 +0,0 @@ -{ - "enumDefs": [], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ - { - "name": "hbase_namespace", - "superTypes": [ - "Asset" - ], - "serviceType": "hbase", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "clusterName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "includeInNotification": true, - "isUnique": false - }, - { - "name": "parameters", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "createTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "modifiedTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "hbase_table", - "superTypes": [ - "DataSet" - ], - "serviceType": "hbase", - "typeVersion": "1.1", - "attributeDefs": [ - { - "name": "uri", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - } - ] - }, - { - "name": "hbase_column_family", - "superTypes": [ - "DataSet" - ], - "serviceType": "hbase", - "typeVersion": "1.0", - "attributeDefs": [] - }, - { - "name": "hbase_column", - "superTypes": [ - "DataSet" - ], - "serviceType": "hbase", - "typeVersion": "1.0", - "attributeDefs": [] - } - ], - "relationshipDefs": [ - { - "name": "hbase_table_namespace", - "serviceType": "hbase", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__hbase_table.namespace", - "endDef1": { - "type": "hbase_table", - "name": "namespace", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "hbase_namespace", - "name": "tables", - "isContainer": true, - "cardinality": "SET" - }, - "propagateTags": "NONE" - }, - { - "name": "hbase_table_column_families", - "serviceType": "hbase", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__hbase_table.column_families", - "endDef1": { - "type": "hbase_table", - "name": "column_families", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "hbase_column_family", - "name": "table", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "propagateTags": "NONE" - }, - { - "name": "hbase_column_family_columns", - "serviceType": "hbase", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__hbase_column_family.columns", - "endDef1": { - "type": "hbase_column_family", - "name": "columns", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "hbase_column", - "name": "column_family", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "propagateTags": "NONE" - } - ] -} \ No newline at end of file diff --git a/addons/models/1000-Hadoop/1065-avro_model.json b/addons/models/1000-Hadoop/1065-avro_model.json deleted file mode 100644 index fdb9686609f..00000000000 --- a/addons/models/1000-Hadoop/1065-avro_model.json +++ /dev/null @@ -1,262 +0,0 @@ -{ - "enumDefs": [], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ - { - "name": "avro_type", - "description": "Atlas Type representing Abstract Avro Type", - "superTypes": [ - "DataSet" - ], - "serviceType": "avro", - "typeVersion": "1.0", - "attributeDefs": [ - ] - }, - { - "name": "avro_field", - "description": "Atlas Type representing an Avro Field", - "superTypes": [ - "avro_type" - ], - "serviceType": "avro", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "doc", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "default", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "avro_record", - "description": "Atlas Type representing Abstract Avro Schema", - "superTypes": [ - "avro_type" - ], - "serviceType": "avro", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "type", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "doc", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "avro_notation", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "versionId", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "isLatest", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "avroClass", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "avro_schema", - "description": "Atlas Type representing Abstract Top-level Avro Schema", - "superTypes": [ - "avro_record" - ], - "serviceType": "avro", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "namespace", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - } - ] - }, - { - "name": "avro_primitive", - "description": "Atlas Type representing an Avro primitive datatype", - "superTypes": [ - "avro_type" - ], - "serviceType": "avro", - "typeVersion": "1.0", - "attributeDefs": [] - }, - { - "name": "avro_fixed", - "description": "Atlas Type representing an Avro fixed datatype", - "superTypes": [ - "avro_type" - ], - "serviceType": "avro", - "typeVersion": "1.0", - "attributeDefs": [] - }, - { - "name": "avro_enum", - "description": "Atlas Type representing an Avro ENUM datatype", - "superTypes": [ - "avro_type" - ], - "serviceType": "avro", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "type", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "symbols", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - } - ] - }, - { - "name": "avro_collection", - "description": "Atlas Type representing an Avro Array datatype", - "superTypes": [ - "avro_type" - ], - "serviceType": "avro", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "type", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "items", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - } - ] - } - ], - "relationshipDefs": [ - { - "name": "avro_schema_associatedEntities", - "serviceType": "avro", - "typeVersion": "1.0", - "relationshipCategory": "ASSOCIATION", - "relationshipLabel": "__avro_schema.associatedEntities", - "endDef1": { - "type": "avro_schema", - "name": "associatedEntities", - "isContainer": false, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "DataSet", - "name": "schema", - "isContainer": false, - "cardinality": "SET" - }, - "propagateTags": "NONE" - }, - { - "name": "avro_record_fields", - "serviceType": "avro", - "typeVersion": "1.0", - "relationshipCategory": "AGGREGATION", - "relationshipLabel": "__avro_record.fields", - "endDef1": { - "type": "avro_record", - "name": "fields", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "avro_field", - "name": "record", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - }, - { - "name": "avro_field_types", - "serviceType": "avro", - "typeVersion": "1.0", - "relationshipCategory": "ASSOCIATION", - "relationshipLabel": "__avro_field.type", - "endDef1": { - "type": "avro_field", - "name": "type", - "isContainer": false, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "avro_type", - "name": "field", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - } - ] -} \ No newline at end of file diff --git a/addons/models/1000-Hadoop/1070-kafka_model.json b/addons/models/1000-Hadoop/1070-kafka_model.json deleted file mode 100644 index 371f8a7b49a..00000000000 --- a/addons/models/1000-Hadoop/1070-kafka_model.json +++ /dev/null @@ -1,219 +0,0 @@ -{ - "enumDefs": [], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ - { - "name": "kafka_topic", - "superTypes": [ - "DataSet" - ], - "serviceType": "kafka", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "topic", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isInNotification": true, - "isUnique": false - }, - { - "name": "uri", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "replicationFactorNational", - "typeName": "int", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "replicationFactorLocal", - "typeName": "int", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "retentionBytesNational", - "typeName": "long", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "segmentBytesNational", - "typeName": "long", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "segmentBytesLocal", - "typeName": "long", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "contactInfo", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "type", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "partitionCountLocal", - "typeName": "int", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "partitionCountNational", - "typeName": "int", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "retentionBytesLocal", - "typeName": "long", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "retentiontimeLocalInHrs", - "typeName": "int", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "retentiontimeNationalInHrs", - "typeName": "int", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "desiredRetentionInHrs", - "typeName": "int", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "keyClassname", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "numberOfEventsPerDay", - "typeName": "long", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "maxThroughputPerSec", - "typeName": "long", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "avgMessageSizeInBytes", - "typeName": "long", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - } - ] - }, - { - "name": "jms_topic", - "superTypes": [ - "DataSet" - ], - "serviceType": "kafka", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "topic", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "uri", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - } - ] - } - ], - "relationshipDefs": [ - { - "name": "kafka_topic_avroSchema", - "serviceType": "kafka", - "typeVersion": "1.0", - "relationshipCategory": "ASSOCIATION", - "relationshipLabel": "__kafka_topic.avroSchema", - "endDef1": { - "type": "kafka_topic", - "name": "avroSchema", - "isContainer": false, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "avro_type", - "name": "kafka_topics_references", - "isContainer": false, - "cardinality": "SET" - }, - "propagateTags": "NONE" - } - ] -} \ No newline at end of file diff --git a/addons/models/1000-Hadoop/1080-storm_model.json b/addons/models/1000-Hadoop/1080-storm_model.json deleted file mode 100644 index 7363dbb995d..00000000000 --- a/addons/models/1000-Hadoop/1080-storm_model.json +++ /dev/null @@ -1,165 +0,0 @@ -{ - "enumDefs": [], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ - { - "name": "storm_topology", - "superTypes": [ - "Process" - ], - "serviceType": "storm", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "id", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": true - }, - { - "name": "startTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "endTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "conf", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "clusterName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "includeInNotification": true, - "isUnique": false - } - ] - }, - { - "name": "storm_node", - "superTypes": [], - "serviceType": "storm", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "name", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "description", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "driverClass", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "conf", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "storm_spout", - "superTypes": [ - "storm_node" - ], - "serviceType": "storm", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "outputs", - "typeName": "array", - "cardinality": "LIST", - "isIndexable": false, - "isOptional": false, - "isUnique": false - } - ] - }, - { - "name": "storm_bolt", - "superTypes": [ - "storm_node" - ], - "serviceType": "storm", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "inputs", - "typeName": "array", - "cardinality": "LIST", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "outputs", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - } - ], - "relationshipDefs": [ - { - "name": "storm_topology_nodes", - "serviceType": "storm", - "typeVersion": "1.0", - "relationshipCategory": "ASSOCIATION", - "relationshipLabel": "__storm_topology.nodes", - "endDef1": { - "type": "storm_topology", - "name": "nodes", - "isContainer": false, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "storm_node", - "name": "topolgies", - "isContainer": false, - "cardinality": "SET" - }, - "propagateTags": "NONE" - } - ] -} \ No newline at end of file diff --git a/addons/models/1000-Hadoop/1090-impala_model.json b/addons/models/1000-Hadoop/1090-impala_model.json deleted file mode 100644 index 24eb5dbbad1..00000000000 --- a/addons/models/1000-Hadoop/1090-impala_model.json +++ /dev/null @@ -1,232 +0,0 @@ -{ - "enumDefs": [], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ - { - "name": "impala_process", - "superTypes": [ - "Process" - ], - "serviceType": "impala", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "startTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "endTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "userName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "operationType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "queryText", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false, - "searchWeight": 10 - }, - { - "name": "queryPlan", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "queryId", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "recentQueries", - "typeName": "array", - "cardinality": "LIST", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "clusterName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "includeInNotification": true, - "isUnique": false, - "searchWeight": 10 - }, - { - "name": "queryGraph", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name" : "impala_column_lineage", - "superTypes" : [ - "Process" - ], - "serviceType": "impala", - "typeVersion" : "1.0", - "attributeDefs" : [ - { - "name": "dependencyType", - "typeName": "string", - "cardinality" : "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - } - ] - }, - { - "name" : "impala_process_execution", - "superTypes" : [ - "ProcessExecution" - ], - "serviceType": "impala", - "typeVersion" : "1.0", - "attributeDefs" : [ - { - "name": "startTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "endTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "userName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "queryText", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false, - "searchWeight": 10 - }, - { - "name": "queryGraph", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "queryId", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "queryPlan", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "hostName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - } - ] - } - ], - "relationshipDefs": [ - { - "name": "impala_process_column_lineage", - "serviceType": "impala", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "impala_column_lineage", - "name": "query", - "isContainer": false, - "cardinality": "SINGLE" - }, - "endDef2": { - "type": "impala_process", - "name": "columnLineages", - "isContainer": true, - "cardinality": "SET" - }, - "propagateTags": "NONE" - }, - { - "name": "impala_process_process_executions", - "serviceType": "impala", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "impala_process", - "name": "processExecutions", - "cardinality": "SET", - "isContainer": true - }, - "endDef2": { - "type": "impala_process_execution", - "name": "process", - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - } - ] -} diff --git a/addons/models/1000-Hadoop/1100-spark_model.json b/addons/models/1000-Hadoop/1100-spark_model.json deleted file mode 100644 index e630958c17d..00000000000 --- a/addons/models/1000-Hadoop/1100-spark_model.json +++ /dev/null @@ -1,582 +0,0 @@ -{ - "enumDefs": [], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ - { - "name": "spark_db", - "superTypes": [ - "DataSet" - ], - "serviceType": "spark", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "location", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false, - "searchWeight": 5 - }, - { - "name": "clusterName", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false, - "searchWeight": 8 - }, - { - "name": "parameters", - "typeName": "map", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "ownerType", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - } - ] - }, - { - "name": "spark_table", - "superTypes": [ - "DataSet" - ], - "serviceType": "spark", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "tableType", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "provider", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false, - "searchWeight": 5 - }, - { - "name": "partitionColumnNames", - "typeName": "array", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "bucketSpec", - "typeName": "map", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "ownerType", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "createTime", - "typeName": "date", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "parameters", - "typeName": "map", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "comment", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false, - "searchWeight": 9 - }, - { - "name": "unsupportedFeatures", - "typeName": "array", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "viewOriginalText", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false, - "searchWeight": 9 - }, - { - "name": "schemaDesc", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false, - "searchWeight": 5 - }, - { - "name": "partitionProvider", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - } - ] - }, - { - "name": "spark_column", - "superTypes": [ - "DataSet" - ], - "serviceType": "spark", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "type", - "typeName": "string", - "isOptional": false, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": true - }, - { - "name": "nullable", - "typeName": "boolean", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "metadata", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "comment", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false, - "searchWeight": 9 - } - ] - }, - { - "name": "spark_ml_directory", - "superTypes": [ - "DataSet" - ], - "serviceType": "spark", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "uri", - "typeName": "string", - "isOptional": false, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": true, - "searchWeight": 10 - }, - { - "name": "directory", - "typeName": "string", - "isOptional": false, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": true, - "searchWeight": 10 - } - ] - }, - { - "name": "spark_storagedesc", - "superTypes": [ - "Referenceable" - ], - "serviceType": "spark", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "location", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false, - "searchWeight": 10 - }, - { - "name": "inputFormat", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "outputFormat", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "serde", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "compressed", - "typeName": "boolean", - "isOptional": false, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": true - }, - { - "name": "parameters", - "typeName": "map", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - } - ] - }, - { - "name": "spark_ml_model", - "superTypes": [ - "DataSet" - ], - "serviceType": "spark", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "extra", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - } - ] - }, - { - "name": "spark_application", - "superTypes": [ - "Process" - ], - "serviceType": "spark", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "currentUser", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": true, - "searchWeight": 10 - }, - { - "name": "remoteUser", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": true, - "searchWeight": 10 - } - ] - }, - { - "name": "spark_process", - "superTypes": [ - "Process" - ], - "serviceType": "spark", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "executionId", - "typeName": "long", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false, - "searchWeight": 10 - }, - { - "name": "currUser", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false, - "searchWeight": 10 - }, - { - "name": "remoteUser", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false, - "searchWeight": 10 - }, - { - "name": "details", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "sparkPlanDescription", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - } - ] - }, - { - "name" : "spark_column_lineage", - "superTypes" : [ - "Process" - ], - "serviceType": "spark", - "typeVersion" : "1.0" - }, - { - "name": "spark_ml_pipeline", - "superTypes": [ - "DataSet" - ], - "serviceType": "spark", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "extra", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - } - ] - } - ], - "relationshipDefs": [ - { - "name": "spark_table_db", - "serviceType": "spark", - "typeVersion": "1.0", - "relationshipCategory": "AGGREGATION", - "endDef1": { - "type": "spark_table", - "name": "db", - "isContainer": false, - "cardinality": "SINGLE" - }, - "endDef2": { - "type": "spark_db", - "name": "tables", - "isContainer": true, - "cardinality": "SET" - }, - "propagateTags": "NONE" - }, - { - "name": "spark_table_columns", - "serviceType": "spark", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "spark_table", - "name": "columns", - "isContainer": true, - "cardinality": "SET" - }, - "endDef2": { - "type": "spark_column", - "name": "table", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - }, - { - "name": "spark_table_storagedesc", - "serviceType": "spark", - "typeVersion": "1.0", - "relationshipCategory": "ASSOCIATION", - "endDef1": { - "type": "spark_table", - "name": "sd", - "cardinality": "SINGLE" - }, - "endDef2": { - "type": "spark_storagedesc", - "name": "table", - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - }, - { - "name": "spark_ml_model_ml_directory", - "serviceType": "spark", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "spark_ml_model", - "name": "directory", - "isContainer": true, - "cardinality": "SINGLE" - }, - "endDef2": { - "type": "spark_ml_directory", - "name": "model", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - }, - { - "name": "spark_ml_pipeline_ml_directory", - "serviceType": "spark", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "spark_ml_pipeline", - "name": "directory", - "isContainer": true, - "cardinality": "SINGLE" - }, - "endDef2": { - "type": "spark_ml_directory", - "name": "pipeline", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - }, - { - "name": "spark_process_column_lineages", - "serviceType": "spark", - "typeVersion": "1.0", - "relationshipCategory": "AGGREGATION", - "endDef1": { - "type": "spark_column_lineage", - "name": "process", - "isContainer": false, - "cardinality": "SINGLE" - }, - "endDef2": { - "type": "spark_process", - "name": "columnLineages", - "isContainer": true, - "cardinality": "SET" - }, - "propagateTags": "NONE" - }, - { - "name": "spark_application_processes", - "serviceType": "spark", - "typeVersion": "1.0", - "relationshipCategory": "AGGREGATION", - "endDef1": { - "type": "spark_application", - "name": "processes", - "cardinality": "SET", - "isContainer": true - }, - "endDef2": { - "type": "spark_process", - "name": "application", - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - }, - { - "name": "spark_ml_model_dataset", - "serviceType": "spark", - "typeVersion": "1.0", - "relationshipCategory": "ASSOCIATION", - "endDef1": { - "type": "spark_ml_model", - "name": "dataset", - "cardinality": "SINGLE" - }, - "endDef2": { - "type": "DataSet", - "name": "model", - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - }, - { - "name": "spark_ml_pipeline_dataset", - "serviceType": "spark", - "typeVersion": "1.0", - "relationshipCategory": "ASSOCIATION", - "endDef1": { - "type": "spark_ml_pipeline", - "name": "dataset", - "cardinality": "SINGLE" - }, - "endDef2": { - "type": "DataSet", - "name": "pipeline", - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - } - ] -} diff --git a/addons/models/1000-Hadoop/1110-flink_model.json b/addons/models/1000-Hadoop/1110-flink_model.json deleted file mode 100644 index 029600fa3ea..00000000000 --- a/addons/models/1000-Hadoop/1110-flink_model.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "entityDefs": [ - { - "name": "flink_application", - "superTypes": [ - "Process" - ], - "serviceType": "flink", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "id", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": true - }, - { - "name": "startTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "endTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "conf", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "flink_process", - "superTypes": [ - "Process" - ], - "serviceType": "flink", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "id", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": true - }, - { - "name": "startTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "endTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "conf", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "flink_application_processes", - "serviceType": "flink", - "typeVersion": "1.0", - "relationshipCategory": "AGGREGATION", - "endDef1": { - "type": "flink_application", - "name": "processes", - "cardinality": "SET", - "isContainer": true - }, - "endDef2": { - "type": "flink_process", - "name": "application", - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - } - ] -}' \ No newline at end of file diff --git a/addons/models/1000-Hadoop/patches/001-hive_column_add_position.json b/addons/models/1000-Hadoop/patches/001-hive_column_add_position.json deleted file mode 100644 index 703a4c3b52c..00000000000 --- a/addons/models/1000-Hadoop/patches/001-hive_column_add_position.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_033", - "description": "Add 'position' attribute to hive_column", - "action": "ADD_ATTRIBUTE", - "typeName": "hive_column", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "params": null, - "attributeDefs": [ - { - "name": "position", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - } - ] -} diff --git a/addons/models/1000-Hadoop/patches/002-hive_column_table_add_options.json b/addons/models/1000-Hadoop/patches/002-hive_column_table_add_options.json deleted file mode 100644 index 697cecd51d2..00000000000 --- a/addons/models/1000-Hadoop/patches/002-hive_column_table_add_options.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_034", - "description": "Add 'schemaAttributes' typeDefOptions to hive_column", - "action": "UPDATE_TYPEDEF_OPTIONS", - "typeName": "hive_column", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "typeDefOptions": { - "schemaAttributes": "[\"name\", \"description\", \"owner\", \"type\", \"comment\", \"position\"]" - } - }, - { - "id": "TYPEDEF_PATCH_1000_035", - "description": "Add 'schemaElementsAttribute' typeDefOptions to hive_table", - "action": "UPDATE_TYPEDEF_OPTIONS", - "typeName": "hive_table", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "typeDefOptions": { - "schemaElementsAttribute": "columns" - } - } - ] -} \ No newline at end of file diff --git a/addons/models/1000-Hadoop/patches/003-hive_column_update_table_remove_constraint.json b/addons/models/1000-Hadoop/patches/003-hive_column_update_table_remove_constraint.json deleted file mode 100644 index 4bfb4be5ec7..00000000000 --- a/addons/models/1000-Hadoop/patches/003-hive_column_update_table_remove_constraint.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_036", - "description": "Update 'table' attribute in hive_column", - "action": "UPDATE_ATTRIBUTE", - "typeName": "hive_column", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "params": null, - "attributeDefs": [ - { - "name": "table", - "typeName": "hive_table", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - } - ] -} diff --git a/addons/models/1000-Hadoop/patches/004-hbase_table_column_family_add_attribute.json b/addons/models/1000-Hadoop/patches/004-hbase_table_column_family_add_attribute.json deleted file mode 100644 index 15a3ac97dad..00000000000 --- a/addons/models/1000-Hadoop/patches/004-hbase_table_column_family_add_attribute.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_037", - "description": "Add 'parameters', 'createTime' and 'modifiedTime' attributes to hbase_table", - "action": "ADD_ATTRIBUTE", - "typeName": "hbase_table", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": null, - "attributeDefs": [ - { - "name": "parameters", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "createTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "modifiedTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "id": "TYPEDEF_PATCH_1000_038", - "description": "Add 'createTime' and 'modifiedTime' attributes to hbase_column_family", - "action": "ADD_ATTRIBUTE", - "typeName": "hbase_column_family", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "params": null, - "attributeDefs": [ - { - "name": "createTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "modifiedTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - } - ] -} \ No newline at end of file diff --git a/addons/models/1000-Hadoop/patches/005-hbase_table_column_family_add_additional_attribute.json b/addons/models/1000-Hadoop/patches/005-hbase_table_column_family_add_additional_attribute.json deleted file mode 100644 index 4daeeae21ec..00000000000 --- a/addons/models/1000-Hadoop/patches/005-hbase_table_column_family_add_additional_attribute.json +++ /dev/null @@ -1,235 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_039", - "description": "Add attributes to hbase_table", - "action": "ADD_ATTRIBUTE", - "typeName": "hbase_table", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "params": null, - "attributeDefs": [ - { - "name": "maxFileSize", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "isReadOnly", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "isCompactionEnabled", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "isNormalizationEnabled", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "replicasPerRegion", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "durability", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - - ] - }, - { - "id": "TYPEDEF_PATCH_1000_040", - "description": "Add attributes to hbase_column_family", - "action": "ADD_ATTRIBUTE", - "typeName": "hbase_column_family", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": null, - "attributeDefs": [ - { - "name": "bloomFilterType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "compressionType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "compactionCompressionType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "encryptionType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "inMemoryCompactionPolicy", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "keepDeletedCells", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "maxVersions", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "minVersions", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "dataBlockEncoding", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "StoragePolicy", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "ttl", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "blockCacheEnabled", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "cacheBloomsOnWrite", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "cacheDataOnWrite", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "cacheIndexesOnWrite", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "evictBlocksOnClose", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "prefetchBlocksOnOpen", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "newVersionBehavior", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "isMobEnabled", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "mobCompactPartitionPolicy", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - } - ] -} \ No newline at end of file diff --git a/addons/models/1000-Hadoop/patches/006-kafka_topic_add_attribute.json b/addons/models/1000-Hadoop/patches/006-kafka_topic_add_attribute.json deleted file mode 100644 index c3711b10978..00000000000 --- a/addons/models/1000-Hadoop/patches/006-kafka_topic_add_attribute.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_041", - "description": "Add 'partitionCount' attribute to kafka_topic", - "action": "ADD_ATTRIBUTE", - "typeName": "kafka_topic", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "params": null, - "attributeDefs": [ - { - "name": "partitionCount", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - } - ] -} diff --git a/addons/models/1000-Hadoop/patches/007-hadoop_model_add_service_type.json b/addons/models/1000-Hadoop/patches/007-hadoop_model_add_service_type.json deleted file mode 100644 index 4ef257f0e68..00000000000 --- a/addons/models/1000-Hadoop/patches/007-hadoop_model_add_service_type.json +++ /dev/null @@ -1,490 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_042", - "description": "Set serviceType 'file_system' to file_action", - "action": "SET_SERVICE_TYPE", - "typeName": "file_action", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "file_system" - }, - { - "id": "TYPEDEF_PATCH_1000_043", - "description": "Set serviceType 'file_system' to fs_permissions", - "action": "SET_SERVICE_TYPE", - "typeName": "fs_permissions", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "file_system" - }, - { - "id": "TYPEDEF_PATCH_1000_044", - "description": "Set serviceType 'file_system' to fs_path", - "action": "SET_SERVICE_TYPE", - "typeName": "fs_path", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "file_system" - }, - { - "id": "TYPEDEF_PATCH_1000_045", - "description": "Set serviceType 'file_system' to hdfs_path", - "action": "SET_SERVICE_TYPE", - "typeName": "hdfs_path", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "serviceType": "file_system" - }, - { - "id": "TYPEDEF_PATCH_1000_046", - "description": "Set serviceType 'hive' to hive_principal_type", - "action": "SET_SERVICE_TYPE", - "typeName": "hive_principal_type", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hive" - }, - { - "id": "TYPEDEF_PATCH_1000_047", - "description": "Set serviceType 'hive' to hive_order", - "action": "SET_SERVICE_TYPE", - "typeName": "hive_order", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hive" - }, - { - "id": "TYPEDEF_PATCH_1000_048", - "description": "Set serviceType 'hive' to hive_serde", - "action": "SET_SERVICE_TYPE", - "typeName": "hive_serde", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hive" - }, - { - "id": "TYPEDEF_PATCH_1000_049", - "description": "Set serviceType 'hive' to hive_process", - "action": "SET_SERVICE_TYPE", - "typeName": "hive_process", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hive" - }, - { - "id": "TYPEDEF_PATCH_1000_050", - "description": "Set serviceType 'hive' to hive_table", - "action": "SET_SERVICE_TYPE", - "typeName": "hive_table", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "serviceType": "hive" - }, - { - "id": "TYPEDEF_PATCH_1000_051", - "description": "Set serviceType 'hive' to hive_storagedesc", - "action": "SET_SERVICE_TYPE", - "typeName": "hive_storagedesc", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hive" - }, - { - "id": "TYPEDEF_PATCH_1000_052", - "description": "Set serviceType 'hive' to hive_db", - "action": "SET_SERVICE_TYPE", - "typeName": "hive_db", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "serviceType": "hive" - }, - { - "id": "TYPEDEF_PATCH_1000_053", - "description": "Set serviceType 'hive' to hive_column", - "action": "SET_SERVICE_TYPE", - "typeName": "hive_column", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "serviceType": "hive" - }, - { - "id": "TYPEDEF_PATCH_1000_054", - "description": "Set serviceType 'hive' to hive_column_lineage", - "action": "SET_SERVICE_TYPE", - "typeName": "hive_column_lineage", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hive" - }, - { - "id": "TYPEDEF_PATCH_1000_055", - "description": "Set serviceType 'hive' to hive_table_db", - "action": "SET_SERVICE_TYPE", - "typeName": "hive_table_db", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hive" - }, - { - "id": "TYPEDEF_PATCH_1000_056", - "description": "Set serviceType 'hive' to hive_table_columns", - "action": "SET_SERVICE_TYPE", - "typeName": "hive_table_columns", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hive" - }, - { - "id": "TYPEDEF_PATCH_1000_057", - "description": "Set serviceType 'hive' to hive_table_partitionkeys", - "action": "SET_SERVICE_TYPE", - "typeName": "hive_table_partitionkeys", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hive" - }, - { - "id": "TYPEDEF_PATCH_1000_058", - "description": "Set serviceType 'hive' to hive_table_storagedesc", - "action": "SET_SERVICE_TYPE", - "typeName": "hive_table_storagedesc", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hive" - }, - { - "id": "TYPEDEF_PATCH_1000_059", - "description": "Set serviceType 'hive' to hive_process_column_lineage", - "action": "SET_SERVICE_TYPE", - "typeName": "hive_process_column_lineage", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hive" - }, - { - "id": "TYPEDEF_PATCH_1000_060", - "description": "Set serviceType 'sqoop' to sqoop_process", - "action": "SET_SERVICE_TYPE", - "typeName": "sqoop_process", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "sqoop" - }, - { - "id": "TYPEDEF_PATCH_1000_061", - "description": "Set serviceType 'sqoop' to sqoop_dbdatastore", - "action": "SET_SERVICE_TYPE", - "typeName": "sqoop_dbdatastore", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "sqoop" - }, - { - "id": "TYPEDEF_PATCH_1000_062", - "description": "Set serviceType 'falcon' to falcon_feed_replication", - "action": "SET_SERVICE_TYPE", - "typeName": "falcon_feed_replication", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "falcon" - }, - { - "id": "TYPEDEF_PATCH_1000_063", - "description": "Set serviceType 'falcon' to falcon_cluster", - "action": "SET_SERVICE_TYPE", - "typeName": "falcon_cluster", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "falcon" - }, - { - "id": "TYPEDEF_PATCH_1000_064", - "description": "Set serviceType 'falcon' to falcon_feed", - "action": "SET_SERVICE_TYPE", - "typeName": "falcon_feed", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "falcon" - }, - { - "id": "TYPEDEF_PATCH_1000_065", - "description": "Set serviceType 'falcon' to falcon_process", - "action": "SET_SERVICE_TYPE", - "typeName": "falcon_process", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "falcon" - }, - { - "id": "TYPEDEF_PATCH_1000_066", - "description": "Set serviceType 'falcon' to falcon_feed_creation", - "action": "SET_SERVICE_TYPE", - "typeName": "falcon_feed_creation", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "falcon" - }, - { - "id": "TYPEDEF_PATCH_1000_067", - "description": "Set serviceType 'falcon' to falcon_feed_cluster", - "action": "SET_SERVICE_TYPE", - "typeName": "falcon_feed_cluster", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "falcon" - }, - { - "id": "TYPEDEF_PATCH_1000_068", - "description": "Set serviceType 'falcon' to falcon_cluster_process", - "action": "SET_SERVICE_TYPE", - "typeName": "falcon_cluster_process", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "falcon" - }, - { - "id": "TYPEDEF_PATCH_1000_069", - "description": "Set serviceType 'falcon' to falcon_cluster_feed_creation", - "action": "SET_SERVICE_TYPE", - "typeName": "falcon_cluster_feed_creation", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "falcon" - }, - { - "id": "TYPEDEF_PATCH_1000_070", - "description": "Set serviceType 'hbase' to hbase_namespace", - "action": "SET_SERVICE_TYPE", - "typeName": "hbase_namespace", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hbase" - }, - { - "id": "TYPEDEF_PATCH_1000_071", - "description": "Set serviceType 'hbase' to hbase_table", - "action": "SET_SERVICE_TYPE", - "typeName": "hbase_table", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "serviceType": "hbase" - }, - { - "id": "TYPEDEF_PATCH_1000_072", - "description": "Set serviceType 'hbase' to hbase_column_family", - "action": "SET_SERVICE_TYPE", - "typeName": "hbase_column_family", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "serviceType": "hbase" - }, - { - "id": "TYPEDEF_PATCH_1000_073", - "description": "Set serviceType 'hbase' to hbase_column", - "action": "SET_SERVICE_TYPE", - "typeName": "hbase_column", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hbase" - }, - { - "id": "TYPEDEF_PATCH_1000_074", - "description": "Set serviceType 'hbase' to hbase_table_namespace", - "action": "SET_SERVICE_TYPE", - "typeName": "hbase_table_namespace", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hbase" - }, - { - "id": "TYPEDEF_PATCH_1000_075", - "description": "Set serviceType 'hbase' to hbase_table_column_families", - "action": "SET_SERVICE_TYPE", - "typeName": "hbase_table_column_families", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hbase" - }, - { - "id": "TYPEDEF_PATCH_1000_076", - "description": "Set serviceType 'hbase' to hbase_column_family_columns", - "action": "SET_SERVICE_TYPE", - "typeName": "hbase_column_family_columns", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "hbase" - }, - { - "id": "TYPEDEF_PATCH_1000_077", - "description": "Set serviceType 'avro' to avro_type", - "action": "SET_SERVICE_TYPE", - "typeName": "avro_type", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "avro" - }, - { - "id": "TYPEDEF_PATCH_1000_078", - "description": "Set serviceType 'avro' to avro_field", - "action": "SET_SERVICE_TYPE", - "typeName": "avro_field", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "avro" - }, - { - "id": "TYPEDEF_PATCH_1000_079", - "description": "Set serviceType 'avro' to avro_record", - "action": "SET_SERVICE_TYPE", - "typeName": "avro_record", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "avro" - }, - { - "id": "TYPEDEF_PATCH_1000_080", - "description": "Set serviceType 'avro' to avro_schema", - "action": "SET_SERVICE_TYPE", - "typeName": "avro_schema", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "avro" - }, - { - "id": "TYPEDEF_PATCH_1000_081", - "description": "Set serviceType 'avro' to avro_primitive", - "action": "SET_SERVICE_TYPE", - "typeName": "avro_primitive", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "avro" - }, - { - "id": "TYPEDEF_PATCH_1000_082", - "description": "Set serviceType 'avro' to avro_fixed", - "action": "SET_SERVICE_TYPE", - "typeName": "avro_fixed", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "avro" - }, - { - "id": "TYPEDEF_PATCH_1000_083", - "description": "Set serviceType 'avro' to avro_enum", - "action": "SET_SERVICE_TYPE", - "typeName": "avro_enum", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "avro" - }, - { - "id": "TYPEDEF_PATCH_1000_084", - "description": "Set serviceType 'avro' to avro_collection", - "action": "SET_SERVICE_TYPE", - "typeName": "avro_collection", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "avro" - }, - { - "id": "TYPEDEF_PATCH_1000_085", - "description": "Set serviceType 'avro' to avro_schema_associatedEntities", - "action": "SET_SERVICE_TYPE", - "typeName": "avro_schema_associatedEntities", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "avro" - }, - { - "id": "TYPEDEF_PATCH_1000_086", - "description": "Set serviceType 'avro' to avro_record_fields", - "action": "SET_SERVICE_TYPE", - "typeName": "avro_record_fields", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "avro" - }, - { - "id": "TYPEDEF_PATCH_1000_087", - "description": "Set serviceType 'avro' to avro_field_types", - "action": "SET_SERVICE_TYPE", - "typeName": "avro_field_types", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "avro" - }, - { - "id": "TYPEDEF_PATCH_1000_088", - "description": "Set serviceType 'kafka' to kafka_topic", - "action": "SET_SERVICE_TYPE", - "typeName": "kafka_topic", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "serviceType": "kafka" - }, - { - "id": "TYPEDEF_PATCH_1000_089", - "description": "Set serviceType 'kafka' to jms_topic", - "action": "SET_SERVICE_TYPE", - "typeName": "jms_topic", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "kafka" - }, - { - "id": "TYPEDEF_PATCH_1000_090", - "description": "Set serviceType 'kafka' to kafka_topic_avroSchema", - "action": "SET_SERVICE_TYPE", - "typeName": "kafka_topic_avroSchema", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "kafka" - }, - { - "id": "TYPEDEF_PATCH_1000_091", - "description": "Set serviceType 'storm' to storm_topology", - "action": "SET_SERVICE_TYPE", - "typeName": "storm_topology", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "storm" - }, - { - "id": "TYPEDEF_PATCH_1000_092", - "description": "Set serviceType 'storm' to storm_node", - "action": "SET_SERVICE_TYPE", - "typeName": "storm_node", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "storm" - }, - { - "id": "TYPEDEF_PATCH_1000_093", - "description": "Set serviceType 'storm' to storm_spout", - "action": "SET_SERVICE_TYPE", - "typeName": "storm_spout", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "storm" - }, - { - "id": "TYPEDEF_PATCH_1000_094", - "description": "Set serviceType 'storm' to storm_bolt", - "action": "SET_SERVICE_TYPE", - "typeName": "storm_bolt", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "storm" - }, - { - "id": "TYPEDEF_PATCH_1000_095", - "description": "Set serviceType 'storm' to storm_topology_nodes", - "action": "SET_SERVICE_TYPE", - "typeName": "storm_topology_nodes", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "storm" - } - ] -} \ No newline at end of file diff --git a/addons/models/1000-Hadoop/patches/008-remove-hive-legacy-attributes.json b/addons/models/1000-Hadoop/patches/008-remove-hive-legacy-attributes.json deleted file mode 100644 index 4544ee3ac81..00000000000 --- a/addons/models/1000-Hadoop/patches/008-remove-hive-legacy-attributes.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_096", - "description": "Remove legacy reference attribute 'db' from hive_table", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "hive_table_db", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__hive_table.db", - "relationshipCategory": "AGGREGATION" - } - }, - { - "id": "TYPEDEF_PATCH_1000_097", - "description": "Remove legacy reference attribute 'columns' from hive_table", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "hive_table_columns", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__hive_table.columns" - } - }, - { - "id": "TYPEDEF_PATCH_1000_098", - "description": "Remove legacy reference attribute 'partitionkeys' from hive_table", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "hive_table_partitionkeys", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__hive_table.partitionkeys" - } - }, - { - "id": "TYPEDEF_PATCH_1000_099", - "description": "Remove legacy reference attribute 'sd' from hive_table", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "hive_table_storagedesc", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__hive_table.sd" - } - }, - { - "id": "TYPEDEF_PATCH_1000_100", - "description": "Remove legacy reference attribute 'query' from hive_column_lineage", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "hive_process_column_lineage", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__hive_column_lineage.query", - "swapEnds": "true" - } - } - ] -} diff --git a/addons/models/1000-Hadoop/patches/009-add_searchweight.json b/addons/models/1000-Hadoop/patches/009-add_searchweight.json deleted file mode 100644 index bfb471a7270..00000000000 --- a/addons/models/1000-Hadoop/patches/009-add_searchweight.json +++ /dev/null @@ -1,412 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_101", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "hive_process", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "userName", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_1000_102", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "hive_process", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "queryText", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_1000_103", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "hive_process", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "clusterName", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_1000_104", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "hive_table", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "comment", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_1000_105", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "hive_table", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "viewOriginalText", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_1000_106", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "hive_table", - "applyToVersion": "1.4", - "updateToVersion": "1.5", - "attributeName": "viewExpandedText", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_1000_107", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "hive_storagedesc", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "location", - "params": { - "searchWeight": 5 - } - }, { - "id": "TYPEDEF_PATCH_1000_108", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "hive_db", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "location", - "params": { - "searchWeight": 5 - } - }, { - "id": "TYPEDEF_PATCH_1000_109", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "hive_db", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "clusterName", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_1000_110", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "hive_column", - "applyToVersion": "1.4", - "updateToVersion": "1.5", - "attributeName": "comment", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_1000_111", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "sqoop_process", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "userName", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_1000_112", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "falcon_cluster", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "colo", - "params": { - "searchWeight": 5 - } - }, { - "id": "TYPEDEF_PATCH_1000_113", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "falcon_feed", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "groups", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_1000_114", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "falcon_process", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "pipelines", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_1000_115", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "hbase_namespace", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "clusterName", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_1000_116", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "hbase_table", - "applyToVersion": "1.4", - "updateToVersion": "1.5", - "attributeName": "uri", - "params": { - "searchWeight": 5 - } - }, { - "id": "TYPEDEF_PATCH_1000_117", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "avro_field", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "doc", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_1000_118", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "avro_record", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "doc", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_1000_119", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "avro_record", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "avro_notation", - "params": { - "searchWeight": 5 - } - }, { - "id": "TYPEDEF_PATCH_1000_120", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "avro_record", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "avroClass", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_1000_121", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "avro_schema", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "namespace", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_1000_122", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "kafka_topic", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "topic", - "params": { - "searchWeight": 10 - } - }, { - "id": "TYPEDEF_PATCH_1000_123", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "kafka_topic", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "uri", - "params": { - "searchWeight": 5 - } - }, { - "id": "TYPEDEF_PATCH_1000_124", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "kafka_topic", - "applyToVersion": "1.4", - "updateToVersion": "1.5", - "attributeName": "contactInfo", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_1000_125", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "kafka_topic", - "applyToVersion": "1.5", - "updateToVersion": "1.6", - "attributeName": "type", - "params": { - "searchWeight": 10 - } - }, { - "id": "TYPEDEF_PATCH_1000_126", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "kafka_topic", - "applyToVersion": "1.6", - "updateToVersion": "1.7", - "attributeName": "keyClassname", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_1000_127", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "jms_topic", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "topic", - "params": { - "searchWeight": 10 - } - } , { - "id": "TYPEDEF_PATCH_1000_128", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "jms_topic", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "uri", - "params": { - "searchWeight": 10 - } - }, { - "id": "TYPEDEF_PATCH_1000_129", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "storm_topology", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "clusterName", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_1000_130", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "storm_node", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "name", - "params": { - "searchWeight": 10 - } - }, { - "id": "TYPEDEF_PATCH_1000_131", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "storm_node", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "description", - "params": { - "searchWeight": 10 - } - }, { - "id": "TYPEDEF_PATCH_1000_132", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "storm_node", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "driverClass", - "params": { - "searchWeight": 8 - } - } , { - "id": "TYPEDEF_PATCH_1000_133", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "fs_path", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "path", - "params": { - "searchWeight": 5 - } - } , { - "id": "TYPEDEF_PATCH_1000_134", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "fs_path", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "group", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_1000_135", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "fs_path", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "posixPermissions", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_1000_136", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "hdfs_path", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "clusterName", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_1000_137", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "hdfs_path", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "nameServiceId", - "params": { - "searchWeight": 10 - } - } - ] -} diff --git a/addons/models/1000-Hadoop/patches/010-hbase_remove_legacy_attributes.json b/addons/models/1000-Hadoop/patches/010-hbase_remove_legacy_attributes.json deleted file mode 100644 index 1e618e55ad6..00000000000 --- a/addons/models/1000-Hadoop/patches/010-hbase_remove_legacy_attributes.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_010_001", - "description": "Remove legacy reference attribute 'namespace' from hbase_table", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "hbase_table_namespace", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__hbase_table.namespace", - "relationshipCategory": "COMPOSITION" - } - }, - { - "id": "TYPEDEF_PATCH_1000_010_002", - "description": "Remove legacy reference attribute 'column_families' from hbase_table", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "hbase_table_column_families", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__hbase_table.column_families" - } - }, - { - "id": "TYPEDEF_PATCH_1000_010_003", - "description": "Remove legacy reference attribute 'columns' from hbase_column_family", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "hbase_column_family_columns", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__hbase_column_family.columns", - "relationshipCategory": "COMPOSITION" - } - } - ] -} diff --git a/addons/models/1000-Hadoop/patches/011-falcon_remove_legacy_atrributes.json b/addons/models/1000-Hadoop/patches/011-falcon_remove_legacy_atrributes.json deleted file mode 100644 index 07b8b8f088c..00000000000 --- a/addons/models/1000-Hadoop/patches/011-falcon_remove_legacy_atrributes.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_011_001", - "description": "Remove legacy reference attribute 'stored-in' from falcon_feed", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "falcon_feed_cluster", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__falcon_feed.stored-in", - "relationshipCategory": "COMPOSITION" - } - }, - { - "id": "TYPEDEF_PATCH_1000_011_002", - "description": "Remove legacy reference attribute 'runs-on' from falcon_process", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "falcon_cluster_process", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__falcon_cluster.processes" - } - }, - { - "id": "TYPEDEF_PATCH_1000_011_003", - "description": "Remove legacy reference attribute 'stored-in' from falcon_feed_creation", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "falcon_cluster_feed_creation", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__falcon_cluster.feedCreations" - } - } - ] -} \ No newline at end of file diff --git a/addons/models/1000-Hadoop/patches/012-avro_remove_legacy_attributs.json b/addons/models/1000-Hadoop/patches/012-avro_remove_legacy_attributs.json deleted file mode 100644 index 2224376c353..00000000000 --- a/addons/models/1000-Hadoop/patches/012-avro_remove_legacy_attributs.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_012_001", - "description": "Remove legacy reference attribute 'associatedEntities' from avro_schema", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "avro_schema_associatedEntities", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__avro_schema.associatedEntities" - } - }, - { - "id": "TYPEDEF_PATCH_1000_012_002", - "description": "Remove legacy reference attribute 'fields' from avro_record", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "avro_record_fields", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__avro_record.fields" - } - }, - { - "id": "TYPEDEF_PATCH_1000_012_003", - "description": "Remove legacy reference attribute 'type' from avro_field", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "avro_field_types", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__avro_field.type" - } - } - ] -} \ No newline at end of file diff --git a/addons/models/1000-Hadoop/patches/013-kafka_remove_legacy_attributes.json b/addons/models/1000-Hadoop/patches/013-kafka_remove_legacy_attributes.json deleted file mode 100644 index 694fc170a41..00000000000 --- a/addons/models/1000-Hadoop/patches/013-kafka_remove_legacy_attributes.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "patches": [ - { - "id": "YPEDEF_PATCH_1000_013_001", - "description": "Remove legacy reference attribute 'avroSchema' from kafka_topic", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "kafka_topic_avroSchema", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__kafka_topic.avroSchema", - "relationshipCategory": "ASSOCIATION" - } - } - ] -} \ No newline at end of file diff --git a/addons/models/1000-Hadoop/patches/014-storm_remove_legacy_attributes.json b/addons/models/1000-Hadoop/patches/014-storm_remove_legacy_attributes.json deleted file mode 100644 index 892554d043f..00000000000 --- a/addons/models/1000-Hadoop/patches/014-storm_remove_legacy_attributes.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_014_001", - "description": "Remove legacy reference attribute 'nodes' from storm_topology", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "storm_topology_nodes", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__storm_topology.nodes" - } - } - ] -} \ No newline at end of file diff --git a/addons/models/1000-Hadoop/patches/015-spark_process_add_query_text_attribute.json b/addons/models/1000-Hadoop/patches/015-spark_process_add_query_text_attribute.json deleted file mode 100644 index ff41ed7ae20..00000000000 --- a/addons/models/1000-Hadoop/patches/015-spark_process_add_query_text_attribute.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_015_001", - "description": "Add 'queryText' attribute to spark_process", - "action": "ADD_ATTRIBUTE", - "typeName": "spark_process", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "params": null, - "attributeDefs": [ - { - "name": "queryText", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - } - ] -} diff --git a/addons/models/1000-Hadoop/patches/016-hive_process_execution_add_display_text_option.json b/addons/models/1000-Hadoop/patches/016-hive_process_execution_add_display_text_option.json deleted file mode 100644 index cb15b3408e4..00000000000 --- a/addons/models/1000-Hadoop/patches/016-hive_process_execution_add_display_text_option.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_016_001", - "description": "Add 'displayTextAttribute' typeDefOptions to hive_process_execution", - "action": "UPDATE_TYPEDEF_OPTIONS", - "typeName": "hive_process_execution", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "typeDefOptions": { - "displayTextAttribute": "queryText" - } - } - ] -} diff --git a/addons/models/1000-Hadoop/patches/017-hive_db_add_managed_location.json b/addons/models/1000-Hadoop/patches/017-hive_db_add_managed_location.json deleted file mode 100644 index e9bd153f7b2..00000000000 --- a/addons/models/1000-Hadoop/patches/017-hive_db_add_managed_location.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_017_001", - "description": "Add 'managedLocation' attribute to hive_db", - "action": "ADD_ATTRIBUTE", - "typeName": "hive_db", - "applyToVersion": "1.4", - "updateToVersion": "1.5", - "params": null, - "attributeDefs": [ - { - "name": "managedLocation", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - } - ] -} diff --git a/addons/models/1000-Hadoop/patches/018-fs_path_add_supertypes.json b/addons/models/1000-Hadoop/patches/018-fs_path_add_supertypes.json deleted file mode 100644 index 89235048ff1..00000000000 --- a/addons/models/1000-Hadoop/patches/018-fs_path_add_supertypes.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_018_001", - "description": "Add superTypes for fs_path", - "action": "ADD_SUPER_TYPES", - "typeName": "fs_path", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "params": null, - "superTypes": [ - "Path" - ] - } - ] -} diff --git a/addons/models/1000-Hadoop/patches/018-kafka_topic_add_rf_attribute.json b/addons/models/1000-Hadoop/patches/018-kafka_topic_add_rf_attribute.json deleted file mode 100644 index cc74bad55d5..00000000000 --- a/addons/models/1000-Hadoop/patches/018-kafka_topic_add_rf_attribute.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_018_001", - "description": "Add 'replicationFactor' attribute to kafka_topic", - "action": "ADD_ATTRIBUTE", - "typeName": "kafka_topic", - "applyToVersion": "1.7", - "updateToVersion": "1.8", - "params": null, - "attributeDefs": [ - { - "name": "replicationFactor", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - } - ] -} diff --git a/addons/models/1000-Hadoop/patches/019-kafka_producer_lineage_add_options.json b/addons/models/1000-Hadoop/patches/019-kafka_producer_lineage_add_options.json deleted file mode 100644 index bff4bd5d30c..00000000000 --- a/addons/models/1000-Hadoop/patches/019-kafka_producer_lineage_add_options.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_1000_019_001", - "description": "Add 'appendRelationshipsOnPartialUpdate' typeDefOptions to kafka_producer_lineage", - "action": "UPDATE_TYPEDEF_OPTIONS", - "typeName": "kafka_producer_lineage", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "typeDefOptions": { - "appendRelationshipsOnPartialUpdate": "[\"outputs\"]" - } - } - ] -} \ No newline at end of file diff --git a/addons/models/2000-RDBMS/2010-rdbms_model.json b/addons/models/2000-RDBMS/2010-rdbms_model.json deleted file mode 100644 index 3d784bf4af1..00000000000 --- a/addons/models/2000-RDBMS/2010-rdbms_model.json +++ /dev/null @@ -1,458 +0,0 @@ -{ - "enumDefs": [], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ - { - "name": "rdbms_instance", - "description": "Instance that the rdbms server is running on", - "superTypes": ["DataSet"], - "serviceType": "rdbms", - "typeVersion": "1.1", - "attributeDefs": [ - { - "name": "rdbms_type", - "typeName": "string", - "isOptional": false, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": true - }, - { - "name": "platform", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": true - }, - { - "name": "cloudOrOnPrem", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "hostname", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "port", - "typeName": "int", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "protocol", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "contact_info", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "comment", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - } - ] - }, - { - "name": "rdbms_db", - "description": "a database (schema) in an rdbms", - "superTypes": ["DataSet"], - "serviceType": "rdbms", - "typeVersion": "1.1", - "attributeDefs": [ - { - "name": "prodOrOther", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": true - }, - { - "name": "contact_info", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - } - ] - }, - { - "name": "rdbms_table", - "description": "a table in an rdbms database (schema)", - "superTypes": ["DataSet"], - "serviceType": "rdbms", - "typeVersion": "1.2", - "options": { - "schemaElementsAttribute": "columns" - }, - "attributeDefs": [ - { - "name": "name_path", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "createTime", - "typeName": "date", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "comment", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "type", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "contact_info", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 1, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": false - } - ] - }, - { - "name": "rdbms_column", - "description": "a column in an rdbms table", - "superTypes": ["DataSet"], - "serviceType": "rdbms", - "typeVersion": "1.2", - "options": { - "schemaAttributes": "[\"name\", \"description\", \"owner\", \"data_type\", \"comment\", \" isPrimaryKey\", \" isNullable\"]" - }, - "attributeDefs": [ - { - "name": "data_type", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": true - }, - { - "name": "length", - "typeName": "int", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "default_value", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "comment", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "isNullable", - "typeName": "boolean", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "isPrimaryKey", - "typeName": "boolean", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - } - ] - }, - { - "name": "rdbms_index", - "description": "An index on an RDBMS table", - "superTypes": ["DataSet"], - "serviceType": "rdbms", - "typeVersion": "1.1", - "attributeDefs": [ - { - "name": "index_type", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "isUnique", - "typeName": "boolean", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - }, - { - "name": "comment", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "isUnique": false, - "isIndexable": false - } - ] - }, - { - "name": "rdbms_foreign_key", - "description": null, - "superTypes": ["DataSet"], - "serviceType": "rdbms", - "typeVersion": "1.1", - "attributeDefs": [ - ] - } - ], - "relationshipDefs": [ - { - "name": "rdbms_instance_databases", - "serviceType": "rdbms", - "typeVersion": "1.2", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__rdbms_instance.databases", - "endDef1": { - "type": "rdbms_instance", - "name": "databases", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "rdbms_db", - "name": "instance", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "propagateTags": "NONE" - }, - { - "name": "rdbms_db_tables", - "serviceType": "rdbms", - "typeVersion": "1.2", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__rdbms_db.tables", - "endDef1": { - "type": "rdbms_db", - "name": "tables", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "rdbms_table", - "name": "db", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "propagateTags": "NONE" - }, - { - "name": "rdbms_table_columns", - "serviceType": "rdbms", - "typeVersion": "1.2", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__rdbms_table.columns", - "endDef1": { - "type": "rdbms_table", - "name": "columns", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "rdbms_column", - "name": "table", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "propagateTags": "NONE" - }, - { - "name": "rdbms_table_indexes", - "serviceType": "rdbms", - "typeVersion": "1.2", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__rdbms_table.indexes", - "endDef1": { - "type": "rdbms_table", - "name": "indexes", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "rdbms_index", - "name": "table", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "propagateTags": "NONE" - }, - { - "name": "rdbms_index_columns", - "serviceType": "rdbms", - "typeVersion": "1.2", - "relationshipCategory": "ASSOCIATION", - "relationshipLabel": "__rdbms_index.columns", - "endDef1": { - "type": "rdbms_index", - "name": "columns", - "isContainer": false, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "rdbms_column", - "name": "indexes", - "isContainer": false, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "propagateTags": "NONE" - }, - { - "name": "rdbms_table_foreign_key", - "serviceType": "rdbms", - "typeVersion": "1.2", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__rdbms_table.foreign_keys", - "endDef1": { - "type": "rdbms_table", - "name": "foreign_keys", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "rdbms_foreign_key", - "name": "table", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "propagateTags": "NONE" - }, - { - "name": "rdbms_foreign_key_key_columns", - "serviceType": "rdbms", - "typeVersion": "1.2", - "relationshipCategory": "ASSOCIATION", - "relationshipLabel": "__rdbms_foreign_key.key_columns", - "endDef1": { - "type": "rdbms_foreign_key", - "name": "key_columns", - "isContainer": false, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "rdbms_column", - "name": "key_column_references", - "isContainer": false, - "cardinality": "SET" - }, - "propagateTags": "NONE" - }, - { - "name": "rdbms_foreign_key_table_references", - "serviceType": "rdbms", - "typeVersion": "1.2", - "relationshipCategory": "ASSOCIATION", - "relationshipLabel": "__rdbms_foreign_key.references_table", - "endDef1": { - "type": "rdbms_foreign_key", - "name": "references_table", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "rdbms_table", - "name": "foreign_key_references", - "isContainer": false, - "cardinality": "SET" - }, - "propagateTags": "NONE" - }, - { - "name": "rdbms_foreign_key_column_references", - "serviceType": "rdbms", - "typeVersion": "1.2", - "relationshipCategory": "ASSOCIATION", - "relationshipLabel": "__rdbms_foreign_key.references_columns", - "endDef1": { - "type": "rdbms_foreign_key", - "name": "references_columns", - "isContainer": false, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "rdbms_column", - "name": "foreign_key_references", - "isContainer": false, - "cardinality": "SET" - }, - "propagateTags": "NONE" - } - ] -} diff --git a/addons/models/2000-RDBMS/patches/001-rdbms_column_table_add_options.json b/addons/models/2000-RDBMS/patches/001-rdbms_column_table_add_options.json deleted file mode 100644 index f37d6da560a..00000000000 --- a/addons/models/2000-RDBMS/patches/001-rdbms_column_table_add_options.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_2000_101", - "description": "Add 'schemaAttributes' typeDefOptions to rdbms_column", - "action": "UPDATE_TYPEDEF_OPTIONS", - "typeName": "rdbms_column", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "typeDefOptions": { - "schemaAttributes": "[\"name\", \"description\", \"owner\", \"data_type\", \"comment\", \" isPrimaryKey\", \" isNullable\"]" - } - }, - { - "id": "TYPEDEF_PATCH_2000_102", - "description": "Add 'schemaElementsAttribute' typeDefOptions to rdbms_table", - "action": "UPDATE_TYPEDEF_OPTIONS", - "typeName": "rdbms_table", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "typeDefOptions": { - "schemaElementsAttribute": "columns" - } - } - ] -} \ No newline at end of file diff --git a/addons/models/2000-RDBMS/patches/002-rdbms_model_add_service_type.json b/addons/models/2000-RDBMS/patches/002-rdbms_model_add_service_type.json deleted file mode 100644 index 2ef1f28b5e1..00000000000 --- a/addons/models/2000-RDBMS/patches/002-rdbms_model_add_service_type.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_2000_103", - "description": "Set serviceType 'rdbms' to rdbms_instance", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_instance", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "serviceType": "rdbms" - }, - { - "id": "TYPEDEF_PATCH_2000_104", - "description": "Set serviceType 'rdbms' to rdbms_db", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_db", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "serviceType": "rdbms" - }, - { - "id": "TYPEDEF_PATCH_2000_105", - "description": "Set serviceType 'rdbms' to rdbms_table", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_table", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "serviceType": "rdbms" - }, - { - "id": "TYPEDEF_PATCH_2000_106", - "description": "Set serviceType 'rdbms' to rdbms_column", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_column", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "serviceType": "rdbms" - }, - { - "id": "TYPEDEF_PATCH_2000_107", - "description": "Set serviceType 'rdbms' to rdbms_index", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_index", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "serviceType": "rdbms" - }, - { - "id": "TYPEDEF_PATCH_2000_108", - "description": "Set serviceType 'rdbms' to rdbms_foreign_key", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_foreign_key", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "serviceType": "rdbms" - }, - { - "id": "TYPEDEF_PATCH_2000_109", - "description": "Set serviceType 'rdbms' to rdbms_instance_databases", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_instance_databases", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "rdbms" - }, - { - "id": "TYPEDEF_PATCH_2000_110", - "description": "Set serviceType 'rdbms' to rdbms_db_tables", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_db_tables", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "rdbms" - }, - { - "id": "TYPEDEF_PATCH_2000_111", - "description": "Set serviceType 'rdbms' to rdbms_table_columns", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_table_columns", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "rdbms" - }, - { - "id": "TYPEDEF_PATCH_2000_112", - "description": "Set serviceType 'rdbms' to rdbms_table_indexes", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_table_indexes", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "rdbms" - }, - { - "id": "TYPEDEF_PATCH_2000_113", - "description": "Set serviceType 'rdbms' to rdbms_index_columns", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_index_columns", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "rdbms" - }, - { - "id": "TYPEDEF_PATCH_2000_114", - "description": "Set serviceType 'rdbms' to rdbms_table_foreign_key", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_table_foreign_key", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "rdbms" - }, - { - "id": "TYPEDEF_PATCH_2000_115", - "description": "Set serviceType 'rdbms' to rdbms_foreign_key_key_columns", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_foreign_key_key_columns", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "rdbms" - }, - { - "id": "TYPEDEF_PATCH_2000_116", - "description": "Set serviceType 'rdbms' to rdbms_foreign_key_table_references", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_foreign_key_table_references", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "rdbms" - }, - { - "id": "TYPEDEF_PATCH_2000_117", - "description": "Set serviceType 'rdbms' to rdbms_foreign_key_column_references", - "action": "SET_SERVICE_TYPE", - "typeName": "rdbms_foreign_key_column_references", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "rdbms" - } - ] -} \ No newline at end of file diff --git a/addons/models/2000-RDBMS/patches/003-remove-rdbms-legacy-attributes.json b/addons/models/2000-RDBMS/patches/003-remove-rdbms-legacy-attributes.json deleted file mode 100644 index 990d4e902f2..00000000000 --- a/addons/models/2000-RDBMS/patches/003-remove-rdbms-legacy-attributes.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_2000_118", - "description": "Remove legacy reference attribute 'databases' from rdbms_instance", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "rdbms_instance_databases", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__rdbms_instance.databases", - "relationshipCategory": "COMPOSITION" - } - }, - { - "id": "TYPEDEF_PATCH_2000_119", - "description": "Remove legacy reference attribute 'tables' from rdbms_db", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "rdbms_db_tables", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__rdbms_db.tables", - "relationshipCategory": "COMPOSITION" - } - }, - { - "id": "TYPEDEF_PATCH_2000_120", - "description": "Remove legacy reference attribute 'columns' from rdbms_table", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "rdbms_table_columns", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__rdbms_table.columns", - "relationshipCategory": "COMPOSITION" - } - }, - { - "id": "TYPEDEF_PATCH_2000_121", - "description": "Remove legacy reference attribute 'indexes' from rdbms_table", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "rdbms_table_indexes", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__rdbms_table.indexes", - "relationshipCategory": "COMPOSITION" - } - }, - { - "id": "TYPEDEF_PATCH_2000_122", - "description": "Remove legacy reference attribute 'foreign_keys' from rdbms_table", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "rdbms_table_foreign_key", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__rdbms_table.foreign_keys", - "relationshipCategory": "COMPOSITION" - } - }, - { - "id": "TYPEDEF_PATCH_2000_123", - "description": "Remove legacy reference attribute 'columns' from rdbms_index", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "rdbms_index_columns", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__rdbms_index.columns" - } - }, - { - "id": "TYPEDEF_PATCH_2000_124", - "description": "Remove legacy reference attribute 'key_columns' from rdbms_foreign_key", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "rdbms_foreign_key_key_columns", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__rdbms_foreign_key.key_columns" - } - }, - { - "id": "TYPEDEF_PATCH_2000_125", - "description": "Remove legacy reference attribute 'references_table' from rdbms_foreign_key", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "rdbms_foreign_key_table_references", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__rdbms_foreign_key.references_table" - } - }, - { - "id": "TYPEDEF_PATCH_2000_126", - "description": "Remove legacy reference attribute 'references_columns' from rdbms_foreign_key", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "rdbms_foreign_key_column_references", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__rdbms_foreign_key.references_columns" - } - } - ] -} diff --git a/addons/models/2000-RDBMS/patches/004-add_searchweight.json b/addons/models/2000-RDBMS/patches/004-add_searchweight.json deleted file mode 100644 index bf060d85a67..00000000000 --- a/addons/models/2000-RDBMS/patches/004-add_searchweight.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_2000_127", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "rdbms_instance", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "rdbms_type", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_2000_128", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "rdbms_instance", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "platform", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_2000_129", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "rdbms_instance", - "applyToVersion": "1.4", - "updateToVersion": "1.5", - "attributeName": "contact_info", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_2000_130", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "rdbms_instance", - "applyToVersion": "1.5", - "updateToVersion": "1.6", - "attributeName": "hostname", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_2000_131", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "rdbms_instance", - "applyToVersion": "1.6", - "updateToVersion": "1.7", - "attributeName": "comment", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_2000_132", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "rdbms_db", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "contact_info", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_2000_133", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "rdbms_table", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "name_path", - "params": { - "searchWeight": 5 - } - }, { - "id": "TYPEDEF_PATCH_2000_134", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "rdbms_table", - "applyToVersion": "1.4", - "updateToVersion": "1.5", - "attributeName": "comment", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_2000_135", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "rdbms_table", - "applyToVersion": "1.5", - "updateToVersion": "1.6", - "attributeName": "contact_info", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_2000_136", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "rdbms_column", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "comment", - "params": { - "searchWeight": 9 - } - }, { - "id": "TYPEDEF_PATCH_2000_137", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "rdbms_index", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "comment", - "params": { - "searchWeight": 9 - } - } - ] -} diff --git a/addons/models/3000-Cloud/3010-aws_common_typedefs.json b/addons/models/3000-Cloud/3010-aws_common_typedefs.json deleted file mode 100644 index b7a92c3123f..00000000000 --- a/addons/models/3000-Cloud/3010-aws_common_typedefs.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "enumDefs": [], - "structDefs": [ - { - "name": "aws_tag", - "description": "Atlas Type representing a tag/value pair associated with an AWS object, eg S3 bucket", - "serviceType": "aws", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "key", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "value", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - } - ] - }, - { - "name": "aws_cloud_watch_metric", - "description": "Atlas Type representing a metric provided by AWS Cloud Watch", - "serviceType": "aws", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "metricName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "scope", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - } - ] - } - ], - "classificationDefs": [], - "entityDefs": [] -} diff --git a/addons/models/3000-Cloud/3020-aws_s3_typedefs.json b/addons/models/3000-Cloud/3020-aws_s3_typedefs.json deleted file mode 100644 index 5275c56b44b..00000000000 --- a/addons/models/3000-Cloud/3020-aws_s3_typedefs.json +++ /dev/null @@ -1,339 +0,0 @@ -{ - "enumDefs": [], - "structDefs": [ - { - "name": "aws_s3_bucket_lifeCycleRule", - "description": "Atlas Type representing the life cycle rules for S3 object store bucket", - "serviceType": "aws", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "ruleType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "days", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "storageClass", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "aws_s3_access_policy", - "description": "Atlas Type representing an access policy statement on an S3 bucket. Can later be fleshed out to represent the JSON structure of the statement.", - "serviceType": "aws", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "policyString", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - } - ] - } - ], - "classificationDefs": [], - "entityDefs": [ - { - "name": "aws_s3_object", - "description": "Atlas Type representing an Object (file) in an S3 Object Store Bucket", - "superTypes": [ "DataSet" ], - "serviceType": "aws", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "dataType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "compressionType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "awsTags", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "createTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "aws_s3_pseudo_dir", - "description": "Atlas Type representing a Pseudo-Directory (prefix) in an S3 Object Store Bucket", - "superTypes": [ "DataSet","Path" ], - "serviceType": "aws", - "typeVersion": "1.1", - "attributeDefs": [ - { - "name": "objectPrefix", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": true - }, - { - "name": "subdomain", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "subject", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "currentStorageLocation", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "dataType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "awsTags", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "createTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "aws_s3_bucket", - "description": "Atlas Type representing a Bucket in an AWS S3 Object Store", - "superTypes": [ "DataSet" ], - "serviceType": "aws", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "partner", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "domain", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "region", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "s3AccessPolicies", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "isEncrypted", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "encryptionType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "lifeCycleRules", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "awsTags", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "cloudWatchMetrics", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "createtime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - } - ], - "relationshipDefs": [ - { - "name": "aws_s3_bucket_aws_s3_pseudo_dirs", - "serviceType": "aws", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__aws_s3_bucket.pseudoDirectories", - "endDef1": { - "type": "aws_s3_bucket", - "name": "pseudoDirectories", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "aws_s3_pseudo_dir", - "name": "bucket", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "propagateTags": "ONE_TO_TWO" - }, - { - "name": "aws_s3_pseudo_dir_aws_objects", - "serviceType": "aws", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__aws_s3_pseudo_dir.s3Objects", - "endDef1": { - "type": "aws_s3_pseudo_dir", - "name": "s3Objects", - "isContainer": true, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "aws_s3_object", - "name": "pseudoDirectory", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "propagateTags": "ONE_TO_TWO" - }, - { - "name": "aws_s3_object_avro_schema", - "serviceType": "aws", - "typeVersion": "1.0", - "relationshipCategory": "ASSOCIATION", - "relationshipLabel": "__aws_s3_object.avroSchema", - "endDef1": { - "type": "aws_s3_object", - "name": "avroSchema", - "isContainer": false, - "cardinality": "SINGLE", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "avro_schema", - "name": "s3Objects", - "isContainer": false, - "cardinality": "SET" - }, - "propagateTags": "NONE" - }, - { - "name": "aws_s3_pseudo_dir_avro_schema", - "serviceType": "aws", - "typeVersion": "1.0", - "relationshipCategory": "ASSOCIATION", - "relationshipLabel": "__aws_s3_pseudo_dir.avroSchemas", - "endDef1": { - "type": "aws_s3_pseudo_dir", - "name": "avroSchemas", - "isContainer": false, - "cardinality": "SET", - "isLegacyAttribute": true - }, - "endDef2": { - "type": "avro_schema", - "name": "s3PseudoDirs", - "isContainer": false, - "cardinality": "SET" - }, - "propagateTags": "NONE" - } - ] -} \ No newline at end of file diff --git a/addons/models/3000-Cloud/3030-aws_s3_v2_typedefs.json b/addons/models/3000-Cloud/3030-aws_s3_v2_typedefs.json deleted file mode 100644 index 977c06682dc..00000000000 --- a/addons/models/3000-Cloud/3030-aws_s3_v2_typedefs.json +++ /dev/null @@ -1,289 +0,0 @@ -{ - "enumDefs": [], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ - { - "name": "aws_s3_v2_container", - "superTypes": [], - "description": "Atlas Type representing a Container Types in an S3 Object Store", - "serviceType": "aws", - "typeVersion": "1.0", - "attributeDefs": [] - }, - { - "name": "aws_s3_v2_contained", - "superTypes": [], - "description": "Atlas Type representing a Contained Types in an S3 Object Store", - "serviceType": "aws", - "typeVersion": "1.0", - "attributeDefs": [] - }, - { - "name": "aws_s3_v2_base", - "description": "Atlas Type representing a base Type for all AWS S3 V2 Data Types", - "superTypes": [ - "DataSet" - ], - "serviceType": "aws", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "region", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "ownerName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "searchWeight" : 5 - }, - { - "name": "ownerId", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "eTag", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "searchWeight" : 5 - }, - { - "name": "encryption", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "awsTags", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "aws_s3_v2_object", - "description": "Atlas Type representing an Object in an S3 Object Store", - "superTypes": [ - "aws_s3_v2_base", - "aws_s3_v2_contained" - ], - "serviceType": "aws", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "lastModifiedTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "bucketName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "searchWeight" : 5 - }, - { - "name": "size", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true - }, - { - "name": "storageClass", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "searchWeight" : 5 - }, - { - "name": "compressionType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "dataType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "aws_s3_v2_directory", - "description": "Atlas Type representing a directory in an S3 Object Store", - "superTypes": [ - "aws_s3_v2_object", - "aws_s3_v2_container", - "Path" - ], - "serviceType": "aws", - "typeVersion": "1.2", - "attributeDefs": [ - { - "name": "objectPrefix", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "subdomain", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "subject", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "storageLocation", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "aws_s3_v2_bucket", - "description": "Atlas Type representing a Bucket in an AWS S3 Object Store", - "superTypes": [ - "aws_s3_v2_base", - "aws_s3_v2_container" - ], - "serviceType": "aws", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "creationTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "permissions", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "partner", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "searchWeight" : 5 - }, - { - "name": "domain", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "s3AccessPolicies", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "lifeCycleRules", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "cloudWatchMetrics", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "accountId", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "searchWeight" : 10 - } - ] - } - ], - "relationshipDefs": [ - { - "name": "aws_s3_v2_container_contained", - "serviceType": "aws", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "aws_s3_v2_container", - "name": "contained", - "isContainer": true, - "cardinality": "SET" - }, - "endDef2": { - "type": "aws_s3_v2_contained", - "name": "container", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - } - ] -} \ No newline at end of file diff --git a/addons/models/3000-Cloud/3040-azure_adls_typedefs.json b/addons/models/3000-Cloud/3040-azure_adls_typedefs.json deleted file mode 100644 index 77c74949aaf..00000000000 --- a/addons/models/3000-Cloud/3040-azure_adls_typedefs.json +++ /dev/null @@ -1,609 +0,0 @@ -{ - "enumDefs": [ - { - "name": "adls_gen2_performance", - "description": "Performance", - "typeVersion": "1.0", - "serviceType": "azure", - "elementDefs": [ - { - "ordinal": 0, - "value": "Standard" - }, - { - "ordinal": 1, - "value": "Premium" - } - ] - }, - { - "name": "adls_gen2_access_tier", - "description": "Access Tier", - "typeVersion": "1.0", - "serviceType": "azure", - "elementDefs": [ - { - "ordinal": 0, - "value": "Cool" - }, - { - "ordinal": 1, - "value": "Hot" - } - ] - }, - { - "name": "adls_gen2_replication", - "description": "Replication", - "typeVersion": "1.0", - "serviceType": "azure", - "elementDefs": [ - { - "ordinal": 0, - "value": "LRS", - "description": "Locally-redundant storage" - }, - { - "ordinal": 1, - "value": "ZRS", - "description": "Zone-redundant storage" - }, - { - "ordinal": 2, - "value": "GRS", - "description": "Geo-redundant storage" - }, - { - "ordinal": 3, - "value": "GZRS", - "description": "Geo-zone-redundant storage" - }, - { - "ordinal": 4, - "value": "RA-GRS", - "description": "Read-access geo-redundant storage" - } - ] - }, - { - "name": "adls_gen2_authentication_method", - "description": "Authentication Method", - "typeVersion": "1.0", - "serviceType": "azure", - "elementDefs": [ - { - "ordinal": 0, - "value": "Access Key" - }, - { - "ordinal": 1, - "value": "Azure AD User Account" - } - ] - } - ], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ - { - "name": "adls_gen2_parent", - "description": "Atlas entity-type representing parent types (container, directory) that can hold other objects in Azure Data Lake Storage Gen2", - "superTypes": [ - ], - "serviceType": "azure", - "typeVersion": "1.0", - "attributeDefs": [ - ] - }, - { - "name": "adls_gen2_child", - "description": "Atlas entity-type representing child types (directory, blob) in Azure Data Lake Storage Gen2", - "superTypes": [ - ], - "serviceType": "azure", - "typeVersion": "1.0", - "attributeDefs": [ - ] - }, - { - "name": "adls_gen2_account", - "description": "Atlas entity-type representing a storage account in Azure Data Lake Storage Gen2", - "superTypes": [ - "Asset" - ], - "serviceType": "azure", - "typeVersion": "1.1", - "attributeDefs": [ - { - "name": "resourceGroup", - "description": "Resource group", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "status", - "description": "Status", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "location", - "description": "Location", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "subscription", - "description": "Subscription", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "tags", - "description": "Tags", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false, - "searchWeight" : 6 - }, - { - "name": "performance", - "description": "Performance", - "typeName": "adls_gen2_performance", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "accessTier", - "description": "Access tier", - "typeName": "adls_gen2_access_tier", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "replication", - "description": "Replication", - "typeName": "adls_gen2_replication", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "accountKind", - "description": "Account kind", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "isSecureTransferRequired", - "description": "Secure transfer required?", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "isLargeFileSharesEnabled", - "description": "Large File Shares enabled?", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "isIdentityBasedAccessForFileSharesEnabled", - "description": "Identity-based access for file shares?", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "isHierarchicalNamespaceEnabled", - "description": "Hierarchical namespace?", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "isNfsV3", - "description": "NFS v3?", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "skuName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "adls_gen2_container", - "description": "Atlas entity-type representing a storage container/filesystem in Azure Data Lake Storage Gen2", - "superTypes": [ - "DataSet", - "adls_gen2_parent" - ], - "serviceType": "azure", - "typeVersion": "1.1", - "attributeDefs": [ - { - "name": "url", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "eTag", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "authenticationMethod", - "typeName": "adls_gen2_authentication_method", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "additionalProperties", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "lastModifiedTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "publicAccess", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "adls_gen2_directory", - "description": "Atlas entity-type representing a directory in an Azure Data Lake Storage Gen2", - "superTypes": [ - "DataSet", - "adls_gen2_parent", - "adls_gen2_child", - "Path" - ], - "serviceType": "azure", - "typeVersion": "1.3", - "attributeDefs": [ - { - "name": "eTag", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "contentType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "contentEncoding", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "contentDisposition", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "cacheControl", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "lastModifiedTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "creationTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "contentLength", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "contentMd5", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "accessTier", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "prefix", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "remainingRetentionDays", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "type", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "additionalProperties", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "adls_gen2_blob", - "description": "Atlas entity-type representing a blob in an Azure Data Lake Storage Gen2", - "superTypes": [ - "DataSet", - "adls_gen2_child" - ], - "serviceType": "azure", - "typeVersion": "1.2", - "attributeDefs": [ - { - "name": "url", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "type", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "eTag", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "contentType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "additionalProperties", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "lastModifiedTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "creationTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "contentLength", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "contentMd5", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "accessTier", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "prefix", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "remainingRetentionDays", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "contentEncoding", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "contentDisposition", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "cacheControl", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - } - ], - "relationshipDefs": [ - { - "name": "adls_gen2_account_containers", - "serviceType": "azure", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "adls_gen2_account", - "name": "containers", - "isContainer": true, - "cardinality": "SET" - }, - "endDef2": { - "type": "adls_gen2_container", - "name": "account", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - }, - { - "name": "adls_gen2_parent_children", - "serviceType": "azure", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "adls_gen2_parent", - "name": "children", - "isContainer": true, - "cardinality": "SET" - }, - "endDef2": { - "type": "adls_gen2_child", - "name": "parent", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - } - ] -} diff --git a/addons/models/3000-Cloud/3050-ozone-typedefs.json b/addons/models/3000-Cloud/3050-ozone-typedefs.json deleted file mode 100644 index 071231ad9fb..00000000000 --- a/addons/models/3000-Cloud/3050-ozone-typedefs.json +++ /dev/null @@ -1,285 +0,0 @@ -{ - "enumDefs": [ - { - "name": "ozone_storage_type", - "description": "The storage type for an Ozone bucket", - "serviceType": "ozone", - "typeVersion": "1.0", - "elementDefs": [ - { - "ordinal": 0, - "value": "RAM_DISK" - }, - { - "ordinal": 1, - "value": "SSD" - }, - { - "ordinal": 2, - "value": "DISK" - }, - { - "ordinal": 3, - "value": "ARCHIVE" - } - ] - }, - { - "name": "ozone_replication_type", - "description": "The replication type for an Ozone key", - "serviceType": "ozone", - "typeVersion": "1.0", - "elementDefs": [ - { - "ordinal": 0, - "value": "RATIS" - }, - { - "ordinal": 1, - "value": "STAND_ALONE" - }, - { - "ordinal": 2, - "value": "CHAINED" - } - ] - } - ], - "structDefs": [ - { - "name": "ozone_key_location", - "description": "Location information about Ozone key", - "serviceType": "ozone", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "containerID", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "localID", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "length", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "offset", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - } - ] - } - ], - "classificationDefs": [], - "entityDefs": [ - { - "name": "ozone_parent", - "description": "Atlas entity-type representing parent types (bucket, key) in Ozone", - "superTypes": [ - ], - "serviceType": "ozone", - "typeVersion": "1.0", - "attributeDefs": [ - ] - }, - { - "name": "ozone_child", - "description": "Atlas entity-type representing child types (key) in Ozone", - "superTypes": [ - ], - "serviceType": "ozone", - "typeVersion": "1.0", - "attributeDefs": [ - ] - }, - { - "name": "ozone_volume", - "description": "Atlas Type representing an volume in an Ozone Object Store", - "superTypes": [ - "DataSet" - ], - "serviceType": "ozone", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "admin", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "quota", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "creationTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "ozone_bucket", - "description": "Atlas Type representing a bucket in an Ozone Object Store Volume", - "superTypes": [ - "DataSet", - "ozone_parent" - ], - "serviceType": "ozone", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "storageType", - "typeName": "ozone_storage_type", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "versioningEnabled", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "encryptionKeyName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "creationTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "ozone_key", - "description": "Atlas Type representing a key in an Ozone Object Store Bucket", - "superTypes": [ - "DataSet", - "ozone_parent", - "ozone_child" - ], - "serviceType": "ozone", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "dataSize", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "replicationType", - "typeName": "ozone_replication_type", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "replicationFactor", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "keyLocations", - "typeName": "array", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "creationTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - } - ], - "relationshipDefs": [ - { - "name": "ozone_volume_buckets", - "serviceType": "ozone", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "ozone_volume", - "name": "buckets", - "isContainer": true, - "cardinality": "SET" - }, - "endDef2": { - "type": "ozone_bucket", - "name": "volume", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - }, - { - "name": "ozone_parent_children", - "serviceType": "ozone", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "ozone_parent", - "name": "children", - "isContainer": true, - "cardinality": "SET" - }, - "endDef2": { - "type": "ozone_child", - "name": "parent", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - } - ] -} \ No newline at end of file diff --git a/addons/models/3000-Cloud/3060-gcp_typedefs.json b/addons/models/3000-Cloud/3060-gcp_typedefs.json deleted file mode 100644 index fbaed79d0ae..00000000000 --- a/addons/models/3000-Cloud/3060-gcp_typedefs.json +++ /dev/null @@ -1,232 +0,0 @@ -{ - "enumDefs": [], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ - { - "name": "gcp_storage_parent", - "description": "Atlas entity-type representing parent types (bucket, vitual directory) that can hold other objects in Google Cloud Storage", - "superTypes": [ - ], - "serviceType": "gcp", - "typeVersion": "1.0", - "attributeDefs": [ - ] - }, - { - "name": "gcp_storage_child", - "description": "Atlas entity-type representing child types (virtual directory, blob) in Google Cloud Storage", - "superTypes": [ - ], - "serviceType": "gcp", - "typeVersion": "1.0", - "attributeDefs": [ - ] - }, - { - "name": "gcp_storage_base", - "description": "Atlas Type representing base Type for all Google Cloud Storage Data Types", - "superTypes": [ - "DataSet" - ], - "serviceType": "gcp", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "creationTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "lastModifiedTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "storageClass", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "encryption", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "publicAccess", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "gcp_storage_bucket", - "description": "Atlas Type representing a Bucket in Google Cloud Storage", - "superTypes": [ - "gcp_storage_parent", - "gcp_storage_base" - ], - "serviceType": "gcp", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "location", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "locationType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "accessControl", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "lifecycleRules", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "labels", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "retentionPolicy", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "requesterPays", - "typeName": "boolean", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "gcp_storage_object", - "description": "Atlas Type representing an Object in Google Cloud Storage", - "superTypes": [ - "gcp_storage_child", - "gcp_storage_base" - ], - "serviceType": "gcp", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "size", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "type", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "retentionExpirationDate", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "holds", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "gcp_storage_virtual_directory", - "description": "Atlas Type representing a virtual directory in Google Cloud Storage", - "superTypes": [ - "gcp_storage_object", - "gcp_storage_parent", - "Path" - ], - "serviceType": "gcp", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "objectPrefix", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - } - ], - "relationshipDefs": [ - { - "name": "gcp_storage_parent_children", - "serviceType": "gcp", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "endDef1": { - "type": "gcp_storage_parent", - "name": "children", - "isContainer": true, - "cardinality": "SET" - }, - "endDef2": { - "type": "gcp_storage_child", - "name": "parent", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - } - ] -} diff --git a/addons/models/3000-Cloud/patches/001-cloud_model_add_service_type.json b/addons/models/3000-Cloud/patches/001-cloud_model_add_service_type.json deleted file mode 100644 index d6be60b0042..00000000000 --- a/addons/models/3000-Cloud/patches/001-cloud_model_add_service_type.json +++ /dev/null @@ -1,103 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_3000_127", - "description": "Set serviceType 'aws' to aws_tag", - "action": "SET_SERVICE_TYPE", - "typeName": "aws_tag", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "aws" - }, - { - "id": "TYPEDEF_PATCH_3000_128", - "description": "Set serviceType 'aws' to aws_cloud_watch_metric", - "action": "SET_SERVICE_TYPE", - "typeName": "aws_cloud_watch_metric", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "aws" - }, - { - "id": "TYPEDEF_PATCH_3000_129", - "description": "Set serviceType 'aws' to aws_s3_bucket_lifeCycleRule", - "action": "SET_SERVICE_TYPE", - "typeName": "aws_s3_bucket_lifeCycleRule", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "aws" - }, - { - "id": "TYPEDEF_PATCH_3000_130", - "description": "Set serviceType 'aws' to aws_s3_access_policy", - "action": "SET_SERVICE_TYPE", - "typeName": "aws_s3_access_policy", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "aws" - }, - { - "id": "TYPEDEF_PATCH_3000_131", - "description": "Set serviceType 'aws' to aws_s3_object", - "action": "SET_SERVICE_TYPE", - "typeName": "aws_s3_object", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "aws" - }, - { - "id": "TYPEDEF_PATCH_3000_132", - "description": "Set serviceType 'aws' to aws_s3_pseudo_dir", - "action": "SET_SERVICE_TYPE", - "typeName": "aws_s3_pseudo_dir", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "aws" - }, - { - "id": "TYPEDEF_PATCH_3000_133", - "description": "Set serviceType 'aws' to aws_s3_bucket", - "action": "SET_SERVICE_TYPE", - "typeName": "aws_s3_bucket", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "aws" - }, - { - "id": "TYPEDEF_PATCH_3000_134", - "description": "Set serviceType 'aws' to aws_s3_bucket_aws_s3_pseudo_dirs", - "action": "SET_SERVICE_TYPE", - "typeName": "aws_s3_bucket_aws_s3_pseudo_dirs", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "aws" - }, - { - "id": "TYPEDEF_PATCH_3000_135", - "description": "Set serviceType 'aws' to aws_s3_pseudo_dir_aws_objects", - "action": "SET_SERVICE_TYPE", - "typeName": "aws_s3_pseudo_dir_aws_objects", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "aws" - }, - { - "id": "TYPEDEF_PATCH_3000_136", - "description": "Set serviceType 'aws' to aws_s3_object_avro_schema", - "action": "SET_SERVICE_TYPE", - "typeName": "aws_s3_object_avro_schema", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "aws" - }, - { - "id": "TYPEDEF_PATCH_3000_137", - "description": "Set serviceType 'aws' to aws_s3_pseudo_dir_avro_schema", - "action": "SET_SERVICE_TYPE", - "typeName": "aws_s3_pseudo_dir_avro_schema", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "serviceType": "aws" - } - ] -} diff --git a/addons/models/3000-Cloud/patches/002-cloud_model_add_searchweight.json b/addons/models/3000-Cloud/patches/002-cloud_model_add_searchweight.json deleted file mode 100644 index 5daaca298a8..00000000000 --- a/addons/models/3000-Cloud/patches/002-cloud_model_add_searchweight.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_3000_138", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "aws_s3_pseudo_dir", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "subject", - "params": { - "searchWeight": 10 - } - }, { - "id": "TYPEDEF_PATCH_3000_139", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "aws_s3_pseudo_dir", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "objectPrefix", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_3000_140", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "aws_s3_pseudo_dir", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "currentStorageLocation", - "params": { - "searchWeight": 5 - } - }, { - "id": "TYPEDEF_PATCH_3000_141", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "aws_s3_pseudo_dir", - "applyToVersion": "1.4", - "updateToVersion": "1.5", - "attributeName": "subdomain", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_3000_142", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "aws_s3_object", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeName": "partner", - "params": { - "searchWeight": 5 - } - }, { - "id": "TYPEDEF_PATCH_3000_143", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "aws_s3_object", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "attributeName": "domain", - "params": { - "searchWeight": 8 - } - }, { - "id": "TYPEDEF_PATCH_3000_144", - "description": "Adding search Weights", - "action": "UPDATE_ATTRIBUTE_METADATA", - "typeName": "aws_s3_object", - "applyToVersion": "1.3", - "updateToVersion": "1.4", - "attributeName": "region", - "params": { - "searchWeight": 8 - } - } - ] -} diff --git a/addons/models/3000-Cloud/patches/003-cloud_model_remove_legacy_attributes.json b/addons/models/3000-Cloud/patches/003-cloud_model_remove_legacy_attributes.json deleted file mode 100644 index 2337f25b6cb..00000000000 --- a/addons/models/3000-Cloud/patches/003-cloud_model_remove_legacy_attributes.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_3000_003_001", - "description": "Remove legacy reference attribute 's3Objects' from aws_s3_pseudo_dir", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "aws_s3_pseudo_dir_aws_objects", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__aws_s3_pseudo_dir.s3Objects", - "relationshipCategory": "COMPOSITION" - } - }, - { - "id": "TYPEDEF_PATCH_3000_003_002", - "description": "Remove legacy reference attribute 'pseudoDirectories' from aws_s3_bucket", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "aws_s3_bucket_aws_s3_pseudo_dirs", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__aws_s3_bucket.pseudoDirectories", - "relationshipCategory": "COMPOSITION" - } - }, - { - "id": "TYPEDEF_PATCH_3000_003_003", - "description": "Remove legacy reference attribute 'avroSchema from aws_s3_object", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "aws_s3_object_avro_schema", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__aws_s3_object.avroSchema", - "relationshipCategory": "ASSOCIATION" - } - }, - { - "id": "TYPEDEF_PATCH_3000_003_004", - "description": "Remove legacy reference attribute 'avroSchemas' from aws_s3_pseudo_dir", - "action": "REMOVE_LEGACY_REF_ATTRIBUTES", - "typeName": "aws_s3_pseudo_dir_avro_schema", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": { - "relationshipLabel": "__aws_s3_pseudo_dir.avroSchemas", - "relationshipCategory": "ASSOCIATION" - } - } - ] -} \ No newline at end of file diff --git a/addons/models/3000-Cloud/patches/004-s3_add_attributes.json b/addons/models/3000-Cloud/patches/004-s3_add_attributes.json deleted file mode 100644 index 6184108db41..00000000000 --- a/addons/models/3000-Cloud/patches/004-s3_add_attributes.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_3000_004_001", - "description": "Add 'permissions' attribute to aws s3 bucket", - "action": "ADD_ATTRIBUTE", - "typeName": "aws_s3_bucket", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "attributeDefs": [ - { - "name": "permissions", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "searchWeight": 5 - }, { - "name": "ownerId", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "searchWeight" : 5 - } - - ] - }, { - "id": "TYPEDEF_PATCH_3000_004_002", - "description": "Add 'ownerId' attribute to aws s3 bucket", - "action": "ADD_ATTRIBUTE", - "typeName": "aws_s3_object", - "applyToVersion": "1.4", - "updateToVersion": "1.5", - "attributeDefs": [ - { - "name": "ownerId", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "searchWeight" : 5 - }, { - "name": "size", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, { - "name": "eTag", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "searchWeight" : 5 - }, { - "name": "lastModified", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, { - "name": "storageClass", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false, - "searchWeight" : 5 - } - ] - } - ] -} diff --git a/addons/models/3000-Cloud/patches/005-azure_adls_add_attributes.json b/addons/models/3000-Cloud/patches/005-azure_adls_add_attributes.json deleted file mode 100644 index ce87d45d6a0..00000000000 --- a/addons/models/3000-Cloud/patches/005-azure_adls_add_attributes.json +++ /dev/null @@ -1,254 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_3000_005_001", - "description": "Add attributes to Azure ADLS Account", - "action": "ADD_ATTRIBUTE", - "typeName": "adls_gen2_account", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "attributeDefs": [ - { - "name": "skuName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "id": "TYPEDEF_PATCH_3000_005_002", - "description": "Add attributes to Azure ADLS container", - "action": "ADD_ATTRIBUTE", - "typeName": "adls_gen2_container", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "attributeDefs": [ - { - "name": "lastModifiedTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "publicAccess", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "id": "TYPEDEF_PATCH_3000_005_003", - "description": "Add attributes to Azure ADLS directory", - "action": "ADD_ATTRIBUTE", - "typeName": "adls_gen2_directory", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "attributeDefs": [ - { - "name": "lastModifiedTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "creationTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "contentLength", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "contentMd5", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "accessTier", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "prefix", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "remainingRetentionDays", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "type", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "additionalProperties", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "id": "TYPEDEF_PATCH_3000_005_004", - "description": "Add attributes to Azure ADLS blob", - "action": "ADD_ATTRIBUTE", - "typeName": "adls_gen2_blob", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "attributeDefs": [ - { - "name": "lastModifiedTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "creationTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "contentLength", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "contentMd5", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "accessTier", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "prefix", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "remainingRetentionDays", - "typeName": "long", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true - }, - { - "name": "contentEncoding", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "contentDisposition", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "cacheControl", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "id": "TYPEDEF_PATCH_3000_005_005", - "description": "Update 'contentType' attribute in adls_gen2_directory", - "action": "UPDATE_ATTRIBUTE", - "typeName": "adls_gen2_directory", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": null, - "attributeDefs": [ - { - "name": "contentType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "id": "TYPEDEF_PATCH_3000_005_006", - "description": "Update 'contentType' attribute in adls_gen2_blob", - "action": "UPDATE_ATTRIBUTE", - "typeName": "adls_gen2_blob", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": null, - "attributeDefs": [ - { - "name": "contentType", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - } - ] -} diff --git a/addons/models/3000-Cloud/patches/006-cloud-model_add_supertypes.json b/addons/models/3000-Cloud/patches/006-cloud-model_add_supertypes.json deleted file mode 100644 index 6e2ea57e496..00000000000 --- a/addons/models/3000-Cloud/patches/006-cloud-model_add_supertypes.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_3000_006_001", - "description": "Add superTypes for aws_s3_pseudo_dir", - "action": "ADD_SUPER_TYPES", - "typeName": "aws_s3_pseudo_dir", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "params": null, - "superTypes": [ - "Path" - ] - }, - { - "id": "TYPEDEF_PATCH_3000_006_002", - "description": "Add superTypes for aws_s3_v2_directory", - "action": "ADD_SUPER_TYPES", - "typeName": "aws_s3_v2_directory", - "applyToVersion": "1.0", - "updateToVersion": "1.1", - "params": null, - "superTypes": [ - "Path" - ] - }, - { - "id": "TYPEDEF_PATCH_3000_006_003", - "description": "Add superTypes for adls_gen2_directory", - "action": "ADD_SUPER_TYPES", - "typeName": "adls_gen2_directory", - "applyToVersion": "1.2", - "updateToVersion": "1.3", - "params": null, - "superTypes": [ - "Path" - ] - } - ] -} diff --git a/addons/models/3000-Cloud/patches/007-s3_v2_update_attributes.json b/addons/models/3000-Cloud/patches/007-s3_v2_update_attributes.json deleted file mode 100644 index f29c5bfbf2b..00000000000 --- a/addons/models/3000-Cloud/patches/007-s3_v2_update_attributes.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "patches": [ - { - "id": "TYPEDEF_PATCH_3000_007_001", - "description": "Update objectPrefix isUnique for aws_s3_v2_directory to false", - "action": "UPDATE_ATTRIBUTE", - "typeName": "aws_s3_v2_directory", - "applyToVersion": "1.1", - "updateToVersion": "1.2", - "params": null, - "attributeDefs": [ - { - "name": "objectPrefix", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - } - ] - } - ] -} \ No newline at end of file diff --git a/addons/models/4000-MachineLearning/4010-ml_model.json b/addons/models/4000-MachineLearning/4010-ml_model.json deleted file mode 100644 index 438a1481fa2..00000000000 --- a/addons/models/4000-MachineLearning/4010-ml_model.json +++ /dev/null @@ -1,377 +0,0 @@ -{ - "enumDefs": [ - { - "category": "ENUM", - "version": 1, - "name": "ml_model_deployment_status", - "description": "The deployment status of a ML model build", - "typeVersion": "1.0", - "elementDefs": [ - { - "value": "unknown", - "ordinal": 0 - }, - { - "value": "deploying", - "ordinal": 1 - }, - { - "value": "deployed", - "ordinal": 2 - }, - { - "value": "stopping", - "ordinal": 3 - }, - { - "value": "stopped", - "ordinal": 4 - } - ] - } - ], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [ - { - "name": "ml_project", - "description": "Represent a ML Project that contains source code and related resources", - "superTypes": [ - "DataSet" - ], - "serviceType": "ml", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "metadata", - "description": "Contains key-value pairs that provide project metadata", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false, - "options": { - "isAppendOnPartialUpdate": "true" - } - }, - { - "name": "createTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - }, - { - "name": "modifiedTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "ml_model_build", - "description": "An immutable container image built from a ML project and its training data", - "superTypes": [ - "DataSet" - ], - "serviceType": "ml", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "version", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "metadata", - "description": "Contains key-value pairs that provide metadata", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false, - "options": { - "isAppendOnPartialUpdate": "true" - } - }, - { - "name": "defaultCpuMillicores", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "defaultMemoryMb", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "defaultGpus", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "imageTag", - "description": "Include URL to get the container image of this model build", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": false, - "includeInNotification": false - }, - { - "name": "imageHash", - "description": "Image signature. Combined with imageTag to uniquely identify a model build", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": false, - "includeInNotification": false - }, - { - "name": "exampleRequest", - "description": "request example to the model as a JSON string", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": false, - "includeInNotification": false - }, - { - "name": "exampleResponse", - "description": "response example from the model as a JSON string", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": false, - "includeInNotification": false - }, - { - "name": "createTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "ml_model_deployment", - "description": "A deployed instance of a model build", - "superTypes": [ - "DataSet" - ], - "serviceType": "ml", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "createTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "deployedTime", - "typeName": "date", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "metadata", - "description": "Contains key-value pairs that provide metadata", - "typeName": "map", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false, - "options": { - "isAppendOnPartialUpdate": "true" - } - }, - { - "name": "modelEndpointURL", - "description": "The URL to receive request and send back prediction", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": false, - "includeInNotification": false - }, - { - "name": "status", - "typeName": "ml_model_deployment_status", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - }, - { - "name": "cpuMillicores", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": false, - "isUnique": false - }, - { - "name": "memoryMb", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "gpus", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - }, - { - "name": "replicas", - "typeName": "int", - "cardinality": "SINGLE", - "isIndexable": false, - "isOptional": true, - "isUnique": false - } - ] - }, - { - "name": "ml_project_create_process", - "description": "process that creates a ML project", - "superTypes": [ - "Process" - ], - "serviceType": "ml", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "userName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - } - ] - }, - { - "name": "ml_model_train_build_process", - "description": "process that trains a model and builds an immutable model build", - "superTypes": [ - "Process" - ], - "serviceType": "ml", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "userName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - } - ] - }, - { - "name": "ml_model_deploy_process", - "description": "process that deploys a model build and creates replicated instances", - "superTypes": [ - "Process" - ], - "serviceType": "ml", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "userName", - "typeName": "string", - "cardinality": "SINGLE", - "isIndexable": true, - "isOptional": false, - "isUnique": false - } - ] - } - ], - "relationshipDefs": [ - { - "name": "ml_project_model_build", - "serviceType": "ml", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__ml_project.builds", - "endDef1": { - "type": "ml_project", - "name": "builds", - "isContainer": true, - "cardinality": "SET" - }, - "endDef2": { - "type": "ml_model_build", - "name": "project", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - }, - { - "name": "ml_build_deployment", - "serviceType": "ml", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "relationshipLabel": "__ml_build.deployments", - "endDef1": { - "type": "ml_model_build", - "name": "deployments", - "isContainer": true, - "cardinality": "SET" - }, - "endDef2": { - "type": "ml_model_deployment", - "name": "build", - "isContainer": false, - "cardinality": "SINGLE" - }, - "propagateTags": "NONE" - } - ] -} diff --git a/addons/policies/atlas_service.json b/addons/policies/atlas_service.json new file mode 100644 index 00000000000..660c84333db --- /dev/null +++ b/addons/policies/atlas_service.json @@ -0,0 +1,54 @@ +{ + "entities": [ + { + "typeName": "AuthService", + "attributes": + { + "qualifiedName": "auth_service_atlas_tag", + "name": "atlas_tag", + "authServiceType": "tag", + "authServiceConfig": { + "ranger.plugin.audit.filters": "[{'accessResult':'DENIED','isAudited':true}]" + } + } + }, + { + "typeName": "AuthService", + "attributes": + { + "qualifiedName": "auth_service_atlas_abac", + "name": "atlas_abac", + "authServiceType": "abac", + "authServiceConfig": { + "ranger.plugin.audit.filters": "[{'accessResult':'DENIED','isAudited':true}]" + } + } + }, + { + "typeName": "AuthService", + "attributes": + { + "qualifiedName": "auth_service_atlas", + "name": "atlas", + "authServiceType": "atlas", + "tagService": "atlas_tag", + "abacService": "atlas_abac", + "authServiceConfig": { + "ranger.plugin.audit.filters": "[ {'accessResult': 'DENIED', 'isAudited': true}, {'users':['atlas'] ,'isAudited':false} ]" + } + } + }, + { + "typeName": "AuthService", + "attributes": + { + "qualifiedName": "auth_service_heka", + "name": "heka", + "authServiceType": "heka", + "tagService": "atlas_tag", + "authServiceConfig": {} + } + } + ] +} + diff --git a/addons/policies/bootstrap_admin_policies.json b/addons/policies/bootstrap_admin_policies.json new file mode 100644 index 00000000000..5f301ad0af7 --- /dev/null +++ b/addons/policies/bootstrap_admin_policies.json @@ -0,0 +1,79 @@ +{ + "entities": [ + { + "typeName": "AuthPolicy", + "attributes": { + "name": "RUN_REPAIR_INDEX", + "qualifiedName": "RUN_REPAIR_INDEX", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": [ + "service-account-atlan-argo", + "service-account-atlan-backend" + ], + "policyGroups": [], + "policyRoles": [], + "policyResourceCategory": "ADMIN", + "policyResources": [ + "atlas-service:*" + ], + "policyActions": [ + "admin-repair-index" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": { + "name": "ADMIN_ALLOW_TASK_CUD", + "qualifiedName": "ADMIN_ALLOW_TASK_CUD", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": [ + "service-account-atlan-argo", + "service-account-atlan-backend" + ], + "policyGroups": [], + "policyRoles": [], + "policyResourceCategory": "ADMIN", + "policyResources": [ + "atlas-service:*" + ], + "policyActions": [ + "admin-task-cud" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": { + "name": "ADMIN_ALLOW_FEATURE_FLAG_CUD", + "qualifiedName": "ADMIN_ALLOW_FEATURE_FLAG_CUD", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": [ + "service-account-atlan-argo", + "service-account-atlan-backend" + ], + "policyGroups": [], + "policyRoles": [], + "policyResourceCategory": "ADMIN", + "policyResources": [ + "atlas-service:*" + ], + "policyActions": [ + "admin-featureFlag-cud" + ] + } + } + ] +} \ No newline at end of file diff --git a/addons/policies/bootstrap_entity_policies.json b/addons/policies/bootstrap_entity_policies.json new file mode 100644 index 00000000000..a82e4e91f03 --- /dev/null +++ b/addons/policies/bootstrap_entity_policies.json @@ -0,0 +1,3771 @@ +{ + "entities": + [ + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 27 + }, + "attributes": + { + "name": "CREATE_SAVEDFILTER", + "qualifiedName": "CREATE_SAVEDFILTER", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:__AtlasUserSavedSearch", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 27 + }, + "attributes": + { + "name": "READ_SAVEDFILTER", + "qualifiedName": "READ_SAVEDFILTER", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:__AtlasUserSavedSearch", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 27 + }, + "attributes": + { + "name": "UPDATE_SAVEDFILTER", + "qualifiedName": "UPDATE_SAVEDFILTER", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:__AtlasUserSavedSearch", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 27 + }, + "attributes": + { + "name": "DELETE_SAVEDFILTER", + "qualifiedName": "DELETE_SAVEDFILTER", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:__AtlasUserSavedSearch", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 26 + }, + "attributes": + { + "name": "LIST_SAVEDFILTER_SELF", + "qualifiedName": "LIST_SAVEDFILTER_SELF", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$guest", + "$member" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:__AtlasUserSavedSearch", + "entity-classification:*", + "entity:{USER}", + "entity:{USER}:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 26 + }, + "attributes": + { + "name": "UPDATE_SAVEDFILTER_SELF", + "qualifiedName": "UPDATE_SAVEDFILTER_SELF", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:__AtlasUserSavedSearch", + "entity-classification:*", + "entity:{USER}", + "entity:{USER}:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 26 + }, + "attributes": + { + "name": "DELETE_SAVEDFILTER_SELF", + "qualifiedName": "DELETE_SAVEDFILTER_SELF", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:__AtlasUserSavedSearch", + "entity-classification:*", + "entity:{USER}", + "entity:{USER}:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 28 + }, + "attributes": + { + "name": "CREATE_GLOSSARY", + "qualifiedName": "CREATE_GLOSSARY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossary", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 28 + }, + "attributes": + { + "name": "READ_GLOSSARY", + "qualifiedName": "READ_GLOSSARY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossary", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 28 + }, + "attributes": + { + "name": "UPDATE_GLOSSARY", + "qualifiedName": "UPDATE_GLOSSARY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossary", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 28 + }, + "attributes": + { + "name": "DELETE_GLOSSARY", + "qualifiedName": "DELETE_GLOSSARY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossary", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 29 + }, + "attributes": + { + "name": "CREATE_TERM", + "qualifiedName": "CREATE_TERM", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossaryTerm", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 29 + }, + "attributes": + { + "name": "READ_TERM", + "qualifiedName": "READ_TERM", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossaryTerm", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 29 + }, + "attributes": + { + "name": "UPDATE_TERM", + "qualifiedName": "UPDATE_TERM", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossaryTerm", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 29 + }, + "attributes": + { + "name": "DELETE_TERM", + "qualifiedName": "DELETE_TERM", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossaryTerm", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 30 + }, + "attributes": + { + "name": "CREATE_CATEGORY", + "qualifiedName": "CREATE_CATEGORY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossaryCategory", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 30 + }, + "attributes": + { + "name": "READ_CATEGORY", + "qualifiedName": "READ_CATEGORY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossaryCategory", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 30 + }, + "attributes": + { + "name": "UPDATE_CATEGORY", + "qualifiedName": "UPDATE_CATEGORY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossaryCategory", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 30 + }, + "attributes": + { + "name": "DELETE_CATEGORY", + "qualifiedName": "DELETE_CATEGORY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossaryCategory", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 34 + }, + "attributes": + { + "name": "CREATE_README", + "qualifiedName": "CREATE_README", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Readme", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 34 + }, + "attributes": + { + "name": "READ_README", + "qualifiedName": "READ_README", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Readme", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 34 + }, + "attributes": + { + "name": "UPDATE_README", + "qualifiedName": "UPDATE_README", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Readme", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 34 + }, + "attributes": + { + "name": "DELETE_README", + "qualifiedName": "DELETE_README", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Readme", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 123 + }, + "attributes": + { + "name": "CREATE_BADGE", + "qualifiedName": "CREATE_BADGE", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Badge", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 123 + }, + "attributes": + { + "name": "READ_BADGE", + "qualifiedName": "READ_BADGE", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Badge", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 123 + }, + "attributes": + { + "name": "UPDATE_BADGE", + "qualifiedName": "UPDATE_BADGE", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Badge", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 123 + }, + "attributes": + { + "name": "DELETE_BADGE", + "qualifiedName": "DELETE_BADGE", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Badge", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 35 + }, + "attributes": + { + "name": "CREATE_BOOKMARK", + "qualifiedName": "CREATE_BOOKMARK", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlanBookmark", + "entity-classification:*", + "entity:{USER}", + "entity:{USER}:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 35 + }, + "attributes": + { + "name": "READ_BOOKMARK_SELF", + "qualifiedName": "READ_BOOKMARK_SELF", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlanBookmark", + "entity-classification:*", + "entity:{USER}", + "entity:{USER}:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 35 + }, + "attributes": + { + "name": "UPDATE_BOOKMARK_SELF", + "qualifiedName": "UPDATE_BOOKMARK_SELF", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlanBookmark", + "entity-classification:*", + "entity:{USER}", + "entity:{USER}:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 35 + }, + "attributes": + { + "name": "DELETE_BOOKMARK_SELF", + "qualifiedName": "DELETE_BOOKMARK_SELF", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlanBookmark", + "entity-classification:*", + "entity:{USER}", + "entity:{USER}:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "UPDATE_QUERY_CLASSIFICATION", + "qualifiedName": "UPDATE_QUERY_CLASSIFICATION", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "{USER}" + ], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Query", + "entity-type:QueryFolder", + "entity-classification:*", + "entity:{USER}", + "entity:*/{USER}/*" + ], + "policyActions": + [ + "entity-add-classification", + "entity-update-classification", + "entity-remove-classification" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "ADD_TERM_CLASSIFICATION", + "qualifiedName": "ADD_TERM_CLASSIFICATION", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossaryTerm", + "entity-classification:*", + "classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-add-classification", + "entity-update-classification", + "entity-remove-classification" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 103 + }, + "attributes": + { + "name": "CREATE_LINK", + "qualifiedName": "CREATE_LINK", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Link", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 103 + }, + "attributes": + { + "name": "READ_LINK", + "qualifiedName": "READ_LINK", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Link", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 103 + }, + "attributes": + { + "name": "UPDATE_LINK", + "qualifiedName": "UPDATE_LINK", + "policySubCategory": "default", + "policyCategory": "bootstrap", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Link", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 103 + }, + "attributes": + { + "name": "DELETE_LINK", + "qualifiedName": "DELETE_LINK", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Link", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CREATE_QUERIES", + "qualifiedName": "CREATE_QUERIES", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:QueryFolderNamespace", + "entity-type:Query", + "entity-type:QueryFolder", + "entity-type:QueryFolderParent", + "entity-type:QueryFolderChild", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "READ_QUERIES", + "qualifiedName": "READ_QUERIES", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:QueryFolderNamespace", + "entity-type:Query", + "entity-type:QueryFolder", + "entity-type:QueryFolderParent", + "entity-type:QueryFolderChild", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "UPDATE_QUERIES", + "qualifiedName": "UPDATE_QUERIES", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:QueryFolderNamespace", + "entity-type:Query", + "entity-type:QueryFolder", + "entity-type:QueryFolderParent", + "entity-type:QueryFolderChild", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "DELETE_QUERIES", + "qualifiedName": "DELETE_QUERIES", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:QueryFolderNamespace", + "entity-type:Query", + "entity-type:QueryFolder", + "entity-type:QueryFolderParent", + "entity-type:QueryFolderChild", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 107 + }, + "attributes": + { + "name": "CREATE_CONNECTION", + "qualifiedName": "CREATE_CONNECTION", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Connection", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 108 + }, + "attributes": + { + "name": "CREATE_COLLECTION", + "qualifiedName": "CREATE_COLLECTION", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Collection", + "entity-classification:*", + "entity:{USER}", + "entity:*/{USER}/*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 109 + }, + "attributes": + { + "name": "BM_UPDATE_GLOSSARY", + "qualifiedName": "BM_UPDATE_GLOSSARY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossary", + "entity-classification:*", + "entity:*", + "entity-business-metadata:*" + ], + "policyActions": + [ + "entity-update-business-metadata" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 110 + }, + "attributes": + { + "name": "BM_UPDATE_TERM", + "qualifiedName": "BM_UPDATE_TERM", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossaryTerm", + "entity-classification:*", + "entity:*", + "entity-business-metadata:*" + ], + "policyActions": + [ + "entity-update-business-metadata" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 114 + }, + "attributes": + { + "name": "BM_UPDATE_CATEGORY", + "qualifiedName": "BM_UPDATE_CATEGORY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossaryCategory", + "entity-classification:*", + "entity:*", + "entity-business-metadata:*" + ], + "policyActions": + [ + "entity-update-business-metadata" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CREATE_PROCESS_ASSET", + "qualifiedName": "CREATE_PROCESS_ASSET", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Process", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "READ_PROCESS_ASSET", + "qualifiedName": "READ_PROCESS_ASSET", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Process", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "UPDATE_PROCESS_ASSET", + "qualifiedName": "UPDATE_PROCESS_ASSET", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Process", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "DELETE_PROCESS_ASSET", + "qualifiedName": "DELETE_PROCESS_ASSET", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Process", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 117 + }, + "attributes": + { + "name": "CREATE_README_TEMPLATE", + "qualifiedName": "CREATE_README_TEMPLATE", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:ReadmeTemplate", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 117 + }, + "attributes": + { + "name": "READ_README_TEMPLATE", + "qualifiedName": "READ_README_TEMPLATE", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:ReadmeTemplate", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 117 + }, + "attributes": + { + "name": "UPDATE_README_TEMPLATE", + "qualifiedName": "UPDATE_README_TEMPLATE", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:ReadmeTemplate", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 117 + }, + "attributes": + { + "name": "DELETE_README_TEMPLATE", + "qualifiedName": "DELETE_README_TEMPLATE", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:ReadmeTemplate", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 119 + }, + "attributes": + { + "name": "CREATE_AUDITENTRY", + "qualifiedName": "CREATE_AUDITENTRY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:__AtlasAuditEntry", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 119 + }, + "attributes": + { + "name": "READ_AUDITENTRY", + "qualifiedName": "READ_AUDITENTRY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:__AtlasAuditEntry", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 119 + }, + "attributes": + { + "name": "UPDATE_AUDITENTRY", + "qualifiedName": "UPDATE_AUDITENTRY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:__AtlasAuditEntry", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 119 + }, + "attributes": + { + "name": "DELETE_AUDITENTRY", + "qualifiedName": "DELETE_AUDITENTRY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:__AtlasAuditEntry", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "UPDATE_ENTITY_BUSINESS_METADATA", + "qualifiedName": "UPDATE_ENTITY_BUSINESS_METADATA", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "admin", + "service-account-atlan-argo", + "service-account-atlan-backend", + "atlan-governance-workflows" + ], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:*", + "entity-classification:*", + "entity:*", + "entity-business-metadata:*" + ], + "policyActions": + [ + "entity-update-business-metadata" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "READ_ENTITY", + "qualifiedName": "READ_ENTITY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "rangertagsync" + ], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:*", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CRUD_ENTITY", + "qualifiedName": "CRUD_ENTITY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "admin", + "service-account-atlan-argo", + "service-account-atlan-backend", + "atlan-governance-workflows" + ], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:*", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read", + "entity-create", + "entity-update", + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "AUR_CLASSIFICATION", + "qualifiedName": "AUR_CLASSIFICATION", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "admin", + "service-account-atlan-argo", + "service-account-atlan-backend", + "atlan-governance-workflows" + ], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:*", + "entity-classification:*", + "entity:*", + "classification:*" + ], + "policyActions": + [ + "entity-add-classification", + "entity-update-classification", + "entity-remove-classification" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "AR_ENITY_LABEL", + "qualifiedName": "AR_ENITY_LABEL", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "admin", + "service-account-atlan-argo", + "service-account-atlan-backend" + ], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:*", + "entity-classification:*", + "entity:*", + "entity-label:*" + ], + "policyActions": + [ + "entity-add-label", + "entity-remove-label" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CRUD_ENTITY_SAVED_SEARCH", + "qualifiedName": "CRUD_ENTITY_SAVED_SEARCH", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "{USER}" + ], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:__AtlasUserProfile", + "entity-type:__AtlasUserSavedSearch", + "entity-classification:*", + "entity:{USER}", + "entity:{USER}:*" + ], + "policyActions": + [ + "entity-read", + "entity-create", + "entity-update", + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CRUD_COLLECTION_FOLDER_QUERY", + "qualifiedName": "CRUD_COLLECTION_FOLDER_QUERY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "{USER}" + ], + "policyGroups": + [], + "policyRoles": + [ + "$member", + "$admin" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Collection", + "entity-type:Query", + "entity-type:Folder", + "entity-classification:*", + "entity:*/{USER}/*" + ], + "policyActions": + [ + "entity-read", + "entity-create", + "entity-update", + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "EIPA_ATLAS_SERVICE", + "qualifiedName": "EIPA_ATLAS_SERVICE", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "admin", + "service-account-atlan-argo", + "service-account-atlan-backend" + ], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "atlas-service:*" + ], + "policyActions": + [ + "admin-export", + "admin-import", + "admin-purge", + "admin-audits" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 120 + }, + "attributes": + { + "name": "CREATE_ACCESS_CONTROL_ENTITIES", + "qualifiedName": "CREATE_ACCESS_CONTROL_ENTITIES", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Persona", + "entity-type:Purpose", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 120 + }, + "attributes": + { + "name": "READ_ACCESS_CONTROL_ENTITIES", + "qualifiedName": "READ_ACCESS_CONTROL_ENTITIES", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [ + "service-account-atlan-argo", + "service-account-atlan-backend", + "atlan-governance-workflows" + ], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Persona", + "entity-type:Purpose", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 120 + }, + "attributes": + { + "name": "UPDATE_ACCESS_CONTROL_ENTITIES", + "qualifiedName": "UPDATE_ACCESS_CONTROL_ENTITIES", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Persona", + "entity-type:Purpose", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 120 + }, + "attributes": + { + "name": "DELETE_ACCESS_CONTROL_ENTITIES", + "qualifiedName": "DELETE_ACCESS_CONTROL_ENTITIES", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Persona", + "entity-type:Purpose", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CREATE_AUTH_POLICIES", + "qualifiedName": "CREATE_AUTH_POLICIES", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "service-account-atlan-argo", + "service-account-atlan-backend", + "atlan-governance-workflows" + ], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AuthPolicy", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "READ_AUTH_POLICIES", + "qualifiedName": "READ_AUTH_POLICIES", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [ + "service-account-atlan-argo", + "service-account-atlan-backend", + "atlan-governance-workflows" + ], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AuthPolicy", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "UPDATE_AUTH_POLICIES", + "qualifiedName": "UPDATE_AUTH_POLICIES", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "service-account-atlan-argo", + "service-account-atlan-backend", + "atlan-governance-workflows" + ], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AuthPolicy", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "DELETE_AUTH_POLICIES", + "qualifiedName": "DELETE_AUTH_POLICIES", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "service-account-atlan-argo", + "service-account-atlan-backend", + "atlan-governance-workflows" + ], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AuthPolicy", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CUD_ENTITY_DENY_GUEST", + "qualifiedName": "CUD_ENTITY_DENY_GUEST", + "description": "cud deny for guest users", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "deny", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$guest" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AtlasGlossaryTerm", + "entity-type:AtlasGlossaryCategory", + "entity-type:AtlasGlossary", + "entity-type:Catalog", + "entity-type:Process", + "entity-type:Connection", + "entity-type:ProcessExecution", + "entity-type:File", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create", + "entity-update", + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "BM_DENY_GUEST", + "qualifiedName": "BM_DENY_GUEST", + "description": "deny guest update entity-business-metadata", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "deny", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$guest" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:*", + "entity-classification:*", + "entity:*", + "entity-business-metadata:*" + ], + "policyActions": + [ + "entity-update-business-metadata" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CUD_CLASSIFICATION_DENY_GUEST", + "qualifiedName": "CUD_CLASSIFICATION_DENY_GUEST", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "deny", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$guest" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:*", + "entity-classification:*", + "entity:*", + "classification:*" + ], + "policyActions": + [ + "entity-add-classification", + "entity-update-classification", + "entity-remove-classification" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "FILE_CRUD_ALLOW_USERS", + "qualifiedName": "FILE_CRUD_ALLOW_USERS", + "description": "Allows user to perform crud operation on file asset", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:File", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create", + "entity-read", + "entity-update", + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CONNECTION_UPDATE_DENY_MEMBER", + "qualifiedName": "CONNECTION_UPDATE_DENY_MEMBER", + "description": "Policy for connection update deny for members", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "deny", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$member" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:Connection", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CRUD_DATA_MESH_ENTITIES", + "qualifiedName": "CRUD_DATA_MESH_ENTITIES", + "description": "Allows user to perform crud operation on data mesh assets", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:DataDomain", + "entity-type:DataProduct", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create", + "entity-read", + "entity-update", + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "DATA_MESH_CLASSIFICATION", + "qualifiedName": "DATA_MESH_CLASSIFICATION", + "description": "Allows tagging data mesh assets", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:DataDomain", + "entity-type:DataProduct", + "entity-classification:*", + "entity:*", + "classification:*" + ], + "policyActions": + [ + "entity-add-classification", + "entity-update-classification", + "entity-remove-classification" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "READ_DATA_MESH_ENTITIES", + "qualifiedName": "READ_DATA_MESH_ENTITIES", + "description": "Allows user to perform to do read operation on data mesh assets", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$member", + "$guest" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:DataDomain", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CUD_DATA_PRODUCT_ENTITY", + "qualifiedName": "CUD_DATA_PRODUCT_ENTITY", + "description": "Allows user to perform cud operation on DataProduct assets.", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "isPolicyEnabled": false, + "policyResources": + [ + "entity-type:DataProduct", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create", + "entity-update", + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "READ_DATA_CONTRACT", + "qualifiedName": "READ_DATA_CONTRACT", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:DataContract", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CU_DATA_CONTRACT", + "qualifiedName": "CU_DATA_CONTRACT", + "description": "cu allow for data contract", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:DataContract", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create", + "entity-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "READ_DATA_MESH_STAKEHOLDER_TITLE", + "qualifiedName": "READ_DATA_MESH_STAKEHOLDER_TITLE", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$guest", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:StakeholderTitle", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + + { + "typeName": "AuthPolicy", + "attributes": { + "name": "CUD_BUSINESS_POLICY", + "qualifiedName": "CUD_BUSINESS_POLICY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": [], + "policyGroups": [], + "policyRoles": [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity-type:BusinessPolicy", + "entity-type:BusinessPolicyException", + "entity-classification:*", + "entity:*" + ], + "policyActions": [ + "entity-create", + "entity-update", + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": { + "name": "READ_BUSINESS_POLICY", + "qualifiedName": "READ_BUSINESS_POLICY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": [], + "policyGroups": [], + "policyRoles": [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity-type:BusinessPolicy", + "entity-type:BusinessPolicyException", + "entity-classification:*", + "entity:*" + ], + "policyActions": [ + "entity-read" + ] + } + }, + + { + "typeName": "AuthPolicy", + "attributes": { + "name": "CUD_INCIDENT", + "qualifiedName": "CUD_INCIDENT", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": [], + "policyGroups": [], + "policyRoles": [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity-type:Incident", + "entity-classification:*", + "entity:*" + ], + "policyActions": [ + "entity-create", + "entity-update", + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": { + "name": "READ_INCIDENT" , + "qualifiedName": "READ_INCIDENT", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": [], + "policyGroups": [], + "policyRoles": [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity-type:Incident", + "entity-classification:*", + "entity:*" + ], + "policyActions": [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": { + "name": "CRUD_BUSINESS_POLICY_LOG", + "qualifiedName": "CRUD_BUSINESS_POLICY_LOG", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": [], + "policyGroups": [], + "policyRoles": [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity-type:BusinessPolicyLog", + "entity-classification:*", + "entity:*" + ], + "policyActions": [ + "entity-create", + "entity-read", + "entity-update", + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": { + "name": "CRUD_TASK", + "qualifiedName": "CRUD_TASK", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": [], + "policyGroups": [], + "policyRoles": [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity-type:Task", + "entity-classification:*", + "entity:*" + ], + "policyActions": [ + "entity-create", + "entity-read", + "entity-update", + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "AI_CLASSIFICATION", + "qualifiedName": "AI_CLASSIFICATION", + "description": "Allows tagging AI assets", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AIApplication", + "entity-type:AIModel", + "entity-classification:*", + "entity:*", + "classification:*" + ], + "policyActions": + [ + "entity-add-classification", + "entity-update-classification", + "entity-remove-classification" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "READ_AI_APPLICATION_ENTITIES", + "qualifiedName": "READ_AI_APPLICATION_ENTITIES", + "description": "Allows user to perform read operation on AI application assets", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$member", + "$guest" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AIApplication", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "READ_AI_MODEL_ENTITIES", + "qualifiedName": "READ_AI_MODEL_ENTITIES", + "description": "Allows user to perform read operation on AI model assets", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$member", + "$guest" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity-type:AIModel", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CRUD_AI_MODEL_ENTITY", + "qualifiedName": "CRUD_AI_MODEL_ENTITY", + "description": "Allows user to perform crud operation on AIModel assets.", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "isPolicyEnabled": true, + "policyResources": + [ + "entity-type:AIModel", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create", + "entity-update", + "entity-delete", + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CRUD_AI_APPLICATION_ENTITY", + "qualifiedName": "CRUD_AI_APPLICATION_ENTITY", + "description": "Allows user to perform crud operation on AIApplication assets.", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "isPolicyEnabled": true, + "policyResources": + [ + "entity-type:AIApplication", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create", + "entity-update", + "entity-delete", + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "BM_UPDATE_AI_ASSETS", + "qualifiedName": "BM_UPDATE_AI_ASSETS", + "description": "Allows user to update AI assets business metadata.", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "isPolicyEnabled": true, + "policyResources": + [ + "entity-type:AIApplication", + "entity-type:AIModel", + "entity-classification:*", + "entity:*", + "entity-business-metadata:*" + ], + "policyActions": + [ + "entity-update-business-metadata" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "READ_STAKEHOLDER_ENTITIES", + "qualifiedName": "READ_STAKEHOLDER_ENTITIES", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity:*", + "entity-type:Stakeholder", + "entity-classification:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "READ_FORMS", + "qualifiedName": "READ_FORM_ENTITIES", + "description": "Allows user to perform read operation on Form assets.", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$guest", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "isPolicyEnabled": true, + "policyResources": + [ + "entity-type:Form", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CUD_FORMS", + "qualifiedName": "CUD_FORM_ENTITIES", + "description": "Allows user to perform cud operation on Form assets.", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "isPolicyEnabled": true, + "policyResources": + [ + "entity-type:Form", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create", + "entity-update", + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CR_RESPONSES", + "qualifiedName": "CR_RESPONSE_ENTITIES", + "description": "Allows all users to perform cr operation on Response assets.", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$guest", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "isPolicyEnabled": true, + "policyResources": + [ + "entity-type:Response", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-create", + "entity-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "UD_RESPONSES", + "qualifiedName": "UD_RESPONSE_ENTITIES", + "description": "Allows admins and api tokens to perform ud operation on Response assets.", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "isPolicyEnabled": true, + "policyResources": + [ + "entity-type:Response", + "entity-classification:*", + "entity:*" + ], + "policyActions": + [ + "entity-update", + "entity-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "ENTITY_BUSINESS_UPDATE_METADATA_BOOT", + "qualifiedName": "ENTITY_BUSINESS_UPDATE_METADATA_BOOT", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity:*", + "entity-type:DataDomain", + "entity-type:DataProduct", + "entity-classification:*", + "entity-business-metadata:*" + ], + "policyActions": + [ + "entity-update-business-metadata" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": { + "name": "READ_DQ_RULE_TEMPLATE" , + "qualifiedName": "READ_DQ_RULE_TEMPLATE", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": [], + "policyGroups": [], + "policyRoles": [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity-type:DataQualityTemplate", + "entity-classification:*", + "entity:*" + ], + "policyActions": [ + "entity-read" + ] + } + } + ] +} diff --git a/addons/policies/bootstrap_heka_policies.json b/addons/policies/bootstrap_heka_policies.json new file mode 100644 index 00000000000..4a9aeb39356 --- /dev/null +++ b/addons/policies/bootstrap_heka_policies.json @@ -0,0 +1,36 @@ +{ + "entities": + [ + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "DENY_DATA_ACCESS_GUEST", + "qualifiedName": "DENY_DATA_ACCESS_GUEST", + "description": "deny data access for guest users", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "heka", + "policyType": "deny", + "policyPriority": 1, + "isPolicyEnabled": false, + "policyUsers": [], + "policyGroups": [], + "policyRoles": + [ + "$guest" + ], + "policyResourceCategory": "ENTITY", + "policyResources": + [ + "entity:*", + "entity-type:*" + ], + "policyActions": + [ + "select" + ] + } + } + ] +} diff --git a/addons/policies/bootstrap_relationship_policies.json b/addons/policies/bootstrap_relationship_policies.json new file mode 100644 index 00000000000..464e6d6e34c --- /dev/null +++ b/addons/policies/bootstrap_relationship_policies.json @@ -0,0 +1,1077 @@ +{ + "entities": + [ + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_GLOSSARY_TERM", + "qualifiedName": "LINK_GLOSSARY_TERM", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:AtlasGlossary", + "end-two-entity-type:AtlasGlossaryTerm", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_GLOSSARY_TERM_CATEGORY", + "qualifiedName": "LINK_GLOSSARY_TERM_CATEGORY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:AtlasGlossaryCategory", + "end-two-entity-type:AtlasGlossaryTerm", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_GLOSSARY_CATEGORY", + "qualifiedName": "LINK_GLOSSARY_CATEGORY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:AtlasGlossary", + "end-two-entity-type:AtlasGlossaryCategory", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_FOLDERS_USER", + "qualifiedName": "LINK_FOLDERS_USER", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "{USER}" + ], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:{USER}", + "end-one-entity:*/{USER}/*", + "end-two-entity:{USER}", + "end-two-entity:*/{USER}/*", + "end-one-entity-type:QueryFolder", + "end-one-entity-type:QueryFolderParent", + "end-two-entity-type:QueryFolder", + "end-two-entity-type:QueryFolderChild", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_CATEGORY_GLOSSARY", + "qualifiedName": "LINK_CATEGORY_GLOSSARY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:AtlasGlossaryCategory", + "end-two-entity-type:AtlasGlossaryCategory", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_FOLDERS", + "qualifiedName": "LINK_FOLDERS", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "{USER}" + ], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:QueryFolder", + "end-one-entity-type:QueryFolderParent", + "end-one-entity-type:QueryFolderChild", + "end-one-entity-type:QueryFolderNamespace", + "end-two-entity-type:QueryFolder", + "end-two-entity-type:QueryFolderParent", + "end-two-entity-type:QueryFolderChild", + "end-two-entity-type:Query", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_GLOSSARY_ASSET", + "qualifiedName": "LINK_GLOSSARY_ASSET", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:AtlasGlossary", + "end-two-entity-type:*", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_TERM_ASSET", + "qualifiedName": "LINK_TERM_ASSET", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:AtlasGlossaryTerm", + "end-two-entity-type:*", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_CATEGORY_ASSET", + "qualifiedName": "LINK_CATEGORY_ASSET", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:AtlasGlossaryCategory", + "end-two-entity-type:*", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_PROCESS_ASSET", + "qualifiedName": "LINK_PROCESS_ASSET", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:Process", + "end-two-entity-type:Catalog", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_PROCESSES", + "qualifiedName": "LINK_PROCESSES", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:Process", + "end-two-entity-type:Process", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "RELATIONSHIP_CRUD", + "qualifiedName": "RELATIONSHIP_CRUD", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "admin", + "service-account-atlan-argo", + "service-account-atlan-backend" + ], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:*", + "end-two-entity-type:*", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_COLLECTION_ASSET", + "qualifiedName": "LINK_COLLECTION_ASSET", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "description": "Policy for link assets to collection", + "policyUsers": + [ + "{USER}", + "admin", + "service-account-atlan-argo", + "service-account-atlan-backend" + ], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*/{USER}/*", + "end-two-entity:*", + "end-one-entity-type:*", + "end-two-entity-type:Catalog", + "end-two-entity-type:Connection", + "end-two-entity-type:Dataset", + "end-two-entity-type:Infrastructure", + "end-two-entity-type:Process", + "end-two-entity-type:ProcessExecution", + "end-two-entity-type:Namespace", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 121 + }, + "attributes": + { + "name": "LINK_ACCESS_CONTROL_POLICY", + "qualifiedName": "LINK_ACCESS_CONTROL_POLICY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:AccessControl", + "end-two-entity-type:AuthPolicy", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 122 + }, + "attributes": + { + "name": "LINK_ACCESS_CONTROL_RESOURCE", + "qualifiedName": "LINK_ACCESS_CONTROL_RESOURCE", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:AccessControl", + "end-two-entity-type:Readme", + "end-two-entity-type:Link", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CUD_RELATIONSHIP_DENY_GUEST", + "qualifiedName": "CUD_RELATIONSHIP_DENY_GUEST", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "deny", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$guest" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:*", + "end-two-entity-type:*", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_MESH_DATA_DOMAIN_TO_DATA_PRODUCT", + "qualifiedName": "LINK_MESH_DATA_DOMAIN_TO_DATA_PRODUCT", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:DataDomain", + "end-two-entity-type:DataProduct", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_MESH_DATA_DOMAIN_TO_DATA_DOMAIN", + "qualifiedName": "LINK_MESH_DATA_DOMAIN_TO_DATA_DOMAIN", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:DataDomain", + "end-two-entity-type:DataDomain", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_RESOURCES_TO_DATA_MESH", + "qualifiedName": "LINK_RESOURCES_TO_DATA_MESH", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:DataDomain", + "end-one-entity-type:DataProduct", + "end-two-entity-type:Readme", + "end-two-entity-type:Link", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_BUSINESS_POLICY_BUSINESS_POLICY", + "qualifiedName": "LINK_BUSINESS_POLICY_BUSINESS_POLICY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:BusinessPolicy", + "end-two-entity-type:BusinessPolicy", + "relationship-type:RelatedBusinessPolicy" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_BUSINESS_POLICY_BUSINESS_POLICY_EXCEPTION", + "qualifiedName": "LINK_BUSINESS_POLICY_BUSINESS_POLICY_EXCEPTION", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:BusinessPolicy", + "end-two-entity-type:BusinessPolicyException", + "relationship-type:BusinessPolicy_BusinessPolicyException" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_ASSETS_USER_DEFINED_RELATIONSHIP", + "qualifiedName": "LINK_ASSETS_USER_DEFINED_RELATIONSHIP", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "relationship-type:UserDefRelationship", + "end-one-entity-type:Referenceable", + "end-two-entity-type:Referenceable", + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_BUSINESS_POLICY_RESOURCE_POLICY", + "qualifiedName": "LINK_BUSINESS_POLICY_RESOURCE_POLICY", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:BusinessPolicy", + "end-two-entity-type:Link", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_AI_MODEL_TO_AI_APPLICATION", + "qualifiedName": "LINK_AI_MODEL_TO_AI_APPLICATION", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:AIModel", + "end-two-entity-type:AIApplication", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_MESH_DATA_DOMAIN_AND_STAKEHOLDER_TITLE_TO_STAKE_HOLDER", + "qualifiedName": "LINK_MESH_DATA_DOMAIN_AND_STAKEHOLDER_TITLE_TO_STAKE_HOLDER", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "relationship-type:*", + "end-one-entity-type:StakeholderTitle", + "end-one-entity-type:DataDomain", + "end-one-entity-classification:*", + "end-one-entity:*", + "end-two-entity-type:Stakeholder", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_ASSET_TO_MESH_DATA_PRODUCT", + "qualifiedName": "LINK_ASSET_TO_MESH_DATA_PRODUCT", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "relationship-type:*", + "end-one-entity-type:Asset", + "end-one-entity-classification:*", + "end-one-entity:*", + "end-two-entity-type:DataProduct", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "LINK_RESOURCES_TO_AI_APP_MODELS", + "qualifiedName": "LINK_RESOURCES_TO_AI_APP_MODELS", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": + [ + "end-one-entity-classification:*", + "end-two-entity-classification:*", + "end-one-entity:*", + "end-two-entity:*", + "end-one-entity-type:AIApplication", + "end-one-entity-type:AIModel", + "end-two-entity-type:Readme", + "end-two-entity-type:Link", + "relationship-type:*" + ], + "policyActions": + [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + } + } + ] +} \ No newline at end of file diff --git a/addons/policies/bootstrap_typedef_policies.json b/addons/policies/bootstrap_typedef_policies.json new file mode 100644 index 00000000000..092c91a4de5 --- /dev/null +++ b/addons/policies/bootstrap_typedef_policies.json @@ -0,0 +1,632 @@ +{ + "entities": + [ + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 1 + }, + "attributes": + { + "name": "CREATE_CLASSIFICATION", + "qualifiedName": "CREATE_CLASSIFICATION", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:classification", + "type:*" + ], + "policyActions": + [ + "type-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 1 + }, + "attributes": + { + "name": "READ_CLASSIFICATION", + "qualifiedName": "READ_CLASSIFICATION", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:classification", + "type:*" + ], + "policyActions": + [ + "type-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 1 + }, + "attributes": + { + "name": "UPDATE_CLASSIFICATION", + "qualifiedName": "UPDATE_CLASSIFICATION", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:classification", + "type:*" + ], + "policyActions": + [ + "type-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 1 + }, + "attributes": + { + "name": "DELETE_CLASSIFICATION", + "qualifiedName": "DELETE_CLASSIFICATION", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:classification", + "type:*" + ], + "policyActions": + [ + "type-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 2 + }, + "attributes": + { + "name": "CREATE_BUSINESS_METADATA", + "qualifiedName": "CREATE_BUSINESS_METADATA", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:business_metadata", + "type:*" + ], + "policyActions": + [ + "type-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 2 + }, + "attributes": + { + "name": "READ_BUSINESS_METADATA", + "qualifiedName": "READ_BUSINESS_METADATA", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:business_metadata", + "type:*" + ], + "policyActions": + [ + "type-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 2 + }, + "attributes": + { + "name": "UPDATE_BUSINESS_METADATA", + "qualifiedName": "UPDATE_BUSINESS_METADATA", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:business_metadata", + "type:*" + ], + "policyActions": + [ + "type-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 2 + }, + "attributes": + { + "name": "DELETE_BUSINESS_METADATA", + "qualifiedName": "DELETE_BUSINESS_METADATA", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:business_metadata", + "type:*" + ], + "policyActions": + [ + "type-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 3 + }, + "attributes": + { + "name": "CREATE_ENUM", + "qualifiedName": "CREATE_ENUM", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:enum", + "type:*" + ], + "policyActions": + [ + "type-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 3 + }, + "attributes": + { + "name": "READ_ENUM", + "qualifiedName": "READ_ENUM", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:enum", + "type:*" + ], + "policyActions": + [ + "type-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 3 + }, + "attributes": + { + "name": "UPDATE_ENUM", + "qualifiedName": "UPDATE_ENUM", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:enum", + "type:*" + ], + "policyActions": + [ + "type-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 3 + }, + "attributes": + { + "name": "DELETE_ENUM", + "qualifiedName": "DELETE_ENUM", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$api-token-default-access" + ], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:enum", + "type:*" + ], + "policyActions": + [ + "type-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 4 + }, + "attributes": + { + "name": "CREATE_TYPEDEF", + "qualifiedName": "CREATE_TYPEDEF", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:*", + "type:*" + ], + "policyActions": + [ + "type-create" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 4 + }, + "attributes": + { + "name": "READ_TYPEDEF", + "qualifiedName": "READ_TYPEDEF", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [ + "admin", + "public" + ], + "policyGroups": + [], + "policyRoles": + [ + "$admin", + "$guest", + "$member", + "$api-token-default-access" + ], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:*", + "type:*" + ], + "policyActions": + [ + "type-read" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 4 + }, + "attributes": + { + "name": "UPDATE_TYPEDEF", + "qualifiedName": "UPDATE_TYPEDEF", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:*", + "type:*" + ], + "policyActions": + [ + "type-update" + ] + } + }, + { + "typeName": "AuthPolicy", + "customAttributes": { + "internalId": 4 + }, + "attributes": + { + "name": "DELETE_TYPEDEF", + "qualifiedName": "DELETE_TYPEDEF", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyPriority": 1, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:*", + "type:*" + ], + "policyActions": + [ + "type-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CRUD_TYPEDEF", + "qualifiedName": "CRUD_TYPEDEF", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "allow", + "policyUsers": + [ + "admin", + "service-account-atlan-argo", + "service-account-atlan-backend" + ], + "policyGroups": + [], + "policyRoles": + [], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:*", + "type:*" + ], + "policyActions": + [ + "type-create", + "type-read", + "type-update", + "type-delete" + ] + } + }, + { + "typeName": "AuthPolicy", + "attributes": + { + "name": "CUD_TYPEDEF_DENY_GUEST", + "qualifiedName": "CUD_TYPEDEF_DENY_GUEST", + "policyCategory": "bootstrap", + "policySubCategory": "default", + "policyServiceName": "atlas", + "policyType": "deny", + "policyPriority": 0, + "policyUsers": + [], + "policyGroups": + [], + "policyRoles": + [ + "$guest" + ], + "policyResourceCategory": "TYPEDEFS", + "policyResources": + [ + "type-category:*", + "type:*" + ], + "policyActions": + [ + "type-create", + "type-update", + "type-delete" + ] + } + } + ] +} \ No newline at end of file diff --git a/addons/policies/global_stakeholder-titles.json b/addons/policies/global_stakeholder-titles.json new file mode 100644 index 00000000000..a32088f11eb --- /dev/null +++ b/addons/policies/global_stakeholder-titles.json @@ -0,0 +1,41 @@ +{ + "entities": [ + { + "typeName": "StakeholderTitle", + "attributes": + { + "qualifiedName": "stakeholderTitle/default/DOMAIN_OWNER", + "name": "Domain Owner", + "stakeholderTitleDomainQualifiedNames": ["*/super"] + } + }, + { + "typeName": "StakeholderTitle", + "attributes": + { + "qualifiedName": "stakeholderTitle/default/DATA_PRODUCT_OWNER", + "name": "Data Product Owner", + "stakeholderTitleDomainQualifiedNames": ["*/super"] + } + }, + { + "typeName": "StakeholderTitle", + "attributes": + { + "qualifiedName": "stakeholderTitle/default/DATA_ENGINEER", + "name": "Data Engineer", + "stakeholderTitleDomainQualifiedNames": ["*/super"] + } + }, + { + "typeName": "StakeholderTitle", + "attributes": + { + "qualifiedName": "stakeholderTitle/default/ARCHITECT", + "name": "Architect", + "stakeholderTitleDomainQualifiedNames": ["*/super"] + } + } + ] +} + diff --git a/addons/sqoop-bridge-shim/pom.xml b/addons/sqoop-bridge-shim/pom.xml deleted file mode 100755 index 533a1f1a8c9..00000000000 --- a/addons/sqoop-bridge-shim/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - sqoop-bridge-shim - Apache Atlas Sqoop Bridge Shim Module - Apache Atlas Sqoop Bridge Shim - jar - - - - - org.apache.atlas - atlas-plugin-classloader - - - - org.apache.sqoop - sqoop - ${sqoop.version} - compile - - - diff --git a/addons/sqoop-bridge-shim/src/main/java/org/apache/atlas/sqoop/hook/SqoopHook.java b/addons/sqoop-bridge-shim/src/main/java/org/apache/atlas/sqoop/hook/SqoopHook.java deleted file mode 100644 index 08b858728e8..00000000000 --- a/addons/sqoop-bridge-shim/src/main/java/org/apache/atlas/sqoop/hook/SqoopHook.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.sqoop.hook; - - -import org.apache.atlas.plugin.classloader.AtlasPluginClassLoader; -import org.apache.sqoop.SqoopJobDataPublisher; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Sqoop hook used for atlas entity registration. - */ -public class SqoopHook extends SqoopJobDataPublisher { - private static final Logger LOG = LoggerFactory.getLogger(SqoopHook.class); - - private static final String ATLAS_PLUGIN_TYPE = "sqoop"; - private static final String ATLAS_SQOOP_HOOK_IMPL_CLASSNAME = "org.apache.atlas.sqoop.hook.SqoopHook"; - - private AtlasPluginClassLoader atlasPluginClassLoader = null; - private SqoopJobDataPublisher sqoopHookImpl = null; - - public SqoopHook() { - this.initialize(); - } - - @Override - public void publish(SqoopJobDataPublisher.Data data) throws Exception { - if (LOG.isDebugEnabled()) { - LOG.debug("==> SqoopHook.run({})", data); - } - - try { - activatePluginClassLoader(); - sqoopHookImpl.publish(data); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== SqoopHook.run({})", data); - } - } - - private void initialize() { - if (LOG.isDebugEnabled()) { - LOG.debug("==> HiveHook.initialize()"); - } - - try { - atlasPluginClassLoader = AtlasPluginClassLoader.getInstance(ATLAS_PLUGIN_TYPE, this.getClass()); - - @SuppressWarnings("unchecked") - Class cls = (Class) Class - .forName(ATLAS_SQOOP_HOOK_IMPL_CLASSNAME, true, atlasPluginClassLoader); - - activatePluginClassLoader(); - - sqoopHookImpl = cls.newInstance(); - } catch (Exception excp) { - LOG.error("Error instantiating Atlas hook implementation", excp); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== HiveHook.initialize()"); - } - } - - private void activatePluginClassLoader() { - if (atlasPluginClassLoader != null) { - atlasPluginClassLoader.activate(); - } - } - - private void deactivatePluginClassLoader() { - if (atlasPluginClassLoader != null) { - atlasPluginClassLoader.deactivate(); - } - } -} diff --git a/addons/sqoop-bridge/pom.xml b/addons/sqoop-bridge/pom.xml deleted file mode 100644 index 021e93f56d3..00000000000 --- a/addons/sqoop-bridge/pom.xml +++ /dev/null @@ -1,472 +0,0 @@ - - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - sqoop-bridge - Apache Atlas Sqoop Bridge Module - Apache Atlas Sqoop Bridge - jar - - - - - org.slf4j - slf4j-api - - - - org.slf4j - slf4j-log4j12 - - - - org.apache.hive - hive-metastore - ${hive.version} - provided - - - org.mortbay.jetty - * - - - com.github.stephenc.findbugs - findbugs-annotations - - - - - - - org.apache.hive - hive-exec - ${hive.version} - provided - - - - org.apache.hive - hive-cli - ${hive.version} - test - - - javax.servlet - * - - - javax.ws.rs - * - - - org.eclipse.jetty.aggregate - * - - - javax.servlet - servlet-api - - - - - - - org.apache.sqoop - sqoop - ${sqoop.version} - compile - - - - org.apache.atlas - atlas-client-v1 - - - - org.apache.atlas - atlas-notification - - - - org.apache.atlas - hive-bridge - - - - org.apache.hive - hive-common - ${hive.version} - - - - - org.apache.atlas - atlas-webapp - war - test - - - - org.apache.hadoop - hadoop-client - - - javax.servlet - servlet-api - - - - - - org.apache.hadoop - hadoop-annotations - - - - org.testng - testng - - - - org.eclipse.jetty - jetty-server - test - - - - org.apache.atlas - atlas-graphdb-impls - pom - test - - - - - - dist - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-hook - package - - copy - - - ${project.build.directory}/dependency/hook/sqoop/atlas-sqoop-plugin-impl - false - false - true - - - ${project.groupId} - ${project.artifactId} - ${project.version} - - - ${project.groupId} - ${project.artifactId} - ${project.version} - - - ${project.groupId} - hive-bridge - ${project.version} - - - ${project.groupId} - atlas-client-common - ${project.version} - - - ${project.groupId} - atlas-client-v1 - ${project.version} - - - ${project.groupId} - atlas-client-v2 - ${project.version} - - - ${project.groupId} - atlas-intg - ${project.version} - - - ${project.groupId} - atlas-notification - ${project.version} - - - ${project.groupId} - atlas-common - ${project.version} - - - org.apache.kafka - kafka_${kafka.scala.binary.version} - ${kafka.version} - - - org.apache.kafka - kafka-clients - ${kafka.version} - - - com.sun.jersey - jersey-json - ${jersey.version} - - - javax.ws.rs - jsr311-api - ${jsr.version} - - - - - - copy-hook-shim - package - - copy - - - ${project.build.directory}/dependency/hook/sqoop - false - false - true - - - ${project.groupId} - sqoop-bridge-shim - ${project.version} - - - ${project.groupId} - atlas-plugin-classloader - ${project.version} - - - - - - - - - - - - - - org.eclipse.jetty - jetty-maven-plugin - ${jetty.version} - - ${skipTests} - - - 31000 - 60000 - - ../../webapp/target/atlas-webapp-${project.version}.war - true - - / - ${project.basedir}/../../webapp/src/test/webapp/WEB-INF/web.xml - - true - - true - - atlas.home - ${project.build.directory} - - - atlas.conf - ${project.build.directory}/test-classes - - - atlas.data - ${project.build.directory}/data - - - atlas.log.dir - ${project.build.directory}/logs - - - atlas.log.file - application.log - - - log4j.configuration - file:///${project.build.directory}/test-classes/atlas-log4j.xml - - - atlas.graphdb.backend - ${graphdb.backend.impl} - - - embedded.solr.directory - ${project.build.directory} - - - solr.log.dir - ${project.build.directory}/logs - - - org.eclipse.jetty.annotations.maxWait - 5000 - - - atlas-stop - 31001 - ${jetty-maven-plugin.stopWait} - jar - - - - org.apache.curator - curator-client - ${curator.version} - - - - org.apache.zookeeper - zookeeper - ${zookeeper.version} - - - - - start-jetty - pre-integration-test - - - stop - deploy-war - - - true - - - - stop-jetty - post-integration-test - - stop - - - - - - - org.apache.maven.plugins - maven-site-plugin - - - org.apache.maven.doxia - doxia-module-twiki - ${doxia.version} - - - org.apache.maven.doxia - doxia-core - ${doxia.version} - - - - - - site - - prepare-package - - - - false - false - - - - - org.codehaus.mojo - exec-maven-plugin - 1.2.1 - false - - - - - - org.apache.maven.plugins - maven-resources-plugin - - - copy-resources - validate - - copy-resources - - - ${basedir}/target/models - - - ${basedir}/../models - - 0000-Area0/0010-base_model.json - 1000-Hadoop/** - - - - - - - copy-solr-resources - validate - - copy-resources - - - ${project.build.directory}/solr - - - ${basedir}/../../test-tools/src/main/resources/solr - - - - - - - - - - diff --git a/addons/sqoop-bridge/src/main/java/org/apache/atlas/sqoop/hook/SqoopHook.java b/addons/sqoop-bridge/src/main/java/org/apache/atlas/sqoop/hook/SqoopHook.java deleted file mode 100644 index 0a8cb966751..00000000000 --- a/addons/sqoop-bridge/src/main/java/org/apache/atlas/sqoop/hook/SqoopHook.java +++ /dev/null @@ -1,258 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.sqoop.hook; - - -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasClient; -import org.apache.atlas.AtlasConstants; -import org.apache.atlas.hive.bridge.HiveMetaStoreBridge; -import org.apache.atlas.hive.model.HiveDataTypes; -import org.apache.atlas.hook.AtlasHook; -import org.apache.atlas.hook.AtlasHookException; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.model.notification.HookNotification.EntityCreateRequestV2; -import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.sqoop.model.SqoopDataTypes; -import org.apache.atlas.type.AtlasTypeUtil; -import org.apache.atlas.utils.AtlasConfigurationUtil; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.lang3.StringUtils; -import org.apache.sqoop.SqoopJobDataPublisher; -import org.apache.sqoop.util.ImportException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.Map; -import java.util.HashMap; -import java.util.Properties; -import java.util.List; -import java.util.Date; - -import static org.apache.atlas.repository.Constants.SQOOP_SOURCE; - -/** - * AtlasHook sends lineage information to the AtlasSever. - */ -public class SqoopHook extends SqoopJobDataPublisher { - private static final Logger LOG = LoggerFactory.getLogger(SqoopHook.class); - - public static final String CLUSTER_NAME_KEY = "atlas.cluster.name"; - public static final String ATLAS_METADATA_NAMESPACE = "atlas.metadata.namespace"; - public static final String DEFAULT_CLUSTER_NAME = "primary"; - - public static final String USER = "userName"; - public static final String DB_STORE_TYPE = "dbStoreType"; - public static final String DB_STORE_USAGE = "storeUse"; - public static final String SOURCE = "source"; - public static final String DESCRIPTION = "description"; - public static final String STORE_URI = "storeUri"; - public static final String OPERATION = "operation"; - public static final String START_TIME = "startTime"; - public static final String END_TIME = "endTime"; - public static final String CMD_LINE_OPTS = "commandlineOpts"; - public static final String INPUTS = "inputs"; - public static final String OUTPUTS = "outputs"; - public static final String ATTRIBUTE_DB = "db"; - - public static final String RELATIONSHIP_HIVE_TABLE_DB = "hive_table_db"; - public static final String RELATIONSHIP_DATASET_PROCESS_INPUTS = "dataset_process_inputs"; - public static final String RELATIONSHIP_PROCESS_DATASET_OUTPUTS = "process_dataset_outputs"; - - private static final AtlasHookImpl atlasHook; - - static { - org.apache.hadoop.conf.Configuration.addDefaultResource("sqoop-site.xml"); - - atlasHook = new AtlasHookImpl(); - } - - @Override - public void publish(SqoopJobDataPublisher.Data data) throws AtlasHookException { - try { - Configuration atlasProperties = ApplicationProperties.get(); - String metadataNamespace = - AtlasConfigurationUtil.getRecentString(atlasProperties, ATLAS_METADATA_NAMESPACE, getClusterName(atlasProperties)); - - AtlasEntity entDbStore = toSqoopDBStoreEntity(data); - AtlasEntity entHiveDb = toHiveDatabaseEntity(metadataNamespace, data.getHiveDB()); - AtlasEntity entHiveTable = data.getHiveTable() != null ? toHiveTableEntity(entHiveDb, data.getHiveTable()) : null; - AtlasEntity entProcess = toSqoopProcessEntity(entDbStore, entHiveDb, entHiveTable, data, metadataNamespace); - - - AtlasEntitiesWithExtInfo entities = new AtlasEntitiesWithExtInfo(entProcess); - - entities.addReferredEntity(entDbStore); - entities.addReferredEntity(entHiveDb); - if (entHiveTable != null) { - entities.addReferredEntity(entHiveTable); - } - - HookNotification message = new EntityCreateRequestV2(AtlasHook.getUser(), entities); - - atlasHook.sendNotification(message); - } catch(Exception e) { - LOG.error("SqoopHook.publish() failed", e); - - throw new AtlasHookException("SqoopHook.publish() failed.", e); - } - } - - private String getClusterName(Configuration config) { - return config.getString(CLUSTER_NAME_KEY, DEFAULT_CLUSTER_NAME); - } - - private AtlasEntity toHiveDatabaseEntity(String metadataNamespace, String dbName) { - AtlasEntity entHiveDb = new AtlasEntity(HiveDataTypes.HIVE_DB.getName()); - String qualifiedName = HiveMetaStoreBridge.getDBQualifiedName(metadataNamespace, dbName); - - entHiveDb.setAttribute(AtlasConstants.CLUSTER_NAME_ATTRIBUTE, metadataNamespace); - entHiveDb.setAttribute(AtlasClient.NAME, dbName); - entHiveDb.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, qualifiedName); - - return entHiveDb; - } - - private AtlasEntity toHiveTableEntity(AtlasEntity entHiveDb, String tableName) { - AtlasEntity entHiveTable = new AtlasEntity(HiveDataTypes.HIVE_TABLE.getName()); - String qualifiedName = HiveMetaStoreBridge.getTableQualifiedName((String)entHiveDb.getAttribute(AtlasConstants.CLUSTER_NAME_ATTRIBUTE), (String)entHiveDb.getAttribute(AtlasClient.NAME), tableName); - - entHiveTable.setAttribute(AtlasClient.NAME, tableName.toLowerCase()); - entHiveTable.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, qualifiedName); - entHiveTable.setRelationshipAttribute(ATTRIBUTE_DB, AtlasTypeUtil.getAtlasRelatedObjectId(entHiveDb, RELATIONSHIP_HIVE_TABLE_DB)); - - return entHiveTable; - } - - private AtlasEntity toSqoopDBStoreEntity(SqoopJobDataPublisher.Data data) throws ImportException { - String table = data.getStoreTable(); - String query = data.getStoreQuery(); - - if (StringUtils.isBlank(table) && StringUtils.isBlank(query)) { - throw new ImportException("Both table and query cannot be empty for DBStoreInstance"); - } - - String usage = table != null ? "TABLE" : "QUERY"; - String source = table != null ? table : query; - String name = getSqoopDBStoreName(data); - - AtlasEntity entDbStore = new AtlasEntity(SqoopDataTypes.SQOOP_DBDATASTORE.getName()); - - entDbStore.setAttribute(AtlasClient.NAME, name); - entDbStore.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, name); - entDbStore.setAttribute(SqoopHook.DB_STORE_TYPE, data.getStoreType()); - entDbStore.setAttribute(SqoopHook.DB_STORE_USAGE, usage); - entDbStore.setAttribute(SqoopHook.STORE_URI, data.getUrl()); - entDbStore.setAttribute(SqoopHook.SOURCE, source); - entDbStore.setAttribute(SqoopHook.DESCRIPTION, ""); - entDbStore.setAttribute(AtlasClient.OWNER, data.getUser()); - - return entDbStore; - } - - private AtlasEntity toSqoopProcessEntity(AtlasEntity entDbStore, AtlasEntity entHiveDb, AtlasEntity entHiveTable, - SqoopJobDataPublisher.Data data, String metadataNamespace) { - AtlasEntity entProcess = new AtlasEntity(SqoopDataTypes.SQOOP_PROCESS.getName()); - String sqoopProcessName = getSqoopProcessName(data, metadataNamespace); - Map sqoopOptionsMap = new HashMap<>(); - Properties options = data.getOptions(); - - for (Object k : options.keySet()) { - sqoopOptionsMap.put((String)k, (String) options.get(k)); - } - - entProcess.setAttribute(AtlasClient.NAME, sqoopProcessName); - entProcess.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, sqoopProcessName); - entProcess.setAttribute(SqoopHook.OPERATION, data.getOperation()); - - List sqoopObjects = Collections.singletonList(AtlasTypeUtil.getAtlasObjectId(entDbStore)); - List hiveObjects = Collections.singletonList(AtlasTypeUtil.getAtlasObjectId(entHiveTable != null ? entHiveTable : entHiveDb)); - - if (isImportOperation(data)) { - entProcess.setRelationshipAttribute(SqoopHook.INPUTS, AtlasTypeUtil.getAtlasRelatedObjectIdList(sqoopObjects, RELATIONSHIP_DATASET_PROCESS_INPUTS)); - entProcess.setRelationshipAttribute(SqoopHook.OUTPUTS, AtlasTypeUtil.getAtlasRelatedObjectIdList(hiveObjects, RELATIONSHIP_PROCESS_DATASET_OUTPUTS)); - } else { - entProcess.setRelationshipAttribute(SqoopHook.INPUTS, AtlasTypeUtil.getAtlasRelatedObjectIdList(hiveObjects, RELATIONSHIP_DATASET_PROCESS_INPUTS)); - entProcess.setRelationshipAttribute(SqoopHook.OUTPUTS, AtlasTypeUtil.getAtlasRelatedObjectIdList(sqoopObjects, RELATIONSHIP_PROCESS_DATASET_OUTPUTS)); - } - - entProcess.setAttribute(SqoopHook.USER, data.getUser()); - entProcess.setAttribute(SqoopHook.START_TIME, new Date(data.getStartTime())); - entProcess.setAttribute(SqoopHook.END_TIME, new Date(data.getEndTime())); - entProcess.setAttribute(SqoopHook.CMD_LINE_OPTS, sqoopOptionsMap); - - return entProcess; - } - - private boolean isImportOperation(SqoopJobDataPublisher.Data data) { - return data.getOperation().toLowerCase().equals("import"); - } - - static String getSqoopProcessName(Data data, String metadataNamespace) { - StringBuilder name = new StringBuilder(String.format("sqoop %s --connect %s", data.getOperation(), data.getUrl())); - - if (StringUtils.isNotEmpty(data.getHiveTable())) { - name.append(" --table ").append(data.getStoreTable()); - } else { - name.append(" --database ").append(data.getHiveDB()); - } - - if (StringUtils.isNotEmpty(data.getStoreQuery())) { - name.append(" --query ").append(data.getStoreQuery()); - } - - if (data.getHiveTable() != null) { - name.append(String.format(" --hive-%s --hive-database %s --hive-table %s --hive-cluster %s", data.getOperation(), data.getHiveDB().toLowerCase(), data.getHiveTable().toLowerCase(), metadataNamespace)); - } else { - name.append(String.format("--hive-%s --hive-database %s --hive-cluster %s", data.getOperation(), data.getHiveDB(), metadataNamespace)); - } - - return name.toString(); - } - - static String getSqoopDBStoreName(SqoopJobDataPublisher.Data data) { - StringBuilder name = new StringBuilder(String.format("%s --url %s", data.getStoreType(), data.getUrl())); - - if (StringUtils.isNotEmpty(data.getHiveTable())) { - name.append(" --table ").append(data.getStoreTable()); - } else { - name.append(" --database ").append(data.getHiveDB()); - } - - if (StringUtils.isNotEmpty(data.getStoreQuery())) { - name.append(" --query ").append(data.getStoreQuery()); - } - - return name.toString(); - } - - private static class AtlasHookImpl extends AtlasHook { - - public String getMessageSource() { - return SQOOP_SOURCE; - } - - public void sendNotification(HookNotification notification) { - super.notifyEntities(Collections.singletonList(notification), null); - } - } -} diff --git a/addons/sqoop-bridge/src/main/java/org/apache/atlas/sqoop/model/SqoopDataTypes.java b/addons/sqoop-bridge/src/main/java/org/apache/atlas/sqoop/model/SqoopDataTypes.java deleted file mode 100644 index e71220ab90f..00000000000 --- a/addons/sqoop-bridge/src/main/java/org/apache/atlas/sqoop/model/SqoopDataTypes.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.sqoop.model; - -/** - * Hive Data Types for model and bridge. - */ -public enum SqoopDataTypes { - - // Classes - SQOOP_DBDATASTORE, - SQOOP_PROCESS, - ; - - public String getName() { - return name().toLowerCase(); - } -} diff --git a/addons/sqoop-bridge/src/test/java/org/apache/atlas/sqoop/hook/SqoopHookIT.java b/addons/sqoop-bridge/src/test/java/org/apache/atlas/sqoop/hook/SqoopHookIT.java deleted file mode 100644 index 71a8779dba2..00000000000 --- a/addons/sqoop-bridge/src/test/java/org/apache/atlas/sqoop/hook/SqoopHookIT.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.sqoop.hook; - -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasClient; -import org.apache.atlas.hive.bridge.HiveMetaStoreBridge; -import org.apache.atlas.hive.model.HiveDataTypes; -import org.apache.atlas.sqoop.model.SqoopDataTypes; -import org.apache.atlas.utils.AuthenticationUtil; -import org.apache.atlas.utils.ParamChecker; -import org.apache.atlas.v1.model.instance.Referenceable; -import org.apache.commons.configuration.Configuration; -import org.apache.sqoop.SqoopJobDataPublisher; -import org.slf4j.Logger; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import java.util.Properties; - -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.fail; - -public class SqoopHookIT { - public static final Logger LOG = org.slf4j.LoggerFactory.getLogger(SqoopHookIT.class); - private static final String CLUSTER_NAME = "primary"; - public static final String DEFAULT_DB = "default"; - private static final int MAX_WAIT_TIME = 2000; - private AtlasClient atlasClient; - - @BeforeClass - public void setUp() throws Exception { - //Set-up sqoop session - Configuration configuration = ApplicationProperties.get(); - if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { - atlasClient = new AtlasClient(configuration.getStringArray(HiveMetaStoreBridge.ATLAS_ENDPOINT), new String[]{"admin", "admin"}); - } else { - atlasClient = new AtlasClient(configuration.getStringArray(HiveMetaStoreBridge.ATLAS_ENDPOINT)); - } - } - - @Test - public void testSqoopImport() throws Exception { - SqoopJobDataPublisher.Data d = new SqoopJobDataPublisher.Data("import", "jdbc:mysql:///localhost/db", - "mysqluser", "mysql", "myTable", null, "default", "hiveTable", new Properties(), - System.currentTimeMillis() - 100, System.currentTimeMillis()); - SqoopHook hook = new SqoopHook(); - hook.publish(d); - Thread.sleep(1000); - String storeName = SqoopHook.getSqoopDBStoreName(d); - assertDBStoreIsRegistered(storeName); - String name = SqoopHook.getSqoopProcessName(d, CLUSTER_NAME); - assertSqoopProcessIsRegistered(name); - assertHiveTableIsRegistered(DEFAULT_DB, "hiveTable"); - } - - @Test - public void testSqoopExport() throws Exception { - SqoopJobDataPublisher.Data d = new SqoopJobDataPublisher.Data("export", "jdbc:mysql:///localhost/db", - "mysqluser", "mysql", "myTable", null, "default", "hiveTable", new Properties(), - System.currentTimeMillis() - 100, System.currentTimeMillis()); - SqoopHook hook = new SqoopHook(); - hook.publish(d); - Thread.sleep(1000); - String storeName = SqoopHook.getSqoopDBStoreName(d); - assertDBStoreIsRegistered(storeName); - String name = SqoopHook.getSqoopProcessName(d, CLUSTER_NAME); - assertSqoopProcessIsRegistered(name); - assertHiveTableIsRegistered(DEFAULT_DB, "hiveTable"); - } - - private String assertDBStoreIsRegistered(String storeName) throws Exception { - LOG.debug("Searching for db store {}", storeName); - return assertEntityIsRegistered(SqoopDataTypes.SQOOP_DBDATASTORE.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, storeName, null); - } - - private String assertHiveTableIsRegistered(String dbName, String tableName) throws Exception { - LOG.debug("Searching for table {}.{}", dbName, tableName); - return assertEntityIsRegistered(HiveDataTypes.HIVE_TABLE.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, HiveMetaStoreBridge.getTableQualifiedName(CLUSTER_NAME, dbName, tableName), null); - } - - private String assertSqoopProcessIsRegistered(String processName) throws Exception { - LOG.debug("Searching for sqoop process {}", processName); - return assertEntityIsRegistered(SqoopDataTypes.SQOOP_PROCESS.getName(), AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, processName, null); - } - - protected String assertEntityIsRegistered(final String typeName, final String property, final String value, - final AssertPredicate assertPredicate) throws Exception { - waitFor(80000, new Predicate() { - @Override - public void evaluate() throws Exception { - Referenceable entity = atlasClient.getEntity(typeName, property, value); - assertNotNull(entity); - if (assertPredicate != null) { - assertPredicate.assertOnEntity(entity); - } - } - }); - Referenceable entity = atlasClient.getEntity(typeName, property, value); - return entity.getId()._getId(); - } - - public interface Predicate { - void evaluate() throws Exception; - } - - public interface AssertPredicate { - void assertOnEntity(Referenceable entity) throws Exception; - } - - protected void waitFor(int timeout, Predicate predicate) throws Exception { - ParamChecker.notNull(predicate, "predicate"); - long mustEnd = System.currentTimeMillis() + timeout; - - while (true) { - try { - predicate.evaluate(); - return; - } catch(Error | Exception e) { - if (System.currentTimeMillis() >= mustEnd) { - fail("Assertions failed. Failing after waiting for timeout " + timeout + " msecs", e); - } - LOG.debug("Waiting up to {} msec as assertion failed", mustEnd - System.currentTimeMillis(), e); - Thread.sleep(5000); - } - } - } -} diff --git a/addons/sqoop-bridge/src/test/resources/atlas-application.properties b/addons/sqoop-bridge/src/test/resources/atlas-application.properties deleted file mode 100644 index 898b69c999e..00000000000 --- a/addons/sqoop-bridge/src/test/resources/atlas-application.properties +++ /dev/null @@ -1,124 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# - -######### Atlas Server Configs ######### -atlas.rest.address=http://localhost:31000 - -######### Graph Database Configs ######### - - -# Graph database implementation. Value inserted by maven. -atlas.graphdb.backend=org.apache.atlas.repository.graphdb.janus.AtlasJanusGraphDatabase - -# Graph Storage -atlas.graph.storage.backend=berkeleyje - -# Entity repository implementation -atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.InMemoryEntityAuditRepository - -# Graph Search Index Backend -atlas.graph.index.search.backend=solr - -#Berkeley storage directory -atlas.graph.storage.directory=${sys:atlas.data}/berkley - -#hbase -#For standalone mode , specify localhost -#for distributed mode, specify zookeeper quorum here - -atlas.graph.storage.hostname=${graph.storage.hostname} -atlas.graph.storage.hbase.regions-per-server=1 -atlas.graph.storage.lock.wait-time=10000 - -#ElasticSearch -atlas.graph.index.search.directory=${sys:atlas.data}/es -atlas.graph.index.search.elasticsearch.client-only=false -atlas.graph.index.search.elasticsearch.local-mode=true -atlas.graph.index.search.elasticsearch.create.sleep=2000 - -# Solr cloud mode properties -atlas.graph.index.search.solr.mode=cloud -atlas.graph.index.search.solr.zookeeper-url=${solr.zk.address} -atlas.graph.index.search.solr.embedded=true -atlas.graph.index.search.max-result-set-size=150 - - -######### Notification Configs ######### -atlas.notification.embedded=true - -atlas.kafka.zookeeper.connect=localhost:19026 -atlas.kafka.bootstrap.servers=localhost:19027 -atlas.kafka.data=${sys:atlas.data}/kafka -atlas.kafka.zookeeper.session.timeout.ms=4000 -atlas.kafka.zookeeper.sync.time.ms=20 -atlas.kafka.consumer.timeout.ms=4000 -atlas.kafka.auto.commit.interval.ms=100 -atlas.kafka.hook.group.id=atlas -atlas.kafka.entities.group.id=atlas_entities -#atlas.kafka.auto.commit.enable=false - -atlas.kafka.enable.auto.commit=false -atlas.kafka.auto.offset.reset=earliest -atlas.kafka.session.timeout.ms=30000 -atlas.kafka.offsets.topic.replication.factor=1 - - - -######### Entity Audit Configs ######### -atlas.audit.hbase.tablename=ATLAS_ENTITY_AUDIT_EVENTS -atlas.audit.zookeeper.session.timeout.ms=1000 -atlas.audit.hbase.zookeeper.quorum=localhost -atlas.audit.hbase.zookeeper.property.clientPort=19026 - -######### Security Properties ######### - -# SSL config -atlas.enableTLS=false -atlas.server.https.port=31443 - -######### Security Properties ######### - -hbase.security.authentication=simple - -atlas.hook.falcon.synchronous=true - -######### JAAS Configuration ######## - -atlas.jaas.KafkaClient.loginModuleName = com.sun.security.auth.module.Krb5LoginModule -atlas.jaas.KafkaClient.loginModuleControlFlag = required -atlas.jaas.KafkaClient.option.useKeyTab = true -atlas.jaas.KafkaClient.option.storeKey = true -atlas.jaas.KafkaClient.option.serviceName = kafka -atlas.jaas.KafkaClient.option.keyTab = /etc/security/keytabs/atlas.service.keytab -atlas.jaas.KafkaClient.option.principal = atlas/_HOST@EXAMPLE.COM - -######### High Availability Configuration ######## -atlas.server.ha.enabled=false -#atlas.server.ids=id1 -#atlas.server.address.id1=localhost:21000 - -######### Atlas Authorization ######### -atlas.authorizer.impl=none -# atlas.authorizer.impl=simple -# atlas.authorizer.simple.authz.policy.file=atlas-simple-authz-policy.json - -######### Atlas Authentication ######### -atlas.authentication.method.file=true -atlas.authentication.method.ldap.type=none -atlas.authentication.method.kerberos=false -# atlas.authentication.method.file.filename=users-credentials.properties diff --git a/addons/sqoop-bridge/src/test/resources/atlas-log4j.xml b/addons/sqoop-bridge/src/test/resources/atlas-log4j.xml deleted file mode 100755 index 262a710f7aa..00000000000 --- a/addons/sqoop-bridge/src/test/resources/atlas-log4j.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/sqoop-bridge/src/test/resources/hive-site.xml b/addons/sqoop-bridge/src/test/resources/hive-site.xml deleted file mode 100644 index f058c2edc20..00000000000 --- a/addons/sqoop-bridge/src/test/resources/hive-site.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - hive.exec.post.hooks - org.apache.atlas.hive.hook.HiveHook - - - - hive.support.concurrency - false - - - - hive.metastore.warehouse.dir - ${user.dir}/target/metastore - - - - javax.jdo.option.ConnectionURL - jdbc:derby:${user.dir}/target/metastore_db;create=true - - - - atlas.hook.hive.synchronous - true - - - - fs.pfile.impl - org.apache.hadoop.fs.ProxyLocalFileSystem - - \ No newline at end of file diff --git a/addons/sqoop-bridge/src/test/resources/sqoop-site.xml b/addons/sqoop-bridge/src/test/resources/sqoop-site.xml deleted file mode 100644 index a63e7e4e8d9..00000000000 --- a/addons/sqoop-bridge/src/test/resources/sqoop-site.xml +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - atlas.rest.address - http://localhost:21000/ - - - - sqoop.job.data.publish.class - org.apache.atlas.sqoop.hook.SqoopHook - - - - atlas.cluster.name - primary - - diff --git a/addons/sqoop-bridge/src/test/resources/users-credentials.properties b/addons/sqoop-bridge/src/test/resources/users-credentials.properties deleted file mode 100644 index 5046dbaf646..00000000000 --- a/addons/sqoop-bridge/src/test/resources/users-credentials.properties +++ /dev/null @@ -1,3 +0,0 @@ -#username=group::sha256-password -admin=ADMIN::a4a88c0872bf652bb9ed803ece5fd6e82354838a9bf59ab4babb1dab322154e1 -rangertagsync=RANGER_TAG_SYNC::0afe7a1968b07d4c3ff4ed8c2d809a32ffea706c66cd795ead9048e81cfaf034 diff --git a/addons/static/templates/collection_bootstrap_policies.json b/addons/static/templates/collection_bootstrap_policies.json new file mode 100644 index 00000000000..d2e868a7c8a --- /dev/null +++ b/addons/static/templates/collection_bootstrap_policies.json @@ -0,0 +1,264 @@ +[ + { + "typeName": "AuthPolicy", + "guid": -1, + "attributes": { + "qualifiedName": "{guid}/collection-link-assets", + "name": "{name}-collection-link-assets", + "policyCategory": "bootstrap", + "policySubCategory": "collection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "collection_admins_{guid}" + ], + "policyActions": [ + "add-relationship", + "remove-relationship" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": [ + "end-one-entity-classification:*", + "end-one-entity:{entity}", + "end-one-entity:{entity}/*", + "end-one-entity-type:*", + + "end-two-entity-classification:*", + "end-two-entity:*", + "end-two-entity-type:Catalog", + "end-two-entity-type:collection", + "end-two-entity-type:Process", + "end-two-entity-type:ProcessExecution", + "end-two-entity-type:Namespace", + + "relationship-type:*" + ] + + } + }, + { + "typeName": "AuthPolicy", + "guid": -2, + "attributes": { + "qualifiedName": "{guid}/collection-add-terms", + "name": "{name}-collection-add-terms", + "policyCategory": "bootstrap", + "policySubCategory": "collection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "collection_admins_{guid}" + ], + "policyActions": [ + "add-relationship", + "remove-relationship" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": [ + "end-one-entity-classification:*", + "end-one-entity:*", + "end-one-entity-type:AtlasGlossaryTerm", + + "end-two-entity-classification:*", + "end-two-entity:{entity}", + "end-two-entity:{entity}/*", + "end-two-entity-type:*", + + "relationship-type:*" + ] + } + }, + { + "typeName": "AuthPolicy", + "guid": -3, + "attributes": { + "qualifiedName": "{guid}/collection-CRUD-admin", + "name": "{name}-collection-CRUD-admin", + "policyCategory": "bootstrap", + "policySubCategory": "collection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "collection_admins_{guid}" + ], + "policyActions": [ + "entity-read", + "entity-create", + "entity-update", + "entity-delete" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:*", + "entity-classification:*" + ] + } + }, + { + "typeName": "AuthPolicy", + "guid": -4, + "attributes": { + "qualifiedName": "{guid}/collection-CRUD-viewer", + "name": "{name}-collection-CRUD-viewer", + "policyCategory": "bootstrap", + "policySubCategory": "collection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "collection_viewer_{guid}" + ], + "policyActions": [ + "entity-read" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:*", + "entity-classification:*" + ] + } + }, + + { + "typeName": "AuthPolicy", + "guid": -5, + "attributes": { + "qualifiedName": "{guid}/collection-entity-business-metadata", + "name": "{name}-collection-entity-business-metadata", + "policyCategory": "bootstrap", + "policySubCategory": "collection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "collection_admins_{guid}" + ], + "policyActions": [ + "entity-update-business-metadata" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:*", + "entity-classification:*", + "entity-business-metadata:*" + ] + } + }, + { + "typeName": "AuthPolicy", + "guid": -6, + "attributes": { + "qualifiedName": "{guid}/collection-classification", + "name": "{name}-collection-classification", + "policyCategory": "bootstrap", + "policySubCategory": "collection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "collection_admins_{guid}" + ], + "policyActions": [ + "entity-add-classification", + "entity-remove-classification", + "entity-update-classification" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:*", + "entity-classification:*", + "classification:*" + ] + } + }, + { + "typeName": "AuthPolicy", + "guid": -7, + "attributes": { + "qualifiedName": "{guid}/collection-entity-label", + "name": "{name}-collection-entity-label", + "policyCategory": "bootstrap", + "policySubCategory": "collection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "collection_admins_{guid}" + ], + "policyActions": [ + "entity-add-label", + "entity-remove-label" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:*", + "entity-classification:*", + "entity-label:*" + ] + } + }, + { + "typeName": "AuthPolicy", + "guid": -8, + "attributes": { + "qualifiedName": "{guid}/collection-unlink-queries", + "name": "{name}-collection-unlink-queries", + "policyCategory": "bootstrap", + "policySubCategory": "collection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "collection_admins_{guid}" + ], + "policyActions": [ + "remove-relationship" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": [ + "end-one-entity-classification:*", + "end-one-entity:*", + "end-one-entity-type:*", + + "end-two-entity-classification:*", + "end-two-entity:{entity}", + "end-two-entity:{entity}/*", + "end-two-entity-type:*", + + "relationship-type:*" + ] + + } + }, + { + "typeName": "AuthPolicy", + "guid": -9, + "attributes": { + "qualifiedName": "{guid}/dataPolicy-collection", + "name": "{name}-dataPolicy-collection", + "policyCategory": "bootstrap", + "policySubCategory": "collection", + "policyType": "allow", + "policyServiceName": "heka", + "policyRoles": [ + "collection_admins_{guid}" + ], + "policyActions": [ + "select" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:*" + ] + } + } +] + + diff --git a/addons/static/templates/connection_bootstrap_policies.json b/addons/static/templates/connection_bootstrap_policies.json new file mode 100644 index 00000000000..4f0b8a448ce --- /dev/null +++ b/addons/static/templates/connection_bootstrap_policies.json @@ -0,0 +1,241 @@ +[ + { + "typeName": "AuthPolicy", + "guid": -1, + "attributes": { + "qualifiedName": "{guid}/connection-link-assets", + "name": "{name}-connection-link-assets", + "policyCategory": "bootstrap", + "policySubCategory": "connection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "connection_admins_{guid}" + ], + "policyActions": [ + "add-relationship", + "remove-relationship" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": [ + "end-one-entity-classification:*", + "end-one-entity:{entity}", + "end-one-entity:{entity}/*", + "end-one-entity-type:*", + + "end-two-entity-classification:*", + "end-two-entity:*", + "end-two-entity-type:Catalog", + "end-two-entity-type:Connection", + "end-two-entity-type:Process", + "end-two-entity-type:ProcessExecution", + "end-two-entity-type:Namespace", + + "relationship-type:*" + ] + + } + }, + { + "typeName": "AuthPolicy", + "guid": -8, + "attributes": { + "qualifiedName": "{guid}/connection-link-assets-inverse", + "name": "{name}-connection-link-assets-inverse", + "policyCategory": "bootstrap", + "policySubCategory": "connection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "connection_admins_{guid}" + ], + "policyActions": [ + "add-relationship", + "remove-relationship" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": [ + "end-one-entity-classification:*", + "end-one-entity:*", + "end-one-entity-type:Catalog", + "end-one-entity-type:Connection", + "end-one-entity-type:Process", + "end-one-entity-type:ProcessExecution", + "end-one-entity-type:Namespace", + + "end-two-entity-classification:*", + "end-two-entity:{entity}", + "end-two-entity:{entity}/*", + "end-two-entity-type:*", + + "relationship-type:*" + ] + } + }, + { + "typeName": "AuthPolicy", + "guid": -2, + "attributes": { + "qualifiedName": "{guid}/connection-add-terms", + "name": "{name}-connection-add-terms", + "policyCategory": "bootstrap", + "policySubCategory": "connection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "connection_admins_{guid}" + ], + "policyActions": [ + "add-relationship", + "remove-relationship" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": [ + "end-one-entity-classification:*", + "end-one-entity:*", + "end-one-entity-type:AtlasGlossaryTerm", + + "end-two-entity-classification:*", + "end-two-entity:{entity}", + "end-two-entity:{entity}/*", + "end-two-entity-type:*", + + "relationship-type:*" + ] + } + }, + { + "typeName": "AuthPolicy", + "guid": -3, + "attributes": { + "qualifiedName": "{guid}/connection-CRUD", + "name": "{name}-connection-CRUD", + "policyCategory": "bootstrap", + "policySubCategory": "connection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "connection_admins_{guid}" + ], + "policyActions": [ + "entity-read", + "entity-create", + "entity-update", + "entity-delete" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:*", + "entity-classification:*" + ] + } + }, + + { + "typeName": "AuthPolicy", + "guid": -4, + "attributes": { + "qualifiedName": "{guid}/connection-entity-business-metadata", + "name": "{name}-connection-entity-business-metadata", + "policyCategory": "bootstrap", + "policySubCategory": "connection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "connection_admins_{guid}" + ], + "policyActions": [ + "entity-update-business-metadata" + ], + "policyResourceCategory": "RELATIONSHIP", + "policyResources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:*", + "entity-classification:*", + "entity-business-metadata:*" + ] + } + }, + { + "typeName": "AuthPolicy", + "guid": -5, + "attributes": { + "qualifiedName": "{guid}/connection-classification", + "name": "{name}-connection-classification", + "policyCategory": "bootstrap", + "policySubCategory": "connection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "connection_admins_{guid}" + ], + "policyActions": [ + "entity-add-classification", + "entity-remove-classification", + "entity-update-classification" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:*", + "entity-classification:*", + "classification:*" + ] + } + }, + { + "typeName": "AuthPolicy", + "guid": -6, + "attributes": { + "qualifiedName": "{guid}/connection-entity-label", + "name": "{name}-connection-entity-label", + "policyCategory": "bootstrap", + "policySubCategory": "connection", + "policyType": "allow", + "policyServiceName": "atlas", + "policyRoles": [ + "connection_admins_{guid}" + ], + "policyActions": [ + "entity-add-label", + "entity-remove-label" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:*", + "entity-classification:*", + "entity-label:*" + ] + } + }, + { + "typeName": "AuthPolicy", + "guid": -7, + "attributes": { + "qualifiedName": "{guid}/dataPolicy-connection", + "name": "{name}-dataPolicy-connection", + "policyCategory": "bootstrap", + "policySubCategory": "connection", + "policyType": "allow", + "policyServiceName": "heka", + "policyRoles": [ + "connection_admins_{guid}" + ], + "policyActions": [ + "select" + ], + "policyResourceCategory": "ENTITY", + "policyResources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:*" + ] + } + } +] \ No newline at end of file diff --git a/addons/static/templates/policy_cache_transformer_persona.json b/addons/static/templates/policy_cache_transformer_persona.json new file mode 100644 index 00000000000..3379b3d974f --- /dev/null +++ b/addons/static/templates/policy_cache_transformer_persona.json @@ -0,0 +1,1489 @@ +{ + "persona-asset-read": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:{entity-type}", + "entity-classification:*" + ], + "actions": ["entity-read"], + "policyConditions": [ + { + "policyConditionType": "excludeEntityTypes", + "policyConditionValues": [ + "DataQualityRule" + ] + } + ] + } + ], + "persona-asset-update": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:{entity-type}", + "entity-classification:*" + ], + "actions": ["entity-update"], + "policyConditions": [ + { + "policyConditionType": "excludeEntityTypes", + "policyConditionValues": [ + "DataQualityRule" + ] + } + ] + }, + { + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:{entity-type}", + "end-one-entity-classification:*", + "end-one-entity:{entity}", + "end-one-entity:{entity}/*", + + "end-two-entity-type:Catalog", + "end-two-entity-type:Connection", + "end-two-entity-type:Process", + "end-two-entity-type:Namespace", + "end-two-entity-type:ProcessExecution", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "actions": ["add-relationship", "remove-relationship"], + "policyConditions": [ + { + "policyConditionType": "excludeEntityTypes", + "policyConditionValues": [ + "DataQualityRule" + ] + } + ] + }, + { + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:Catalog", + "end-one-entity-type:Connection", + "end-one-entity-type:Process", + "end-one-entity-type:Namespace", + "end-one-entity-type:ProcessExecution", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:{entity-type}", + "end-two-entity-classification:*", + "end-two-entity:{entity}", + "end-two-entity:{entity}/*" + ], + "actions": ["add-relationship", "remove-relationship"], + "policyConditions": [ + { + "policyConditionType": "excludeEntityTypes", + "policyConditionValues": [ + "DataQualityRule" + ] + } + ] + } + ], + "persona-api-create": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:{entity-type}", + "entity-classification:*" + ], + "actions": ["entity-create"], + "policyConditions": [ + { + "policyConditionType": "excludeEntityTypes", + "policyConditionValues": [ + "DataQualityRule" + ] + } + ] + } + ], + "persona-api-delete": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:{entity-type}", + "entity-classification:*" + ], + "actions": ["entity-delete"], + "policyConditions": [ + { + "policyConditionType": "excludeEntityTypes", + "policyConditionValues": [ + "DataQualityRule" + ] + } + ] + } + ], + "persona-business-update-metadata": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:{entity-type}", + "entity-classification:*", + "entity-business-metadata:*" + ], + "actions": ["entity-update-business-metadata"] + } + ], + "persona-entity-add-classification": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:{entity-type}", + "entity-classification:*", + "classification:*" + ], + "actions": [ + "entity-add-classification", + "entity-update-classification" + ] + } + ], + "persona-entity-update-classification": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:{entity-type}", + "entity-classification:*", + "classification:*" + ], + "actions": ["entity-update-classification"] + } + ], + "persona-entity-remove-classification": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:{entity-type}", + "entity-classification:*", + "classification:*" + ], + "actions": [ + "entity-remove-classification", + "entity-update-classification" + ] + } + ], + "persona-add-terms": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:AtlasGlossaryTerm", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:{entity-type}", + "end-two-entity-classification:*", + "end-two-entity:{entity}", + "end-two-entity:{entity}/*" + ], + "actions": ["add-relationship"] + } + ], + "persona-remove-terms": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:AtlasGlossaryTerm", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:{entity-type}", + "end-two-entity-classification:*", + "end-two-entity:{entity}", + "end-two-entity:{entity}/*" + ], + "actions": ["remove-relationship"] + } + ], + + + + "persona-glossary-read": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:*{entity}", + "entity-type:AtlasGlossary", + "entity-type:AtlasGlossaryTerm", + "entity-type:AtlasGlossaryCategory", + "entity-classification:*" + ], + "actions": ["entity-read"] + }, + { + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:AtlasGlossary", + "end-one-entity-type:AtlasGlossaryTerm", + "end-one-entity-type:AtlasGlossaryCategory", + "end-one-entity-classification:*", + "end-one-entity:*{entity}", + + "end-two-entity-type:AtlasGlossary", + "end-two-entity-type:AtlasGlossaryTerm", + "end-two-entity-type:AtlasGlossaryCategory", + "end-two-entity-classification:*", + "end-two-entity:*{entity}" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + } + ], + "persona-glossary-update": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:*{entity}", + "entity-type:AtlasGlossary", + "entity-type:AtlasGlossaryTerm", + "entity-type:AtlasGlossaryCategory", + "entity-classification:*" + ], + "actions": ["entity-update"] + }, + { + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:AtlasGlossary", + "end-one-entity-type:AtlasGlossaryTerm", + "end-one-entity-type:AtlasGlossaryCategory", + "end-one-entity-classification:*", + "end-one-entity:*{entity}", + + "end-two-entity-type:*", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + }, + { + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:*", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:*", + "end-two-entity-classification:*", + "end-two-entity:*{entity}" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + } + ], + "persona-glossary-create": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:*{entity}", + "entity-type:AtlasGlossary", + "entity-type:AtlasGlossaryTerm", + "entity-type:AtlasGlossaryCategory", + "entity-classification:*" + ], + "actions": ["entity-create"] + } + ], + "persona-glossary-delete": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:*{entity}", + "entity-type:AtlasGlossary", + "entity-type:AtlasGlossaryTerm", + "entity-type:AtlasGlossaryCategory", + "entity-classification:*" + ], + "actions": ["entity-delete"] + } + ], + "persona-glossary-update-custom-metadata": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:*{entity}", + "entity-type:AtlasGlossary", + "entity-type:AtlasGlossaryTerm", + "entity-type:AtlasGlossaryCategory", + "entity-classification:*", + "entity-business-metadata:*" + ], + "actions": ["entity-update-business-metadata"] + } + ], + "persona-glossary-add-classifications": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:*{entity}", + "entity-type:AtlasGlossary", + "entity-type:AtlasGlossaryTerm", + "entity-type:AtlasGlossaryCategory", + "entity-classification:*", + "classification:*" + ], + "actions": [ + "entity-add-classification", + "entity-update-classification" + ] + } + ], + "persona-glossary-update-classifications": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:*{entity}", + "entity-type:AtlasGlossary", + "entity-type:AtlasGlossaryTerm", + "entity-type:AtlasGlossaryCategory", + "entity-classification:*", + "classification:*" + ], + "actions": ["entity-update-classification"] + } + ], + "persona-glossary-delete-classifications": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:*{entity}", + "entity-type:AtlasGlossary", + "entity-type:AtlasGlossaryTerm", + "entity-type:AtlasGlossaryCategory", + "entity-classification:*", + "classification:*" + ], + "actions": [ + "entity-remove-classification", + "entity-update-classification" + ] + } + ], + + "persona-domain-read": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:DataDomain", + "entity-type:DataProduct", + "entity-classification:*" + ], + "actions": ["entity-read"] + } + ], + "persona-domain-update": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:{entity}", + "entity-type:DataDomain", + "entity-classification:*", + "classification:*" + ], + "actions": [ + "entity-update", + "entity-add-classification", + "entity-update-classification", + "entity-remove-classification" + ] + }, + { + "policyResourceCategory": "ENTITY", + "description": "Create Stakeholder for this Domain", + "policyType": "ACCESS", + "resources": [ + "entity:default/*/{entity}", + "entity-type:Stakeholder", + "entity-classification:*" + ], + "actions": [ + "entity-read", + "entity-create", + "entity-update", + "entity-delete" + ] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink Stakeholder to this Domain", + + "resources": [ + "relationship-type:*", + + "end-one-entity-type:DataDomain", + "end-one-entity-classification:*", + "end-one-entity:{entity}", + + "end-two-entity-type:Stakeholder", + "end-two-entity-classification:*", + "end-two-entity:default/*/{entity}" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink any Stakeholder Title to this Domain's Stakeholder", + + "resources": [ + "relationship-type:*", + + "end-one-entity-type:StakeholderTitle", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:Stakeholder", + "end-two-entity-classification:*", + "end-two-entity:default/*/{entity}" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink any DataDomain, DataProduct OR DataContract to this Domain", + + "resources": [ + "relationship-type:*", + + "end-one-entity-type:DataDomain", + "end-two-entity-type:DataProduct", + "end-one-entity-classification:*", + "end-one-entity:{entity}", + "end-one-entity:{entity}/*", + + "end-two-entity-type:DataDomain", + "end-two-entity-type:DataProduct", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink any DataDomain, DataProduct OR DataContract to this Domain", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:DataDomain", + "end-one-entity-type:DataProduct", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:DataDomain", + "end-two-entity-type:DataProduct", + "end-two-entity-classification:*", + "end-two-entity:{entity}", + "end-two-entity:{entity}/*" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink resource to this Domain", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:DataDomain", + "end-one-entity-classification:*", + "end-one-entity:{entity}", + + "end-two-entity-type:Resource", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink term to this Sub Domain", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:AtlasGlossaryTerm", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:DataDomain", + "end-two-entity-classification:*", + "end-two-entity:{entity}" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + } + ], + "persona-domain-business-update-metadata": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}", + "entity-type:DataDomain", + "entity-classification:*", + "entity-business-metadata:*" + ], + "actions": ["entity-update-business-metadata"] + } + ], + + "persona-domain-sub-domain-read": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:{entity}/*domain/*", + "entity-type:DataDomain", + "entity-classification:*" + ], + "actions": ["entity-read"] + } + ], + "persona-domain-sub-domain-create": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:{entity}/*domain/*", + "entity-type:DataDomain", + "entity-classification:*" + ], + "actions": ["entity-create"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink this DataProduct to any parent Domain", + "resources": [ + "relationship-type:*", + + "end-one-entity:{entity}/*", + "end-one-entity:{entity}", + "end-one-entity-type:DataDomain", + "end-one-entity-classification:*", + + "end-two-entity:{entity}/*", + "end-one-entity:{entity}", + "end-two-entity-type:DataDomain", + "end-two-entity-classification:*" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + } + ], + "persona-domain-sub-domain-update": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:{entity}/*domain/*", + "entity-type:DataDomain", + "entity-classification:*", + "classification:*" + ], + "actions": [ + "entity-update", + "entity-add-classification", + "entity-update-classification", + "entity-remove-classification" + ] + }, + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "description": "Create Stakeholder for Sub Domains", + + "resources": [ + "entity:default/*/{entity}/*", + "entity-type:Stakeholder", + "entity-classification:*" + ], + "actions": [ + "entity-read", + "entity-create", + "entity-update", + "entity-delete" + ] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink Stakeholder to Sub Domains", + + "resources": [ + "relationship-type:*", + + "end-one-entity-type:DataDomain", + "end-one-entity-classification:*", + "end-one-entity:{entity}/*domain/*", + + "end-two-entity-type:Stakeholder", + "end-two-entity-classification:*", + "end-two-entity:default/*/{entity}/*" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink any Stakeholder Title to sub-domains's Stakeholder", + + "resources": [ + "relationship-type:*", + + "end-one-entity-type:StakeholderTitle", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:Stakeholder", + "end-two-entity-classification:*", + "end-two-entity:default/*/{entity}/*" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink resource to this Sub Domain", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:DataDomain", + "end-one-entity-classification:*", + "end-one-entity:{entity}/*domain/*", + + "end-two-entity-type:Resource", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink term to this Sub Domain", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:AtlasGlossaryTerm", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:DataDomain", + "end-two-entity-classification:*", + "end-two-entity:{entity}/*domain/*" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + } + ], + "persona-domain-sub-domain-delete": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:{entity}/*domain/*", + "entity-type:DataDomain", + "entity-classification:*" + ], + "actions": ["entity-delete"] + } + ], + "persona-domain-sub-domain-business-update-metadata": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}/*domain/*", + "entity-type:DataDomain", + "entity-classification:*", + "entity-business-metadata:*" + ], + "actions": ["entity-update-business-metadata"] + } + ], + + "persona-domain-product-read": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:{entity}/*product/*", + "entity:{entity}", + "entity-type:DataProduct", + "entity-classification:*" + ], + "actions": ["entity-read"] + } + ], + "persona-domain-product-create": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:{entity}/*product/*", + "entity-type:DataProduct", + "entity-classification:*" + ], + "actions": ["entity-create"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink this DataProduct to any parent Domain", + "resources": [ + "relationship-type:*", + + "end-one-entity:{entity}/*", + "end-one-entity:{entity}", + "end-one-entity-type:DataDomain", + "end-one-entity-classification:*", + + "end-two-entity:{entity}/*", + "end-two-entity-type:DataProduct", + "end-two-entity-classification:*" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink any Asset to this DataProduct", + + "resources": [ + "relationship-type:*", + + "end-one-entity-type:Asset", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:DataProduct", + "end-two-entity-classification:*", + "end-two-entity:{entity}/*product/*" + ], + + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + } + ], + "persona-domain-product-update": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:{entity}/*product/*", + "entity:{entity}", + "entity-type:DataProduct", + "entity-classification:*", + "classification:*" + ], + "actions": [ + "entity-update", + "entity-add-classification", + "entity-update-classification", + "entity-remove-classification" + ] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink any Asset to this DataProduct", + + "resources": [ + "relationship-type:*", + + "end-one-entity-type:Asset", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:DataProduct", + "end-two-entity-classification:*", + "end-two-entity:{entity}", + "end-two-entity:{entity}/*product/*" + ], + + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink any Asset to this DataProduct", + + "resources": [ + "relationship-type:*", + + "end-one-entity-type:DataProduct", + "end-one-entity-classification:*", + "end-one-entity:{entity}", + "end-one-entity:{entity}/*product/*", + + "end-two-entity-type:Asset", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + } + ], + "persona-domain-product-delete": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:{entity}/*product/*", + "entity:{entity}", + "entity-type:DataProduct", + "entity-classification:*" + ], + "actions": ["entity-delete"] + } + ], + "persona-domain-product-business-update-metadata": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}/*product/*", + "entity:{entity}", + "entity-type:DataProduct", + "entity-classification:*", + "entity-business-metadata:*" + ], + "actions": ["entity-update-business-metadata"] + } + ], + + "select": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}", + "entity:{entity}/*", + "entity-type:{entity-type}" + ], + "actions": ["select"] + } + ], + "persona-ai-application-read": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:*", + "entity-type:AIApplication", + "entity-classification:*" + ], + "actions": ["entity-read"] + } + ], + "persona-ai-application-create": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:*", + "entity-type:AIApplication", + "entity-classification:*" + ], + "actions": ["entity-create", "entity-update"] + } + ], + "persona-ai-application-update": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:*", + "entity-type:AIApplication", + "entity-classification:*" + ], + "actions": ["entity-update"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink AIModel to any AIApplication", + "resources": [ + "relationship-type:*", + "end-one-entity-type:AIModel", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:AIApplication", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink resource to this AIApplication", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:AIApplication", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:Resource", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + } + ], + "persona-ai-application-delete": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:*", + "entity-type:AIApplication", + "entity-classification:*" + ], + "actions": ["entity-delete"] + } + ], + "persona-ai-application-business-update-metadata": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:*", + "entity-type:AIApplication", + "entity-classification:*", + "entity-business-metadata:*" + ], + "actions": ["entity-update-business-metadata"] + } + ], + "persona-ai-application-add-terms": [ + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link term to this AI asset", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:AtlasGlossaryTerm", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:AIApplication", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "actions": ["add-relationship", "update-relationship"] + } + ], + "persona-ai-application-remove-terms": [ + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink term to this AI asset", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:AtlasGlossaryTerm", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:AIApplication", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "actions": ["remove-relationship"] + } + ], + "persona-ai-application-add-classification": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:*", + "entity-type:AIApplication", + "entity-classification:*", + "classification:*" + ], + "actions": [ + "entity-add-classification", + "entity-update-classification" + ] + } + ], + "persona-ai-application-remove-classification": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:*", + "entity-type:AIApplication", + "entity-classification:*", + "classification:*" + ], + "actions": [ + "entity-update-classification", + "entity-remove-classification" + ] + } + ], + "persona-ai-model-read": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:*", + "entity-type:AIModel", + "entity-classification:*" + ], + "actions": ["entity-read"] + } + ], + "persona-ai-model-create": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:*", + "entity-type:AIModel", + "entity-classification:*" + ], + "actions": ["entity-create", "entity-update"] + } + ], + "persona-ai-model-update": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:*", + "entity-type:AIModel", + "entity-classification:*" + ], + "actions": ["entity-update"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink AIModel to any AIApplication", + "resources": [ + "relationship-type:*", + "end-one-entity-type:AIModel", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:AIApplication", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink resource to this AIModel", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:AIModel", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:Resource", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "actions": ["add-relationship", "update-relationship", "remove-relationship"] + }, + { + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "description": "Allow to update relation for datasets for this AIModel", + "resources": [ + "relationship-type:*", + "end-one-entity-type:AIModel", + "end-one-entity-classification:*", + "end-one-entity:*", + "end-one-entity:{entity}/*", + + "end-two-entity-type:Catalog", + "end-two-entity-type:Connection", + "end-two-entity-type:Process", + "end-two-entity-type:Namespace", + "end-two-entity-type:ProcessExecution", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "actions": ["add-relationship", "remove-relationship"] + }, + { + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "description": "Allow to update relation for datasets for this AIModel", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:Catalog", + "end-one-entity-type:Connection", + "end-one-entity-type:Process", + "end-one-entity-type:Namespace", + "end-one-entity-type:ProcessExecution", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:AIModel", + "end-two-entity-classification:*", + "end-two-entity:*", + "end-two-entity:{entity}/*" + ], + "actions": ["add-relationship", "remove-relationship"] + }, + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "description": "Create/delete process to update datasets for this AIModel", + "resources": [ + "entity:*", + "entity-type:Process", + "entity-classification:*" + ], + "actions": ["entity-create", "entity-delete"] + } + ], + "persona-ai-model-delete": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:*", + "entity-type:AIModel", + "entity-classification:*" + ], + "actions": ["entity-delete"] + } + ], + "persona-ai-model-business-update-metadata": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:*", + "entity-type:AIModel", + "entity-classification:*", + "entity-business-metadata:*" + ], + "actions": ["entity-update-business-metadata"] + } + ], + "persona-ai-model-add-terms": [ + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link term to this AI asset", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:AtlasGlossaryTerm", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:AIModel", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "actions": ["add-relationship", "update-relationship"] + } + ], + "persona-ai-model-remove-terms": [ + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink term to this AI asset", + "resources": [ + "relationship-type:*", + + "end-one-entity-type:AtlasGlossaryTerm", + "end-one-entity-classification:*", + "end-one-entity:*", + + "end-two-entity-type:AIModel", + "end-two-entity-classification:*", + "end-two-entity:*" + ], + "actions": ["remove-relationship"] + } + ], + "persona-ai-model-add-classification": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:*", + "entity-type:AIModel", + "entity-classification:*", + "classification:*" + ], + "actions": [ + "entity-add-classification", + "entity-update-classification" + ] + } + ], + "persona-ai-model-remove-classification": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:*", + "entity-type:AIModel", + "entity-classification:*", + "classification:*" + ], + "actions": [ + "entity-update-classification", + "entity-remove-classification" + ] + } + ], + "persona-dq-read": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}/*/rule/*", + "entity-type:DataQualityRule", + "entity-classification:*" + ], + "actions": ["entity-read"] + } + ], + "persona-dq-create": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:{entity}/*/rule/*", + "entity-type:DataQualityRule", + "entity-classification:*" + ], + "actions": ["entity-create"] + }, + { + "policyResourceCategory": "RELATIONSHIP", + "policyType": "ACCESS", + "description": "Link/unlink this DQRule to any Asset", + "resources": [ + "relationship-type:*", + + "end-one-entity:{entity}/*/rule/*", + "end-one-entity-type:DataQualityRule", + "end-one-entity-classification:*", + + "end-two-entity:*", + "end-two-entity-type:Asset", + "end-two-entity-classification:*" + + ], + "actions": ["add-relationship", "remove-relationship", "update-relationship"] + } + ], + "persona-dq-update": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "resources": [ + "entity:{entity}/*/rule/*", + "entity-type:DataQualityRule", + "entity-classification:*" + ], + "actions": ["entity-update"] + }, + { + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "resources": [ + "relationship-type:*", + + "end-one-entity:{entity}/*/rule/*", + "end-one-entity-type:DataQualityRule", + "end-one-entity-classification:*", + + "end-two-entity:*", + "end-two-entity-type:Asset", + "end-two-entity-classification:*" + ], + "actions": ["add-relationship", "remove-relationship", "update-relationship"] + } + ], + "persona-dq-delete": [ + { + "policyResourceCategory": "ENTITY", + "policyType": "ACCESS", + "resources": [ + "entity:{entity}/*/rule/*", + "entity-type:DataQualityRule", + "entity-classification:*" + ], + "actions": ["entity-delete"] + } + ], + + "persona-asset-read-abac": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "policyFilterCriteria": "{criteria}", + "actions": ["entity-read"] + } + ], + "persona-asset-update-abac": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "policyFilterCriteria": "{criteria}", + "actions": ["entity-update"] + }, + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "policyFilterCriteria": "{\"endOneEntity\":{entity-criteria},\"endTwoEntity\":{\"condition\": \"AND\", \"criterion\": [{\"attributeName\": \"__typeName\", \"attributeValue\": [\"Catalog\", \"Connection\", \"Process\", \"Namespace\", \"ProcessExecution\"], \"operator\": \"IN\"}]}}", + "actions": ["add-relationship", "remove-relationship"] + }, + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "policyFilterCriteria": "{\"endOneEntity\":{\"condition\": \"AND\", \"criterion\": [{\"attributeName\": \"__typeName\", \"attributeValue\": [\"Catalog\", \"Connection\", \"Process\", \"Namespace\", \"ProcessExecution\"], \"operator\": \"IN\"}]},\"endTwoEntity\":{entity-criteria}}", + "actions": ["add-relationship", "remove-relationship"] + } + ], + "persona-api-create-abac": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "policyFilterCriteria": "{criteria}", + "actions": ["entity-create"] + } + ], + "persona-api-delete-abac": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "policyFilterCriteria": "{criteria}", + "actions": ["entity-delete"] + } + ], + "persona-business-update-metadata-abac": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "policyFilterCriteria": "{criteria}", + "actions": ["entity-update-business-metadata"] + } + ], + "persona-entity-add-classification-abac": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "policyFilterCriteria": "{criteria}", + "actions": ["entity-add-classification", "entity-update-classification"] + } + ], + "persona-entity-update-classification-abac": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "policyFilterCriteria": "{criteria}", + "actions": ["entity-update-classification"] + } + ], + "persona-entity-remove-classification-abac": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "ENTITY", + "policyFilterCriteria": "{criteria}", + "actions": ["entity-update-classification", "entity-remove-classification"] + } + ], + "persona-add-terms-abac": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "policyFilterCriteria": "{\"endOneEntity\":{\"condition\": \"AND\", \"criterion\": [{\"attributeName\": \"__typeName\", \"attributeValue\": \"AtlasGlossaryTerm\",\"operator\": \"EQUALS\"}]},\"endTwoEntity\":{entity-criteria}}", + "actions": ["add-relationship", "update-relationship"] + } + ], + "persona-remove-terms-abac": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "policyFilterCriteria": "{\"endOneEntity\":{\"condition\": \"AND\", \"criterion\": [{\"attributeName\": \"__typeName\", \"attributeValue\": \"AtlasGlossaryTerm\",\"operator\": \"EQUALS\"}]},\"endTwoEntity\":{entity-criteria}}", + "actions": ["remove-relationship"] + } + ] +} diff --git a/addons/static/templates/policy_cache_transformer_purpose.json b/addons/static/templates/policy_cache_transformer_purpose.json new file mode 100644 index 00000000000..79e6aa25dc7 --- /dev/null +++ b/addons/static/templates/policy_cache_transformer_purpose.json @@ -0,0 +1,68 @@ +{ + "entity-update": [ + { + "policyType": "ACCESS", + "policyResourceCategory": "TAG", + "resources": [ + "tag:{tag}" + ], + "actions": ["entity-update"] + }, + { + "policyServiceName": "atlas", + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "resources": [ + "end-one-entity-classification:{tag}", + "end-one-entity:*", + "end-one-entity-type:*", + + "end-two-entity:*", + "end-two-entity-type:Readme", + "end-two-entity-type:Link", + "end-two-entity-classification:*", + + "relationship-type:*" + ], + "actions": ["add-relationship", "remove-relationship"] + } + ], + "purpose-add-terms": [ + { + "policyServiceName": "atlas", + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "resources": [ + "relationship-type:*", + + "end-one-entity-classification:*", + "end-one-entity:*", + "end-one-entity-type:AtlasGlossaryTerm", + + "end-two-entity:*", + "end-two-entity-type:*", + "end-two-entity-classification:{tag}" + ], + "actions": ["add-relationship"] + } + ], + "purpose-remove-terms": [ + { + "policyServiceName": "atlas", + "policyType": "ACCESS", + "policyResourceCategory": "RELATIONSHIP", + "resources": [ + "relationship-type:*", + + "end-one-entity-classification:*", + "end-one-entity:*", + "end-one-entity-type:AtlasGlossaryTerm", + + "end-two-entity:*", + "end-two-entity-type:*", + "end-two-entity-classification:{tag}" + ], + "actions": ["remove-relationship"] + } + ] +} \ No newline at end of file diff --git a/addons/storm-bridge-shim/pom.xml b/addons/storm-bridge-shim/pom.xml deleted file mode 100755 index f4e75927f07..00000000000 --- a/addons/storm-bridge-shim/pom.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - storm-bridge-shim - Apache Atlas Storm Bridge Shim Module - Apache Atlas Storm Bridge Shim - jar - - - - - org.apache.atlas - atlas-plugin-classloader - - - - - org.apache.storm - storm-core - ${storm.version} - jar - - - org.slf4j - slf4j-log4j12 - - - javax.servlet - servlet-api - - - io.dropwizard.metrics - metrics-core - - - io.dropwizard.metrics - metrics-graphite - - - io.dropwizard.metrics - metrics-ganglia - - - - - - - io.dropwizard.metrics - metrics-core - ${dropwizard-metrics} - - - io.dropwizard.metrics - metrics-graphite - ${dropwizard-metrics} - - - io.dropwizard.metrics - metrics-ganglia - ${dropwizard-metrics} - - - - diff --git a/addons/storm-bridge-shim/src/main/java/org/apache/atlas/storm/hook/StormAtlasHook.java b/addons/storm-bridge-shim/src/main/java/org/apache/atlas/storm/hook/StormAtlasHook.java deleted file mode 100644 index 0ce7633aa2d..00000000000 --- a/addons/storm-bridge-shim/src/main/java/org/apache/atlas/storm/hook/StormAtlasHook.java +++ /dev/null @@ -1,105 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.storm.hook; - - -import org.apache.atlas.plugin.classloader.AtlasPluginClassLoader; -import org.apache.storm.ISubmitterHook; -import org.apache.storm.generated.StormTopology; -import org.apache.storm.generated.TopologyInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Map; - -/** - * Storm hook used for atlas entity registration. - */ -public class StormAtlasHook implements ISubmitterHook { - private static final Logger LOG = LoggerFactory.getLogger(StormAtlasHook.class); - - - private static final String ATLAS_PLUGIN_TYPE = "storm"; - private static final String ATLAS_STORM_HOOK_IMPL_CLASSNAME = "org.apache.atlas.storm.hook.StormAtlasHook"; - - private AtlasPluginClassLoader atlasPluginClassLoader = null; - private ISubmitterHook stormHook = null; - - - public StormAtlasHook() { - this.initialize(); - } - - @Override - public void notify(TopologyInfo topologyInfo, Map stormConf, StormTopology stormTopology) - throws IllegalAccessException { - if (LOG.isDebugEnabled()) { - LOG.debug("==> StormAtlasHook.notify({}, {}, {})", topologyInfo, stormConf, stormTopology); - } - - try { - activatePluginClassLoader(); - stormHook.notify(topologyInfo, stormConf, stormTopology); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== StormAtlasHook.notify({}, {}, {})", topologyInfo, stormConf, stormTopology); - } - } - - private void initialize() { - if (LOG.isDebugEnabled()) { - LOG.debug("==> StormAtlasHook.initialize()"); - } - - try { - atlasPluginClassLoader = AtlasPluginClassLoader.getInstance(ATLAS_PLUGIN_TYPE, this.getClass()); - - @SuppressWarnings("unchecked") - Class cls = (Class) Class - .forName(ATLAS_STORM_HOOK_IMPL_CLASSNAME, true, atlasPluginClassLoader); - - activatePluginClassLoader(); - - stormHook = cls.newInstance(); - } catch (Exception excp) { - LOG.error("Error instantiating Atlas hook implementation", excp); - } finally { - deactivatePluginClassLoader(); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("<== StormAtlasHook.initialize()"); - } - } - - private void activatePluginClassLoader() { - if (atlasPluginClassLoader != null) { - atlasPluginClassLoader.activate(); - } - } - - private void deactivatePluginClassLoader() { - if (atlasPluginClassLoader != null) { - atlasPluginClassLoader.deactivate(); - } - } -} diff --git a/addons/storm-bridge/pom.xml b/addons/storm-bridge/pom.xml deleted file mode 100644 index e8106afce0e..00000000000 --- a/addons/storm-bridge/pom.xml +++ /dev/null @@ -1,591 +0,0 @@ - - - - 4.0.0 - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - ../../ - - storm-bridge - Apache Atlas Storm Bridge Module - Apache Atlas Storm Bridge - jar - - - - - org.apache.atlas - atlas-client-v1 - - - - org.apache.atlas - atlas-client-v2 - - - - org.apache.atlas - atlas-notification - - - - org.apache.atlas - hive-bridge - - - - org.apache.hive - hive-exec - ${hive.version} - - - javax.servlet - * - - - provided - - - - org.apache.hbase - hbase-common - ${hbase.version} - - - javax.servlet - servlet-api - - - org.eclipse.jetty - * - - - - - - org.mockito - mockito-all - - - - - - org.apache.storm - storm-core - ${storm.version} - - - org.slf4j - log4j-over-slf4j - - - javax.servlet - servlet-api - - - io.dropwizard.metrics - metrics-core - - - io.dropwizard.metrics - metrics-graphite - - - io.dropwizard.metrics - metrics-ganglia - - - - - - - io.dropwizard.metrics - metrics-core - ${dropwizard-metrics} - - - io.dropwizard.metrics - metrics-graphite - ${dropwizard-metrics} - - - io.dropwizard.metrics - metrics-ganglia - ${dropwizard-metrics} - - - - - org.testng - testng - - - - org.eclipse.jetty - jetty-server - test - - - - org.eclipse.jetty - jetty-util - ${jetty.version} - test - - - - commons-collections - commons-collections - - - - - - org.apache.atlas - atlas-graphdb-impls - pom - test - - - - org.apache.atlas - atlas-webapp - war - test - - - - com.fasterxml.jackson.core - jackson-core - ${jackson.version} - test - - - - - - dist - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-hook - package - - copy - - - ${project.build.directory}/dependency/hook/storm/atlas-storm-plugin-impl - false - false - true - - - ${project.groupId} - ${project.artifactId} - ${project.version} - - - ${project.groupId} - atlas-client-common - ${project.version} - - - ${project.groupId} - atlas-client-v1 - ${project.version} - - - ${project.groupId} - atlas-client-v2 - ${project.version} - - - ${project.groupId} - hive-bridge - ${project.version} - - - ${project.groupId} - atlas-intg - ${project.version} - - - ${project.groupId} - atlas-notification - ${project.version} - - - ${project.groupId} - atlas-common - ${project.version} - - - org.apache.kafka - kafka_${kafka.scala.binary.version} - ${kafka.version} - - - org.apache.kafka - kafka-clients - ${kafka.version} - - - aopalliance - aopalliance - ${aopalliance.version} - - - commons-configuration - commons-configuration - ${commons-conf.version} - - - org.apache.commons - commons-configuration2 - ${commons-conf2.version} - - - commons-logging - commons-logging - ${commons-logging.version} - - - commons-collections - commons-collections - ${commons-collections.version} - - - javax.inject - javax.inject - ${javax-inject.version} - - - org.codehaus.jettison - jettison - ${jettison.version} - - - org.codehaus.jettison - jettison - ${jettison.version} - - - com.thoughtworks.paranamer - paranamer - ${paranamer.version} - - - org.apache.hive - hive-exec - ${hive.version} - - - org.apache.hbase - hbase-common - ${hbase.version} - - - org.apache.hadoop - hadoop-common - ${hadoop.version} - - - org.apache.hadoop - hadoop-auth - ${hadoop.version} - - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.databind.version} - - - - com.fasterxml.jackson.core - jackson-core - ${jackson.version} - - - - com.fasterxml.jackson.core - jackson-annotations - ${jackson.version} - - - org.codehaus.woodstox - stax2-api - ${codehaus.woodstox.stax2-api.version} - - - org.apache.hadoop - hadoop-hdfs-client - ${hadoop.hdfs-client.version} - - - - log4j - log4j - ${log4j.version} - - - com.sun.jersey - jersey-json - ${jersey.version} - - - javax.ws.rs - jsr311-api - ${jsr.version} - - - com.fasterxml.woodstox - woodstox-core - ${woodstox-core.version} - - - - - - copy-hook-shim - package - - copy - - - ${project.build.directory}/dependency/hook/storm - false - false - true - - - ${project.groupId} - storm-bridge-shim - ${project.version} - - - ${project.groupId} - atlas-plugin-classloader - ${project.version} - - - - - - - - - - - - - - - org.eclipse.jetty - jetty-maven-plugin - ${jetty.version} - - ${skipTests} - - - 31000 - 60000 - - ../../webapp/target/atlas-webapp-${project.version}.war - true - ../../webapp/src/main/webapp - - / - ${project.basedir}/../../webapp/src/main/webapp/WEB-INF/web.xml - - true - - true - - atlas.home - ${project.build.directory} - - - atlas.conf - ${project.build.directory}/test-classes - - - atlas.data - ${project.build.directory}/data - - - atlas.log.dir - ${project.build.directory}/logs - - - atlas.log.file - application.log - - - log4j.configuration - file:///${project.build.directory}/test-classes/atlas-log4j.xml - - - atlas.graphdb.backend - ${graphdb.backend.impl} - - - embedded.solr.directory - ${project.build.directory} - - - solr.log.dir - ${project.build.directory}/logs - - - org.eclipse.jetty.annotations.maxWait - 5000 - - - atlas-stop - 31001 - ${jetty-maven-plugin.stopWait} - jar - - - - org.apache.curator - curator-client - ${curator.version} - - - - org.apache.zookeeper - zookeeper - ${zookeeper.version} - - - - - start-jetty - pre-integration-test - - - stop - deploy-war - - - true - - - - stop-jetty - post-integration-test - - stop - - - - - - - org.apache.maven.plugins - maven-site-plugin - - - org.apache.maven.doxia - doxia-module-twiki - ${doxia.version} - - - org.apache.maven.doxia - doxia-core - ${doxia.version} - - - - - - site - - prepare-package - - - - false - false - - - - - - org.codehaus.mojo - exec-maven-plugin - 1.2.1 - false - - - - - - - org.apache.maven.plugins - maven-resources-plugin - - - copy-resources - validate - - copy-resources - - - ${basedir}/target/models - - - ${basedir}/../models - - 0000-Area0/0010-base_model.json - 1000-Hadoop/** - - - - - - - copy-solr-resources - validate - - copy-resources - - - ${project.build.directory}/solr - - - ${basedir}/../../test-tools/src/main/resources/solr - - - - - - - - - - diff --git a/addons/storm-bridge/src/main/java/org/apache/atlas/storm/hook/StormAtlasHook.java b/addons/storm-bridge/src/main/java/org/apache/atlas/storm/hook/StormAtlasHook.java deleted file mode 100644 index 69d58d5743d..00000000000 --- a/addons/storm-bridge/src/main/java/org/apache/atlas/storm/hook/StormAtlasHook.java +++ /dev/null @@ -1,416 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.storm.hook; - -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityExtInfo; -import org.apache.atlas.model.notification.HookNotification; -import org.apache.atlas.model.notification.HookNotification.EntityCreateRequestV2; -import org.apache.atlas.type.AtlasTypeUtil; -import org.apache.atlas.utils.HdfsNameServiceResolver; -import org.apache.commons.collections.CollectionUtils; -import org.apache.storm.ISubmitterHook; -import org.apache.storm.generated.Bolt; -import org.apache.storm.generated.SpoutSpec; -import org.apache.storm.generated.StormTopology; -import org.apache.storm.generated.TopologyInfo; -import org.apache.storm.utils.Utils; -import org.apache.atlas.AtlasClient; -import org.apache.atlas.AtlasConstants; -import org.apache.atlas.hive.bridge.HiveMetaStoreBridge; -import org.apache.atlas.hook.AtlasHook; -import org.apache.atlas.storm.model.StormDataTypes; -import org.apache.commons.lang.StringUtils; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.hbase.HBaseConfiguration; -import org.apache.hadoop.hive.conf.HiveConf; -import org.slf4j.Logger; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Date; - -import static org.apache.atlas.repository.Constants.STORM_SOURCE; - -/** - * StormAtlasHook sends storm topology metadata information to Atlas - * via a Kafka Broker for durability. - *

- * This is based on the assumption that the same topology name is used - * for the various lifecycle stages. - */ -public class StormAtlasHook extends AtlasHook implements ISubmitterHook { - public static final Logger LOG = org.slf4j.LoggerFactory.getLogger(StormAtlasHook.class); - - public static final String ANONYMOUS_OWNER = "anonymous"; // if Storm topology does not contain the owner instance; possible if Storm is running in unsecure mode. - public static final String HBASE_NAMESPACE_DEFAULT = "default"; - public static final String ATTRIBUTE_DB = "db"; - - public static final String RELATIONSHIP_STORM_TOPOLOGY_NODES = "storm_topology_nodes"; - public static final String RELATIONSHIP_DATASET_PROCESS_INPUTS = "dataset_process_inputs"; - public static final String RELATIONSHIP_PROCESS_DATASET_OUTPUTS = "process_dataset_outputs"; - public static final String HBASE_TABLE_QUALIFIED_NAME_FORMAT = "%s:%s@%s"; - - /** - * This is the client-side hook that storm fires when a topology is added. - * - * @param topologyInfo topology info - * @param stormConf configuration - * @param stormTopology a storm topology - */ - @Override - public void notify(TopologyInfo topologyInfo, Map stormConf, StormTopology stormTopology) { - LOG.info("Collecting metadata for a new storm topology: {}", topologyInfo.get_name()); - - try { - String user = getUser(topologyInfo.get_owner(), null); - AtlasEntity topology = createTopologyInstance(topologyInfo, stormConf); - AtlasEntitiesWithExtInfo entity = new AtlasEntitiesWithExtInfo(topology); - - addTopologyDataSets(stormTopology, topologyInfo.get_owner(), stormConf, topology, entity); - - // create the graph for the topology - List graphNodes = createTopologyGraph(stormTopology, stormTopology.get_spouts(), stormTopology.get_bolts()); - - if (CollectionUtils.isNotEmpty(graphNodes)) { - // add the connection from topology to the graph - topology.setRelationshipAttribute("nodes", AtlasTypeUtil.getAtlasRelatedObjectIds(graphNodes, RELATIONSHIP_STORM_TOPOLOGY_NODES)); - - for (AtlasEntity graphNode : graphNodes) { - entity.addReferredEntity(graphNode); - } - } - - List hookNotifications = Collections.singletonList(new EntityCreateRequestV2(user, entity)); - - notifyEntities(hookNotifications, null); - } catch (Exception e) { - throw new RuntimeException("Atlas hook is unable to process the topology.", e); - } - } - - private AtlasEntity createTopologyInstance(TopologyInfo topologyInfo, Map stormConf) { - AtlasEntity topology = new AtlasEntity(StormDataTypes.STORM_TOPOLOGY.getName()); - String owner = topologyInfo.get_owner(); - - if (StringUtils.isEmpty(owner)) { - owner = ANONYMOUS_OWNER; - } - - topology.setAttribute("id", topologyInfo.get_id()); - topology.setAttribute(AtlasClient.NAME, topologyInfo.get_name()); - topology.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, topologyInfo.get_name()); - topology.setAttribute(AtlasClient.OWNER, owner); - topology.setAttribute("startTime", new Date(System.currentTimeMillis())); - topology.setAttribute(AtlasConstants.CLUSTER_NAME_ATTRIBUTE, getMetadataNamespace()); - - return topology; - } - - private void addTopologyDataSets(StormTopology stormTopology, String topologyOwner, Map stormConf, AtlasEntity topology, AtlasEntityExtInfo entityExtInfo) { - // add each spout as an input data set - addTopologyInputs(stormTopology.get_spouts(), stormConf, topologyOwner, topology, entityExtInfo); - - // add the appropriate bolts as output data sets - addTopologyOutputs(stormTopology, topologyOwner, stormConf, topology, entityExtInfo); - } - - private void addTopologyInputs(Map spouts, Map stormConf, String topologyOwner, AtlasEntity topology, AtlasEntityExtInfo entityExtInfo) { - List inputs = new ArrayList<>(); - - for (Map.Entry entry : spouts.entrySet()) { - Serializable instance = Utils.javaDeserialize(entry.getValue().get_spout_object().get_serialized_java(), Serializable.class); - String dsType = instance.getClass().getSimpleName(); - AtlasEntity dsEntity = addDataSet(dsType, topologyOwner, instance, stormConf, entityExtInfo); - - if (dsEntity != null) { - inputs.add(dsEntity); - } - } - - topology.setRelationshipAttribute("inputs", AtlasTypeUtil.getAtlasRelatedObjectIds(inputs, RELATIONSHIP_DATASET_PROCESS_INPUTS)); - } - - private void addTopologyOutputs(StormTopology stormTopology, String topologyOwner, Map stormConf, AtlasEntity topology, AtlasEntityExtInfo entityExtInfo) { - List outputs = new ArrayList<>(); - Map bolts = stormTopology.get_bolts(); - Set boltNames = StormTopologyUtil.getTerminalUserBoltNames(stormTopology); - - for (String boltName : boltNames) { - Serializable instance = Utils.javaDeserialize(bolts.get(boltName).get_bolt_object().get_serialized_java(), Serializable.class); - String dsType = instance.getClass().getSimpleName(); - AtlasEntity dsEntity = addDataSet(dsType, topologyOwner, instance, stormConf, entityExtInfo); - - if (dsEntity != null) { - outputs.add(dsEntity); - } - } - - topology.setRelationshipAttribute("outputs", AtlasTypeUtil.getAtlasRelatedObjectIds(outputs, RELATIONSHIP_PROCESS_DATASET_OUTPUTS)); - } - - private AtlasEntity addDataSet(String dataSetType, String topologyOwner, Serializable instance, Map stormConf, AtlasEntityExtInfo entityExtInfo) { - Map config = StormTopologyUtil.getFieldValues(instance, true, null); - AtlasEntity ret = null; - String metadataNamespace = getMetadataNamespace(); - - // todo: need to redo this with a config driven approach - switch (dataSetType) { - case "KafkaSpout": { - String topicName = config.get("KafkaSpout.kafkaSpoutConfig.translator.topic"); - String uri = config.get("KafkaSpout.kafkaSpoutConfig.kafkaProps.bootstrap.servers"); - - if (StringUtils.isEmpty(topicName)) { - topicName = config.get("KafkaSpout._spoutConfig.topic"); - } - - if (StringUtils.isEmpty(uri)) { - uri = config.get("KafkaSpout._spoutConfig.hosts.brokerZkStr"); - } - - if (StringUtils.isEmpty(topologyOwner)) { - topologyOwner = ANONYMOUS_OWNER; - } - - if (topicName == null) { - LOG.error("Kafka topic name not found"); - } else { - ret = new AtlasEntity(StormDataTypes.KAFKA_TOPIC.getName()); - - ret.setAttribute("topic", topicName); - ret.setAttribute("uri", uri); - ret.setAttribute(AtlasClient.OWNER, topologyOwner); - ret.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, getKafkaTopicQualifiedName(metadataNamespace, topicName)); - ret.setAttribute(AtlasClient.NAME, topicName); - } - } - break; - - case "HBaseBolt": { - final String hbaseTableName = config.get("HBaseBolt.tableName"); - String uri = config.get("hbase.rootdir"); - - if (StringUtils.isEmpty(uri)) { - uri = hbaseTableName; - } - - metadataNamespace = extractComponentMetadataNamespace(HBaseConfiguration.create(), stormConf); - - if (hbaseTableName == null) { - LOG.error("HBase table name not found"); - } else { - ret = new AtlasEntity(StormDataTypes.HBASE_TABLE.getName()); - - ret.setAttribute("uri", hbaseTableName); - ret.setAttribute(AtlasClient.NAME, uri); - ret.setAttribute(AtlasClient.OWNER, stormConf.get("storm.kerberos.principal")); - //TODO - Hbase Namespace is hardcoded to 'default'. need to check how to get this or is it already part of tableName - ret.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, getHbaseTableQualifiedName(metadataNamespace, HBASE_NAMESPACE_DEFAULT, hbaseTableName)); - } - } - break; - - case "HdfsBolt": { - final String hdfsUri = config.get("HdfsBolt.rotationActions") == null ? config.get("HdfsBolt.fileNameFormat.path") : config.get("HdfsBolt.rotationActions"); - final String hdfsPathStr = config.get("HdfsBolt.fsUrl") + hdfsUri; - final Path hdfsPath = new Path(hdfsPathStr); - final String nameServiceID = HdfsNameServiceResolver.getNameServiceIDForPath(hdfsPathStr); - - ret = new AtlasEntity(HiveMetaStoreBridge.HDFS_PATH); - - ret.setAttribute(AtlasConstants.CLUSTER_NAME_ATTRIBUTE, metadataNamespace); - ret.setAttribute(AtlasClient.OWNER, stormConf.get("hdfs.kerberos.principal")); - ret.setAttribute(AtlasClient.NAME, Path.getPathWithoutSchemeAndAuthority(hdfsPath).toString().toLowerCase()); - - if (StringUtils.isNotEmpty(nameServiceID)) { - String updatedPath = HdfsNameServiceResolver.getPathWithNameServiceID(hdfsPathStr); - - ret.setAttribute("path", updatedPath); - ret.setAttribute("nameServiceId", nameServiceID); - ret.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, getHdfsPathQualifiedName(metadataNamespace, updatedPath)); - } else { - ret.setAttribute("path", hdfsPathStr); - ret.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, getHdfsPathQualifiedName(metadataNamespace, hdfsPathStr)); - } - } - break; - - case "HiveBolt": { - metadataNamespace = extractComponentMetadataNamespace(new HiveConf(), stormConf); - - final String dbName = config.get("HiveBolt.options.databaseName"); - final String tblName = config.get("HiveBolt.options.tableName"); - - if (dbName == null || tblName ==null) { - LOG.error("Hive database or table name not found"); - } else { - AtlasEntity dbEntity = new AtlasEntity("hive_db"); - - dbEntity.setAttribute(AtlasClient.NAME, dbName); - dbEntity.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, HiveMetaStoreBridge.getDBQualifiedName(metadataNamespace, dbName)); - dbEntity.setAttribute(AtlasConstants.CLUSTER_NAME_ATTRIBUTE, metadataNamespace); - - entityExtInfo.addReferredEntity(dbEntity); - - // todo: verify if hive table has everything needed to retrieve existing table - ret = new AtlasEntity("hive_table"); - - ret.setAttribute(AtlasClient.NAME, tblName); - ret.setRelationshipAttribute(ATTRIBUTE_DB, AtlasTypeUtil.getAtlasRelatedObjectId(dbEntity, "hive_table_db")); - ret.setAttribute(AtlasClient.REFERENCEABLE_ATTRIBUTE_NAME, HiveMetaStoreBridge.getTableQualifiedName(metadataNamespace, dbName, tblName)); - } - } - break; - - default: - // custom node - create a base dataset class with name attribute - //TODO - What should we do for custom data sets. Not sure what name we can set here? - return null; - } - - if (ret != null) { - entityExtInfo.addReferredEntity(ret); - } - - return ret; - } - - private List createTopologyGraph(StormTopology stormTopology, Map spouts, Map bolts) { - // Add graph of nodes in the topology - Map nodeEntities = new HashMap<>(); - - addSpouts(spouts, nodeEntities); - addBolts(bolts, nodeEntities); - - addGraphConnections(stormTopology, nodeEntities); - - return new ArrayList<>(nodeEntities.values()); - } - - private void addSpouts(Map spouts, Map nodeEntities) { - for (Map.Entry entry : spouts.entrySet()) { - String spoutName = entry.getKey(); - AtlasEntity spout = createSpoutInstance(spoutName, entry.getValue()); - - nodeEntities.put(spoutName, spout); - } - } - - private void addBolts(Map bolts, Map nodeEntities) { - for (Map.Entry entry : bolts.entrySet()) { - String boltName = entry.getKey(); - AtlasEntity boltInstance = createBoltInstance(boltName, entry.getValue()); - - nodeEntities.put(boltName, boltInstance); - } - } - - private AtlasEntity createSpoutInstance(String spoutName, SpoutSpec stormSpout) { - AtlasEntity spout = new AtlasEntity(StormDataTypes.STORM_SPOUT.getName()); - Serializable instance = Utils.javaDeserialize(stormSpout.get_spout_object().get_serialized_java(), Serializable.class); - Map flatConfigMap = StormTopologyUtil.getFieldValues(instance, true, null); - - spout.setAttribute(AtlasClient.NAME, spoutName); - spout.setAttribute("driverClass", instance.getClass().getName()); - spout.setAttribute("conf", flatConfigMap); - - return spout; - } - - private AtlasEntity createBoltInstance(String boltName, Bolt stormBolt) { - AtlasEntity bolt = new AtlasEntity(StormDataTypes.STORM_BOLT.getName()); - Serializable instance = Utils.javaDeserialize(stormBolt.get_bolt_object().get_serialized_java(), Serializable.class); - Map flatConfigMap = StormTopologyUtil.getFieldValues(instance, true, null); - - bolt.setAttribute(AtlasClient.NAME, boltName); - bolt.setAttribute("driverClass", instance.getClass().getName()); - bolt.setAttribute("conf", flatConfigMap); - - return bolt; - } - - private void addGraphConnections(StormTopology stormTopology, Map nodeEntities) { - // adds connections between spouts and bolts - Map> adjacencyMap = StormTopologyUtil.getAdjacencyMap(stormTopology, true); - - for (Map.Entry> entry : adjacencyMap.entrySet()) { - String nodeName = entry.getKey(); - Set adjacencyList = adjacencyMap.get(nodeName); - - if (CollectionUtils.isEmpty(adjacencyList)) { - continue; - } - - // add outgoing links - AtlasEntity node = nodeEntities.get(nodeName); - List outputs = new ArrayList<>(adjacencyList.size()); - - outputs.addAll(adjacencyList); - node.setAttribute("outputs", outputs); - - // add incoming links - for (String adjacentNodeName : adjacencyList) { - AtlasEntity adjacentNode = nodeEntities.get(adjacentNodeName); - @SuppressWarnings("unchecked") - List inputs = (List) adjacentNode.getAttribute("inputs"); - - if (inputs == null) { - inputs = new ArrayList<>(); - } - - inputs.add(nodeName); - adjacentNode.setAttribute("inputs", inputs); - } - } - } - - public static String getKafkaTopicQualifiedName(String metadataNamespace, String topicName) { - return String.format("%s@%s", topicName.toLowerCase(), metadataNamespace); - } - - public static String getHbaseTableQualifiedName(String metadataNamespace, String nameSpace, String tableName) { - return String.format(HBASE_TABLE_QUALIFIED_NAME_FORMAT, nameSpace.toLowerCase(), tableName.toLowerCase(), metadataNamespace); - } - - public static String getHdfsPathQualifiedName(String metadataNamespace, String hdfsPath) { - return String.format("%s@%s", hdfsPath.toLowerCase(), metadataNamespace); - } - - private String extractComponentMetadataNamespace(Configuration configuration, Map stormConf) { - String clusterName = configuration.get(CLUSTER_NAME_KEY, null); - - if (clusterName == null) { - clusterName = getMetadataNamespace(); - } - - return clusterName; - } - - @Override - public String getMessageSource() { - return STORM_SOURCE; - } -} \ No newline at end of file diff --git a/addons/storm-bridge/src/main/java/org/apache/atlas/storm/hook/StormTopologyUtil.java b/addons/storm-bridge/src/main/java/org/apache/atlas/storm/hook/StormTopologyUtil.java deleted file mode 100644 index b903dbc6949..00000000000 --- a/addons/storm-bridge/src/main/java/org/apache/atlas/storm/hook/StormTopologyUtil.java +++ /dev/null @@ -1,248 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.storm.hook; - -import org.apache.commons.lang.StringUtils; -import org.apache.storm.generated.Bolt; -import org.apache.storm.generated.GlobalStreamId; -import org.apache.storm.generated.Grouping; -import org.apache.storm.generated.StormTopology; -import com.google.common.base.Joiner; -import org.slf4j.Logger; - -import java.lang.reflect.Field; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * A storm topology utility class. - */ -public final class StormTopologyUtil { - public static final Logger LOG = org.slf4j.LoggerFactory.getLogger(StormTopologyUtil.class); - - private StormTopologyUtil() { - } - - public static Set getTerminalUserBoltNames(StormTopology topology) { - Set terminalBolts = new HashSet<>(); - Set inputs = new HashSet<>(); - for (Map.Entry entry : topology.get_bolts().entrySet()) { - String name = entry.getKey(); - Set inputsForBolt = entry.getValue().get_common().get_inputs().keySet(); - if (!isSystemComponent(name)) { - for (GlobalStreamId streamId : inputsForBolt) { - inputs.add(streamId.get_componentId()); - } - } - } - - for (String boltName : topology.get_bolts().keySet()) { - if (!isSystemComponent(boltName) && !inputs.contains(boltName)) { - terminalBolts.add(boltName); - } - } - - return terminalBolts; - } - - public static boolean isSystemComponent(String componentName) { - return componentName.startsWith("__"); - } - - public static Map> getAdjacencyMap(StormTopology topology, - boolean removeSystemComponent) { - Map> adjacencyMap = new HashMap<>(); - - for (Map.Entry entry : topology.get_bolts().entrySet()) { - String boltName = entry.getKey(); - Map inputs = entry.getValue().get_common().get_inputs(); - for (Map.Entry input : inputs.entrySet()) { - String inputComponentId = input.getKey().get_componentId(); - Set components = adjacencyMap.containsKey(inputComponentId) - ? adjacencyMap.get(inputComponentId) : new HashSet(); - components.add(boltName); - components = removeSystemComponent ? removeSystemComponents(components) - : components; - if (!removeSystemComponent || !isSystemComponent(inputComponentId)) { - adjacencyMap.put(inputComponentId, components); - } - } - } - - return adjacencyMap; - } - - public static Set removeSystemComponents(Set components) { - Set userComponents = new HashSet<>(); - for (String component : components) { - if (!isSystemComponent(component)) - userComponents.add(component); - } - - return userComponents; - } - - private static final Set WRAPPER_TYPES = new HashSet() {{ - add(Boolean.class); - add(Character.class); - add(Byte.class); - add(Short.class); - add(Integer.class); - add(Long.class); - add(Float.class); - add(Double.class); - add(Void.class); - add(String.class); - }}; - - public static boolean isWrapperType(Class clazz) { - return WRAPPER_TYPES.contains(clazz); - } - - public static boolean isCollectionType(Class clazz) { - return Collection.class.isAssignableFrom(clazz); - } - - public static boolean isMapType(Class clazz) { - return Map.class.isAssignableFrom(clazz); - } - - public static Map getFieldValues(Object instance, - boolean prependClassName, - Set objectsToSkip) { - if (objectsToSkip == null) { - objectsToSkip = new HashSet<>(); - } - - Map output = new HashMap<>(); - - try { - if (objectsToSkip.add(instance)) { - Class clazz = instance.getClass(); - for (Class c = clazz; c != null; c = c.getSuperclass()) { - Field[] fields = c.getDeclaredFields(); - for (Field field : fields) { - if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) { - continue; - } - - String key; - if (prependClassName) { - key = String.format("%s.%s", clazz.getSimpleName(), field.getName()); - } else { - key = field.getName(); - } - - boolean accessible = field.isAccessible(); - if (!accessible) { - field.setAccessible(true); - } - Object fieldVal = field.get(instance); - if (fieldVal == null) { - continue; - } else if (fieldVal.getClass().isPrimitive() || - isWrapperType(fieldVal.getClass())) { - if (toString(fieldVal, false).isEmpty()) continue; - output.put(key, toString(fieldVal, false)); - } else if (isMapType(fieldVal.getClass())) { - //TODO: check if it makes more sense to just stick to json - // like structure instead of a flatten output. - Map map = (Map) fieldVal; - for (Object entry : map.entrySet()) { - Object mapKey = ((Map.Entry) entry).getKey(); - Object mapVal = ((Map.Entry) entry).getValue(); - - String keyStr = getString(mapKey, false, objectsToSkip); - String valStr = getString(mapVal, false, objectsToSkip); - if (StringUtils.isNotEmpty(valStr)) { - output.put(String.format("%s.%s", key, keyStr), valStr); - } - } - } else if (isCollectionType(fieldVal.getClass())) { - //TODO check if it makes more sense to just stick to - // json like structure instead of a flatten output. - Collection collection = (Collection) fieldVal; - if (collection.size() == 0) continue; - String outStr = ""; - for (Object o : collection) { - outStr += getString(o, false, objectsToSkip) + ","; - } - if (outStr.length() > 0) { - outStr = outStr.substring(0, outStr.length() - 1); - } - output.put(key, String.format("%s", outStr)); - } else { - Map nestedFieldValues = getFieldValues(fieldVal, false, objectsToSkip); - for (Map.Entry entry : nestedFieldValues.entrySet()) { - output.put(String.format("%s.%s", key, entry.getKey()), entry.getValue()); - } - } - if (!accessible) { - field.setAccessible(false); - } - } - } - } - } - catch (Exception e){ - LOG.warn("Exception while constructing topology", e); - } - return output; - } - - private static String getString(Object instance, - boolean wrapWithQuote, - Set objectsToSkip) { - if (instance == null) { - return null; - } else if (instance.getClass().isPrimitive() || isWrapperType(instance.getClass())) { - return toString(instance, wrapWithQuote); - } else { - return getString(getFieldValues(instance, false, objectsToSkip), wrapWithQuote); - } - } - - private static String getString(Map flattenFields, boolean wrapWithQuote) { - String outStr = ""; - if (flattenFields != null && !flattenFields.isEmpty()) { - if (wrapWithQuote) { - outStr += "\"" + Joiner.on(",").join(flattenFields.entrySet()) + "\","; - } else { - outStr += Joiner.on(",").join(flattenFields.entrySet()) + ","; - } - } - if (outStr.length() > 0) { - outStr = outStr.substring(0, outStr.length() - 1); - } - return outStr; - } - - private static String toString(Object instance, boolean wrapWithQuote) { - if (instance instanceof String) - if (wrapWithQuote) - return "\"" + instance + "\""; - else - return instance.toString(); - else - return instance.toString(); - } -} diff --git a/addons/storm-bridge/src/main/java/org/apache/atlas/storm/model/StormDataTypes.java b/addons/storm-bridge/src/main/java/org/apache/atlas/storm/model/StormDataTypes.java deleted file mode 100644 index 7eb1e3cb879..00000000000 --- a/addons/storm-bridge/src/main/java/org/apache/atlas/storm/model/StormDataTypes.java +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.storm.model; - - -/** - * Storm Data Types for model and hook. - */ -public enum StormDataTypes { - - // Topology Classes - STORM_TOPOLOGY, // represents the topology containing the DAG - - STORM_NODE, // base abstraction for producer and processor - STORM_SPOUT, // data producer node having only outputs - STORM_BOLT, // data processing node having both inputs and outputs - - // Data Sets - KAFKA_TOPIC, // kafka data set - JMS_TOPIC, // jms data set - HBASE_TABLE, // hbase table data set - ; - - public String getName() { - return name().toLowerCase(); - } -} diff --git a/addons/storm-bridge/src/test/java/org/apache/atlas/storm/hook/StormAtlasHookIT.java b/addons/storm-bridge/src/test/java/org/apache/atlas/storm/hook/StormAtlasHookIT.java deleted file mode 100644 index e11e1b8b0af..00000000000 --- a/addons/storm-bridge/src/test/java/org/apache/atlas/storm/hook/StormAtlasHookIT.java +++ /dev/null @@ -1,98 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.storm.hook; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasClient; -import org.apache.atlas.hive.bridge.HiveMetaStoreBridge; -import org.apache.atlas.v1.model.instance.Referenceable; -import org.apache.atlas.storm.model.StormDataTypes; -import org.apache.atlas.utils.AuthenticationUtil; -import org.apache.commons.configuration.Configuration; -import org.apache.storm.ILocalCluster; -import org.apache.storm.generated.StormTopology; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -@Test -public class StormAtlasHookIT { - - public static final Logger LOG = LoggerFactory.getLogger(StormAtlasHookIT.class); - - private static final String ATLAS_URL = "http://localhost:21000/"; - private static final String TOPOLOGY_NAME = "word-count"; - - private ILocalCluster stormCluster; - private AtlasClient atlasClient; - - @BeforeClass - public void setUp() throws Exception { - // start a local storm cluster - stormCluster = StormTestUtil.createLocalStormCluster(); - LOG.info("Created a storm local cluster"); - - Configuration configuration = ApplicationProperties.get(); - if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { - atlasClient = new AtlasClient(configuration.getStringArray(HiveMetaStoreBridge.ATLAS_ENDPOINT), new String[]{"admin", "admin"}); - } else { - atlasClient = new AtlasClient(configuration.getStringArray(HiveMetaStoreBridge.ATLAS_ENDPOINT)); - } - } - - - @AfterClass - public void tearDown() throws Exception { - LOG.info("Shutting down storm local cluster"); - stormCluster.shutdown(); - - atlasClient = null; - } - - @Test - public void testAddEntities() throws Exception { - StormTopology stormTopology = StormTestUtil.createTestTopology(); - StormTestUtil.submitTopology(stormCluster, TOPOLOGY_NAME, stormTopology); - LOG.info("Submitted topology {}", TOPOLOGY_NAME); - - // todo: test if topology metadata is registered in atlas - String guid = getTopologyGUID(); - Assert.assertNotNull(guid); - LOG.info("GUID is {}", guid); - - Referenceable topologyReferenceable = atlasClient.getEntity(guid); - Assert.assertNotNull(topologyReferenceable); - } - - private String getTopologyGUID() throws Exception { - LOG.debug("Searching for topology {}", TOPOLOGY_NAME); - String query = String.format("from %s where name = \"%s\"", - StormDataTypes.STORM_TOPOLOGY.getName(), TOPOLOGY_NAME); - - JsonNode results = atlasClient.search(query, 10, 0); - JsonNode row = results.get(0); - - return row.has("$id$") ? row.get("$id$").get("id").asText() : null; - } -} diff --git a/addons/storm-bridge/src/test/java/org/apache/atlas/storm/hook/StormTestUtil.java b/addons/storm-bridge/src/test/java/org/apache/atlas/storm/hook/StormTestUtil.java deleted file mode 100644 index d869f18cd71..00000000000 --- a/addons/storm-bridge/src/test/java/org/apache/atlas/storm/hook/StormTestUtil.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.storm.hook; - -import org.apache.storm.Config; -import org.apache.storm.ILocalCluster; -import org.apache.storm.Testing; -import org.apache.storm.generated.StormTopology; -import org.apache.storm.testing.TestGlobalCount; -import org.apache.storm.testing.TestWordCounter; -import org.apache.storm.testing.TestWordSpout; -import org.apache.storm.topology.TopologyBuilder; -import org.apache.storm.utils.Utils; - -import java.util.HashMap; - -/** - * An until to create a test topology. - */ -final class StormTestUtil { - - private StormTestUtil() { - } - - public static ILocalCluster createLocalStormCluster() { - // start a local storm cluster - HashMap localClusterConf = new HashMap<>(); - localClusterConf.put("nimbus-daemon", true); - return Testing.getLocalCluster(localClusterConf); - } - - public static StormTopology createTestTopology() { - TopologyBuilder builder = new TopologyBuilder(); - builder.setSpout("words", new TestWordSpout(), 10); - builder.setBolt("count", new TestWordCounter(), 3).shuffleGrouping("words"); - builder.setBolt("globalCount", new TestGlobalCount(), 2).shuffleGrouping("count"); - - return builder.createTopology(); - } - - public static Config submitTopology(ILocalCluster stormCluster, String topologyName, - StormTopology stormTopology) throws Exception { - Config stormConf = new Config(); - stormConf.putAll(Utils.readDefaultConfig()); - stormConf.put("storm.cluster.mode", "local"); - stormConf.setDebug(true); - stormConf.setMaxTaskParallelism(3); - stormConf.put(Config.STORM_TOPOLOGY_SUBMISSION_NOTIFIER_PLUGIN, - org.apache.atlas.storm.hook.StormAtlasHook.class.getName()); - - stormCluster.submitTopology(topologyName, stormConf, stormTopology); - - Thread.sleep(10000); - return stormConf; - } -} diff --git a/addons/storm-bridge/src/test/resources/atlas-application.properties b/addons/storm-bridge/src/test/resources/atlas-application.properties deleted file mode 100644 index b822578947c..00000000000 --- a/addons/storm-bridge/src/test/resources/atlas-application.properties +++ /dev/null @@ -1,126 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# - -######### Atlas Server Configs ######### -atlas.rest.address=http://localhost:31000 - - - -######### Graph Database Configs ######### - - -# Graph database implementation. Value inserted by maven. -atlas.graphdb.backend=org.apache.atlas.repository.graphdb.janus.AtlasJanusGraphDatabase - -# Graph Storage -atlas.graph.storage.backend=berkeleyje - -# Entity repository implementation -atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.InMemoryEntityAuditRepository - -# Graph Search Index Backend -atlas.graph.index.search.backend=solr - -#Berkeley storage directory -atlas.graph.storage.directory=${sys:atlas.data}/berkley - -#hbase -#For standalone mode , specify localhost -#for distributed mode, specify zookeeper quorum here - -atlas.graph.storage.hostname=${graph.storage.hostname} -atlas.graph.storage.hbase.regions-per-server=1 -atlas.graph.storage.lock.wait-time=10000 - -#ElasticSearch -atlas.graph.index.search.directory=${sys:atlas.data}/es -atlas.graph.index.search.elasticsearch.client-only=false -atlas.graph.index.search.elasticsearch.local-mode=true -atlas.graph.index.search.elasticsearch.create.sleep=2000 - -# Solr cloud mode properties -atlas.graph.index.search.solr.mode=cloud -atlas.graph.index.search.solr.zookeeper-url=${solr.zk.address} -atlas.graph.index.search.solr.embedded=true -atlas.graph.index.search.max-result-set-size=150 - - -######### Notification Configs ######### -atlas.notification.embedded=true - -atlas.kafka.zookeeper.connect=localhost:19026 -atlas.kafka.bootstrap.servers=localhost:19027 -atlas.kafka.data=${sys:atlas.data}/kafka -atlas.kafka.zookeeper.session.timeout.ms=4000 -atlas.kafka.zookeeper.sync.time.ms=20 -atlas.kafka.consumer.timeout.ms=4000 -atlas.kafka.auto.commit.interval.ms=100 -atlas.kafka.hook.group.id=atlas -atlas.kafka.entities.group.id=atlas_entities -#atlas.kafka.auto.commit.enable=false - -atlas.kafka.enable.auto.commit=false -atlas.kafka.auto.offset.reset=earliest -atlas.kafka.session.timeout.ms=30000 -atlas.kafka.offsets.topic.replication.factor=1 - - - -######### Entity Audit Configs ######### -atlas.audit.hbase.tablename=ATLAS_ENTITY_AUDIT_EVENTS -atlas.audit.zookeeper.session.timeout.ms=1000 -atlas.audit.hbase.zookeeper.quorum=localhost -atlas.audit.hbase.zookeeper.property.clientPort=19026 - -######### Security Properties ######### - -# SSL config -atlas.enableTLS=false -atlas.server.https.port=31443 - -######### Security Properties ######### - -hbase.security.authentication=simple - -atlas.hook.falcon.synchronous=true - -######### JAAS Configuration ######## - -atlas.jaas.KafkaClient.loginModuleName = com.sun.security.auth.module.Krb5LoginModule -atlas.jaas.KafkaClient.loginModuleControlFlag = required -atlas.jaas.KafkaClient.option.useKeyTab = true -atlas.jaas.KafkaClient.option.storeKey = true -atlas.jaas.KafkaClient.option.serviceName = kafka -atlas.jaas.KafkaClient.option.keyTab = /etc/security/keytabs/atlas.service.keytab -atlas.jaas.KafkaClient.option.principal = atlas/_HOST@EXAMPLE.COM - -######### High Availability Configuration ######## -atlas.server.ha.enabled=false -#atlas.server.ids=id1 -#atlas.server.address.id1=localhost:21000 - -######### Atlas Authorization ######### -atlas.authorizer.impl=none -# atlas.authorizer.impl=simple -# atlas.authorizer.simple.authz.policy.file=atlas-simple-authz-policy.json - -######### Atlas Authentication ######### -atlas.authentication.method.file=true -atlas.authentication.method.ldap.type=none -atlas.authentication.method.kerberos=false -# atlas.authentication.method.file.filename=users-credentials.properties diff --git a/addons/storm-bridge/src/test/resources/atlas-log4j.xml b/addons/storm-bridge/src/test/resources/atlas-log4j.xml deleted file mode 100755 index 262a710f7aa..00000000000 --- a/addons/storm-bridge/src/test/resources/atlas-log4j.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/addons/storm-bridge/src/test/resources/users-credentials.properties b/addons/storm-bridge/src/test/resources/users-credentials.properties deleted file mode 100644 index 5046dbaf646..00000000000 --- a/addons/storm-bridge/src/test/resources/users-credentials.properties +++ /dev/null @@ -1,3 +0,0 @@ -#username=group::sha256-password -admin=ADMIN::a4a88c0872bf652bb9ed803ece5fd6e82354838a9bf59ab4babb1dab322154e1 -rangertagsync=RANGER_TAG_SYNC::0afe7a1968b07d4c3ff4ed8c2d809a32ffea706c66cd795ead9048e81cfaf034 diff --git a/atlas-examples/pom.xml b/atlas-examples/pom.xml deleted file mode 100644 index 1ff213cb380..00000000000 --- a/atlas-examples/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - apache-atlas - org.apache.atlas - 3.0.0-SNAPSHOT - - 4.0.0 - - atlas-examples - pom - - sample-app - - - - \ No newline at end of file diff --git a/atlas-examples/sample-app/README.md b/atlas-examples/sample-app/README.md deleted file mode 100644 index 65ac54c3dc2..00000000000 --- a/atlas-examples/sample-app/README.md +++ /dev/null @@ -1,13 +0,0 @@ -## Introduction -This is a simple application to demonstrate the use of AtlasClient. SampleApp provides examples to use following Client APIs. -1. TypeDef -2. Entity -3. Lineage -4. Search -5. Glossary - -## Setting up -1. cd ~/Desktop/atlas/atlas-examples/sample-app (the location where you have downloaded sample-app) -2. mvn clean install -3. mvn exec:java -4. Then it will ask you to enter AtlasServer URL, username and password. \ No newline at end of file diff --git a/atlas-examples/sample-app/pom.xml b/atlas-examples/sample-app/pom.xml deleted file mode 100644 index aa3c6374feb..00000000000 --- a/atlas-examples/sample-app/pom.xml +++ /dev/null @@ -1,104 +0,0 @@ - - - - - atlas-examples - org.apache.atlas - 3.0.0-SNAPSHOT - - 4.0.0 - - sample-app - - - - org.apache.atlas - atlas-client-common - ${project.version} - - - org.apache.atlas - atlas-common - ${project.version} - - - - org.apache.atlas - atlas-client-v2 - ${project.version} - - - - org.apache.atlas - atlas-intg - ${project.version} - - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - - - com.fasterxml.jackson.core - jackson-core - - - com.fasterxml.jackson.core - jackson-annotations - - - - - - com.fasterxml.jackson.core - jackson-core - ${jackson.version} - - - - com.fasterxml.jackson.core - jackson-annotations - ${jackson.version} - - - - - - - - org.codehaus.mojo - exec-maven-plugin - - - - java - - - - - org.apache.atlas.examples.sampleapp.SampleApp - - - - - - \ No newline at end of file diff --git a/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/DiscoveryExample.java b/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/DiscoveryExample.java deleted file mode 100644 index d309c9ed441..00000000000 --- a/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/DiscoveryExample.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.examples.sampleapp; - -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.AtlasServiceException; -import org.apache.atlas.model.discovery.AtlasQuickSearchResult; -import org.apache.atlas.model.discovery.AtlasSearchResult; -import org.apache.atlas.model.instance.AtlasEntityHeader; - -import java.util.List; - -public class DiscoveryExample { - private static final String[] DSL_QUERIES = new String[] { "from DataSet", "from Process" }; - - private final AtlasClientV2 client; - - DiscoveryExample(AtlasClientV2 client) { - this.client = client; - } - - public void testSearch() { - for (String dslQuery : DSL_QUERIES) { - try { - AtlasSearchResult result = client.dslSearchWithParams(dslQuery, 10, 0); - List entities = result != null ? result.getEntities() : null; - int resultCount = entities == null ? 0 : entities.size(); - - SampleApp.log("DSL Query: " + dslQuery); - SampleApp.log(" result count: " + resultCount); - - for (int i = 0; i < resultCount; i++) { - SampleApp.log(" result # " + (i + 1) + ": " + entities.get(i)); - } - } catch (Exception e) { - SampleApp.log("query -: " + dslQuery + " failed"); - } - } - } - - public void quickSearch(String searchString) { - try { - AtlasQuickSearchResult result = client.quickSearch(searchString, SampleAppConstants.TABLE_TYPE, false, 2, 0); - List entities = result != null && result.getSearchResults() != null ? result.getSearchResults().getEntities() : null; - int resultCount = entities == null ? 0 : entities.size(); - - SampleApp.log("Quick search: query-string=" + searchString); - SampleApp.log(" result count: " + resultCount); - - for (int i = 0; i < resultCount; i++) { - SampleApp.log(" result # " + (i + 1) + ": " + entities.get(i)); - } - } catch (AtlasServiceException e) { - e.printStackTrace(); - } - } - - public void basicSearch(String typeName, String classification, String query) { - try { - AtlasSearchResult result = client.basicSearch(typeName, classification, query, false, 2, 0); - List entities = result != null ? result.getEntities() : null; - int resultCount = entities == null ? 0 : entities.size(); - - SampleApp.log("Basic search: typeName=" + typeName + ", classification=" + classification + ", query=" + query); - SampleApp.log(" result count: " + resultCount); - - for (int i = 0; i < resultCount; i++) { - SampleApp.log(" result # " + (i + 1) + ": " + entities.get(i)); - } - } catch (AtlasServiceException e) { - e.printStackTrace(); - } - } -} diff --git a/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/EntityExample.java b/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/EntityExample.java deleted file mode 100644 index 3d9d4845b09..00000000000 --- a/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/EntityExample.java +++ /dev/null @@ -1,277 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.examples.sampleapp; - -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.AtlasServiceException; -import org.apache.atlas.model.instance.AtlasClassification; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; -import org.apache.atlas.model.instance.AtlasEntityHeader; -import org.apache.atlas.model.instance.AtlasStruct; -import org.apache.atlas.model.instance.EntityMutationResponse; -import org.apache.atlas.model.instance.EntityMutations; -import org.apache.atlas.type.AtlasTypeUtil; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static java.util.Arrays.asList; -import static org.apache.atlas.examples.sampleapp.SampleAppConstants.*; -import static org.apache.atlas.type.AtlasTypeUtil.toAtlasRelatedObjectId; -import static org.apache.atlas.type.AtlasTypeUtil.toAtlasRelatedObjectIds; - -public class EntityExample { - private static final String DATABASE_NAME = "employee_db_entity"; - private static final String TABLE_NAME = "employee_table_entity"; - private static final String PROCESS_NAME = "employee_process_entity"; - private static final String METADATA_NAMESPACE_SUFFIX = "@cl1"; - private static final String MANAGED_TABLE = "Managed"; - private static final String ATTR_NAME = "name"; - private static final String ATTR_DESCRIPTION = "description"; - private static final String ATTR_QUALIFIED_NAME = "qualifiedName"; - private static final String REFERENCEABLE_ATTRIBUTE_NAME = ATTR_QUALIFIED_NAME; - private static final String COLUMN_TIME_ID = "time_id"; - private static final String COLUMN_CUSTOMER_ID = "customer_id"; - private static final String COLUMN_COMPANY_ID = "company_id"; - - private final AtlasClientV2 client; - private AtlasEntity dbEntity; - private AtlasEntity tableEntityUS; - private AtlasEntity tableEntityCanada; - private AtlasEntityHeader loadProcess; - - EntityExample(AtlasClientV2 client) { - this.client = client; - } - - public void createEntities() throws Exception { - if (dbEntity == null) { - dbEntity = createDatabaseEntity(DATABASE_NAME); - - SampleApp.log("Created entity: typeName=" + dbEntity.getTypeName() + ", qualifiedName=" + dbEntity.getAttribute(ATTR_QUALIFIED_NAME) + ", guid=" + dbEntity.getGuid()); - } - - if (tableEntityCanada == null) { - tableEntityCanada = createTableEntity(TABLE_NAME + "_CANADA"); - - SampleApp.log("Created entity: typeName=" + tableEntityCanada.getTypeName() + ", qualifiedName=" + tableEntityCanada.getAttribute(ATTR_QUALIFIED_NAME) + ", guid=" + tableEntityCanada.getGuid()); - } - - if (tableEntityUS == null) { - tableEntityUS = createTableEntity(TABLE_NAME + "_US"); - - SampleApp.log("Created entity: typeName=" + tableEntityUS.getTypeName() + ", qualifiedName=" + tableEntityUS.getAttribute(ATTR_QUALIFIED_NAME) + ", guid=" + tableEntityUS.getGuid()); - } - - if (loadProcess == null) { - loadProcess = createProcessEntity(PROCESS_NAME); - - SampleApp.log("Created entity: typeName=" + loadProcess.getTypeName() + ", qualifiedName=" + loadProcess.getAttribute(ATTR_QUALIFIED_NAME) + ", guid=" + loadProcess.getGuid()); - } - } - - public AtlasEntity getTableEntity() { - return tableEntityUS; - } - - public void getEntityByGuid(String entityGuid) throws Exception { - AtlasEntityWithExtInfo entity = client.getEntityByGuid(entityGuid); - - if (entity != null) { - SampleApp.log("Retrieved entity with guid=" + entityGuid); - SampleApp.log(" " + entity); - } - } - - public void deleteEntities() throws Exception { - client.deleteEntityByGuid(loadProcess.getGuid()); - - SampleApp.log("Deleted entity: guid=" + loadProcess.getGuid()); - - List entityGuids = Arrays.asList(tableEntityUS.getGuid(), tableEntityCanada.getGuid(), dbEntity.getGuid()); - - client.deleteEntitiesByGuids(entityGuids); - - SampleApp.log("Deleted entities:"); - for (String entityGuid : entityGuids) { - SampleApp.log(" guid=" + entityGuid); - } - } - - private AtlasEntity createTableEntity(String tableName) throws Exception { - return createHiveTable(dbEntity, tableName, MANAGED_TABLE, - Arrays.asList(createColumn(COLUMN_TIME_ID, "int", "time id"), - createColumn(COLUMN_CUSTOMER_ID, "int", "customer id", SampleAppConstants.PII_TAG), - createColumn(COLUMN_COMPANY_ID, "double", "company id", SampleAppConstants.FINANCE_TAG)), - SampleAppConstants.METRIC_TAG); - } - - private AtlasEntityHeader createProcessEntity(String processName) throws Exception { - return createProcess(processName, "hive query for monthly avg salary", "user ETL", - asList(tableEntityUS), - asList(tableEntityCanada), - "create table as select ", "plan", "id", "graph", SampleAppConstants.CLASSIFIED_TAG); - } - - private AtlasEntityHeader createProcess(String name, String description, String user, List inputs, List outputs, - String queryText, String queryPlan, String queryId, String queryGraph, String... classificationNames) throws Exception { - - AtlasEntity entity = new AtlasEntity(SampleAppConstants.PROCESS_TYPE); - - entity.setAttribute(ATTR_NAME, name); - entity.setAttribute(REFERENCEABLE_ATTRIBUTE_NAME, name + METADATA_NAMESPACE_SUFFIX); - entity.setAttribute(ATTR_DESCRIPTION, description); - entity.setAttribute(ATTR_USERNAME, user); - entity.setAttribute(ATTR_START_TIME, System.currentTimeMillis()); - entity.setAttribute(ATTR_END_TIME, System.currentTimeMillis() + 10000); - entity.setAttribute(ATTR_QUERY_TEXT, queryText); - entity.setAttribute(ATTR_QUERY_PLAN, queryPlan); - entity.setAttribute(ATTR_QUERY_ID, queryId); - entity.setAttribute(ATTR_QUERY_GRAPH, queryGraph); - entity.setAttribute(ATTR_OPERATION_TYPE, "testOperation"); - - entity.setRelationshipAttribute(ATTR_INPUTS, toAtlasRelatedObjectIds(inputs)); - entity.setRelationshipAttribute(ATTR_OUTPUTS, toAtlasRelatedObjectIds(outputs)); - - entity.setClassifications(toAtlasClassifications(classificationNames)); - - return createEntity(new AtlasEntityWithExtInfo(entity)); - } - - private AtlasEntity createColumn(String name, String dataType, String comment, String... classificationNames) { - AtlasEntity ret = new AtlasEntity(SampleAppConstants.COLUMN_TYPE); - - ret.setAttribute(ATTR_NAME, name); - ret.setAttribute(REFERENCEABLE_ATTRIBUTE_NAME, name + METADATA_NAMESPACE_SUFFIX); - ret.setAttribute(ATTR_DATA_TYPE, dataType); - ret.setAttribute(ATTR_COMMENT, comment); - - ret.setClassifications(toAtlasClassifications(classificationNames)); - - return ret; - } - - private List toAtlasClassifications(String[] classificationNames) { - List ret = new ArrayList<>(); - - if (classificationNames != null) { - for (String classificationName : classificationNames) { - ret.add(new AtlasClassification(classificationName)); - } - } - - return ret; - } - - private AtlasEntityHeader createEntity(AtlasEntityWithExtInfo atlasEntityWithExtInfo) { - EntityMutationResponse entity; - - try { - entity = client.createEntity(atlasEntityWithExtInfo); - - if (entity != null && entity.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE) != null) { - List list = entity.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE); - - if (list.size() > 0) { - return entity.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE).get(0); - } - } - } catch (AtlasServiceException e) { - SampleApp.log("failed in create entity"); - e.printStackTrace(); - } - - return null; - } - - private AtlasEntity createDatabaseEntity(String dbName) { - AtlasEntity hiveDBInstance = createHiveDBInstance(dbName); - AtlasEntityHeader entityHeader = createEntity(new AtlasEntityWithExtInfo(hiveDBInstance)); - - if (entityHeader != null && entityHeader.getGuid() != null) { - hiveDBInstance.setGuid(entityHeader.getGuid()); - } - - return hiveDBInstance; - } - - protected AtlasEntity createHiveDBInstance(String dbName) { - AtlasEntity entity = new AtlasEntity(SampleAppConstants.DATABASE_TYPE); - - entity.setAttribute(ATTR_NAME, dbName); - entity.setAttribute(ATTR_DESCRIPTION, "employee database"); - entity.setAttribute(METADATA_NAMESPACE_SUFFIX, "employeeCluster"); - entity.setAttribute(REFERENCEABLE_ATTRIBUTE_NAME, dbName + METADATA_NAMESPACE_SUFFIX); - entity.setAttribute(ATTR_OWNER, "user"); - entity.setAttribute(ATTR_LOCATION_URI, "/tmp"); - entity.setAttribute(ATTR_CREATE_TIME, 1000); - - return entity; - } - - private AtlasEntity createHiveTable(AtlasEntity database, String tableName, String tableType, List columns, String... classificationNames) throws Exception { - AtlasEntityWithExtInfo entityWithExtInfo = new AtlasEntityWithExtInfo(); - - AtlasEntity hiveTableInstance = createHiveTable(database, tableName, tableType, classificationNames); - entityWithExtInfo.setEntity(hiveTableInstance); - hiveTableInstance.setRelationshipAttribute(ATTR_COLUMNS, toAtlasRelatedObjectIds(columns)); - - for (AtlasEntity column : columns) { - column.setRelationshipAttribute(ATTR_TABLE, toAtlasRelatedObjectId(hiveTableInstance)); - entityWithExtInfo.addReferredEntity(column); - } - - AtlasEntityHeader createdHeader = createEntity(entityWithExtInfo); - - if (createdHeader != null && createdHeader.getGuid() != null) { - hiveTableInstance.setGuid(createdHeader.getGuid()); - } - - return hiveTableInstance; - } - - private AtlasEntity createHiveTable(AtlasEntity database, String tableName, String tableType, String... classificationNames) throws Exception { - AtlasEntity table = new AtlasEntity(SampleAppConstants.TABLE_TYPE); - - table.setAttribute(ATTR_NAME, tableName); - table.setAttribute(REFERENCEABLE_ATTRIBUTE_NAME, database.getAttribute(ATTR_NAME) + "." + tableName + METADATA_NAMESPACE_SUFFIX); - table.setAttribute(ATTR_TABLE_TYPE, tableType); - table.setRelationshipAttribute(ATTR_DB, AtlasTypeUtil.getAtlasRelatedObjectId(database, TABLE_DATABASE_TYPE)); - - table.setAttribute(ATTR_DESCRIPTION, "emp table"); - table.setAttribute(ATTR_LAST_ACCESS_TIME, "2014-07-11T08:00:00.000Z"); - table.setAttribute(ATTR_LEVEL, 2); - table.setAttribute(ATTR_COMPRESSED, false); - table.setClassifications(toAtlasClassifications(classificationNames)); - - AtlasStruct serde1 = new AtlasStruct(STRUCT_TYPE_SERDE); - - serde1.setAttribute(ATTR_NAME, "serde1"); - serde1.setAttribute(ATTR_SERDE, "serde1"); - table.setAttribute(ATTR_SERDE1, serde1); - - AtlasStruct serde2 = new AtlasStruct(STRUCT_TYPE_SERDE); - serde2.setAttribute(ATTR_NAME, "serde2"); - serde2.setAttribute(ATTR_SERDE, "serde2"); - table.setAttribute(ATTR_SERDE2, serde2); - - return table; - } -} \ No newline at end of file diff --git a/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/GlossaryExample.java b/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/GlossaryExample.java deleted file mode 100644 index 7d5690ce8c4..00000000000 --- a/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/GlossaryExample.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.examples.sampleapp; - -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.model.glossary.AtlasGlossary; -import org.apache.atlas.model.glossary.AtlasGlossary.AtlasGlossaryExtInfo; -import org.apache.atlas.model.glossary.AtlasGlossaryCategory; -import org.apache.atlas.model.glossary.AtlasGlossaryTerm; -import org.apache.atlas.model.glossary.relations.AtlasGlossaryHeader; - -public class GlossaryExample { - private static final String GLOSSARY_NAME = "EmployeeCountry"; - - private final AtlasClientV2 client; - private AtlasGlossary empGlossary; - private AtlasGlossaryTerm empSalaryTerm; - private AtlasGlossaryCategory empCompanyCategory; - - GlossaryExample(AtlasClientV2 client) { - this.client = client; - } - - public void createGlossary() throws Exception { - AtlasGlossary glossary = new AtlasGlossary(); - - glossary.setName(GLOSSARY_NAME); - glossary.setLanguage("English"); - glossary.setShortDescription("This is a test Glossary"); - - empGlossary = client.createGlossary(glossary); - } - - public void getGlossaryDetail() throws Exception { - AtlasGlossaryExtInfo extInfo = client.getGlossaryExtInfo(empGlossary.getGuid()); - - assert (extInfo != null); - - SampleApp.log("Glossary extended info: " + extInfo.getGuid() + "; name: " + extInfo.getName() + "; language: " + extInfo.getLanguage()); - } - - public void createGlossaryTerm() throws Exception { - if (empSalaryTerm != null) { - SampleApp.log("EmpSalaryTerm: term already exists"); - return; - } - - AtlasGlossaryHeader glossary = new AtlasGlossaryHeader(); - AtlasGlossaryTerm term = new AtlasGlossaryTerm(); - - glossary.setGlossaryGuid(empGlossary.getGuid()); - glossary.setDisplayText(empGlossary.getName()); - - term.setAnchor(glossary); - term.setName("EmpSalaryTerm"); - - empSalaryTerm = client.createGlossaryTerm(term); - - if (empSalaryTerm != null) { - SampleApp.log("Created term for Employee Salary: " + empSalaryTerm); - } - } - - public void createGlossaryCategory() throws Exception { - if (empCompanyCategory != null) { - SampleApp.log("EmpSalaryCategory: category already exists"); - return; - } - - AtlasGlossaryHeader glossary = new AtlasGlossaryHeader(); - AtlasGlossaryCategory category = new AtlasGlossaryCategory(); - - glossary.setGlossaryGuid(empGlossary.getGuid()); - glossary.setDisplayText(empGlossary.getName()); - - category.setAnchor(glossary); - category.setName("EmpSalaryCategory"); - - empCompanyCategory = client.createGlossaryCategory(category); - - if (empCompanyCategory != null) { - SampleApp.log("Created Category for Employee Category :- " + empCompanyCategory); - } - } - - public void deleteGlossary() throws Exception { - if (empGlossary != null) { - client.deleteGlossaryByGuid(empGlossary.getGuid()); - - SampleApp.log("empGlossary is not present. Skipping the delete operation."); - } - - empGlossary = null; - empSalaryTerm = null; - empCompanyCategory = null; - } -} diff --git a/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/LineageExample.java b/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/LineageExample.java deleted file mode 100644 index aba3b812d63..00000000000 --- a/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/LineageExample.java +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.examples.sampleapp; - -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.AtlasServiceException; -import org.apache.atlas.model.instance.AtlasEntityHeader; -import org.apache.atlas.model.lineage.AtlasLineageInfo; - -import java.util.Map; -import java.util.Set; - -public class LineageExample { - private AtlasClientV2 atlasClient; - - LineageExample(AtlasClientV2 atlasClient) { - this.atlasClient = atlasClient; - } - - public void lineage(String guid) throws AtlasServiceException { - AtlasLineageInfo lineageInfo = atlasClient.getLineageInfo(guid, AtlasLineageInfo.LineageDirection.BOTH, 0); - Set relations = lineageInfo.getRelations(); - Map guidEntityMap = lineageInfo.getGuidEntityMap(); - - for (AtlasLineageInfo.LineageRelation relation : relations) { - AtlasEntityHeader fromEntity = guidEntityMap.get(relation.getFromEntityId()); - AtlasEntityHeader toEntity = guidEntityMap.get(relation.getToEntityId()); - - SampleApp.log(fromEntity.getDisplayText() + "(" + fromEntity.getTypeName() + ") -> " + - toEntity.getDisplayText() + "(" + toEntity.getTypeName() + ")"); - } - } -} \ No newline at end of file diff --git a/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/SampleApp.java b/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/SampleApp.java deleted file mode 100644 index f663de16be6..00000000000 --- a/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/SampleApp.java +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.examples.sampleapp; - -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.AtlasException; -import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.utils.AuthenticationUtil; - -import java.util.Date; - -public class SampleApp { - private AtlasClientV2 client; - - SampleApp(String[] atlasServerUrls, String[] basicAuthUsernamePassword) { - client = new AtlasClientV2(atlasServerUrls, basicAuthUsernamePassword); - } - - SampleApp(String[] atlasServerUrls) throws AtlasException { - client = new AtlasClientV2(atlasServerUrls); - } - - public static void main(String[] args) throws Exception { - SampleApp sampleApp = null; - - try { - if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { - String[] atlasServerUrls = getServerUrl(); - String[] basicAuthUsernamePassword = getUserInput(); - - sampleApp = new SampleApp(atlasServerUrls, basicAuthUsernamePassword); - } else { - String[] atlasServerUrls = getServerUrl(); - - sampleApp = new SampleApp(atlasServerUrls); - } - - // TypeDef Examples - TypeDefExample typeDefExample = new TypeDefExample(sampleApp.getClient()); - - typeDefExample.createTypeDefinitions(); - typeDefExample.printTypeDefinitions(); - - // Entity Examples - EntityExample entityExample = new EntityExample(sampleApp.getClient()); - - entityExample.createEntities(); - - AtlasEntity createdEntity = entityExample.getTableEntity(); - - entityExample.getEntityByGuid(createdEntity.getGuid()); - - // Lineage Examples - sampleApp.lineageExample(createdEntity.getGuid()); - - // Discovery/Search Examples - sampleApp.discoveryExample(createdEntity); - - // Glossary Examples - sampleApp.glossaryExample(); - - entityExample.deleteEntities(); - } finally { - if (sampleApp != null && sampleApp.getClient() != null) { - sampleApp.getClient().close(); - } - } - } - - public static void log(String message) { - System.out.println("[" + new Date() + "] " + message); - } - - public AtlasClientV2 getClient() { - return client; - } - - private void lineageExample(String entityGuid) throws Exception { - LineageExample lineageExample = new LineageExample(client); - - lineageExample.lineage(entityGuid); - } - - private void discoveryExample(AtlasEntity entity) { - DiscoveryExample discoveryExample = new DiscoveryExample(client); - - discoveryExample.testSearch(); - discoveryExample.quickSearch(entity.getTypeName()); - discoveryExample.basicSearch(entity.getTypeName(), SampleAppConstants.METRIC_TAG, (String)entity.getAttribute(SampleAppConstants.ATTR_NAME)); - } - - private void glossaryExample() throws Exception { - GlossaryExample glossaryExample = new GlossaryExample(client); - - glossaryExample.createGlossary(); - glossaryExample.createGlossaryTerm(); - glossaryExample.getGlossaryDetail(); - glossaryExample.createGlossaryCategory(); - glossaryExample.deleteGlossary(); - } - - private static String[] getUserInput() { - try { - String username = System.console().readLine("Enter username: "); - char[] pwChar = System.console().readPassword("Enter password: "); - String password = (pwChar != null) ? new String(pwChar) : ""; - - return new String[] { username, password }; - } catch (Exception e) { - System.out.print("Error while reading user input"); - System.exit(1); - } - - return null; // will not reach here - } - - private static String[] getServerUrl() { - try { - String atlasServerUrl = System.console().readLine("Enter Atlas server URL: "); - - return new String[] { atlasServerUrl }; - } catch (Exception e) { - System.out.print("Error while reading user input"); - System.exit(1); - } - - return null; // will not reach here - } -} \ No newline at end of file diff --git a/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/SampleAppConstants.java b/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/SampleAppConstants.java deleted file mode 100644 index 4b7b44dc959..00000000000 --- a/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/SampleAppConstants.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.examples.sampleapp; - -public final class SampleAppConstants { - public static final String ATTR_NAME = "name"; - public static final String ATTR_DESCRIPTION = "description"; - public static final String ATTR_CREATE_TIME = "createTime"; - public static final String ATTR_OWNER = "owner"; - public static final String ATTR_TABLE_TYPE = "tableType"; - public static final String ATTR_LAST_ACCESS_TIME = "lastAccessTime"; - public static final String ATTR_RANDOM_TABLE = "randomTable"; - public static final String ATTR_TEMPORARY = "temporary"; - public static final String ATTR_DATA_TYPE = "dataType"; - public static final String ATTR_COMMENT = "comment"; - public static final String ATTR_LOCATION_URI = "locationUri"; - public static final String ATTR_USERNAME = "userName"; - public static final String ATTR_START_TIME = "startTime"; - public static final String ATTR_END_TIME = "endTime"; - public static final String ATTR_QUERY_TEXT = "queryText"; - public static final String ATTR_QUERY_PLAN = "queryPlan"; - public static final String ATTR_QUERY_ID = "queryId"; - public static final String ATTR_QUERY_GRAPH = "queryGraph"; - public static final String ATTR_OPERATION_TYPE = "operationType"; - public static final String ATTR_LEVEL = "level"; - public static final String ATTR_COMPRESSED = "compressed"; - public static final String ATTR_SERDE = "serde"; - public static final String ATTR_SERDE1 = "serde1"; - public static final String ATTR_SERDE2 = "serde2"; - public static final String ATTR_ATTR1 = "attr1"; - public static final String ATTR_ATTR2 = "attr2"; - public static final String ATTR_ATTR8 = "attr8"; - public static final String ATTR_ATTR11 = "attr11"; - public static final String ATTR_ATTR18 = "attr88"; - public static final String ATTR_INPUTS = "inputs"; - public static final String ATTR_OUTPUTS = "outputs"; - public static final String ATTR_DB = "db"; - public static final String ATTR_TABLE = "table"; - public static final String ATTR_COLUMNS = "columns"; - - public static final String ENTITY_TYPE_DATASET = "DataSet"; - public static final String ENTITY_TYPE_PROCESS = "Process"; - - public static final String PII_TAG = "SAMPLE_PII"; - public static final String FINANCE_TAG = "SAMPLE_FINANCE"; - public static final String CLASSIFIED_TAG = "SAMPLE_CLASSIFIED"; - public static final String METRIC_TAG = "SAMPLE_METRIC"; - - public static final String DATABASE_TYPE = "sample_db_type"; - public static final String PROCESS_TYPE = "sample_process_type"; - public static final String TABLE_TYPE = "sample_table_type"; - public static final String COLUMN_TYPE = "sample_column_type"; - - public static final String TABLE_DATABASE_TYPE = "sample_db_tables"; - public static final String TABLE_COLUMNS_TYPE = "sample_table_columns"; - public static final String ENUM_TABLE_TYPE = "sample_tableType"; - public static final String BUSINESS_METADATA_TYPE = "sample_bmWithAllTypes"; - public static final String BUSINESS_METADATA_TYPE_MV = "sample_bmWithAllTypesMV"; - public static final String STRUCT_TYPE_SERDE = "sample_serdeType"; -} diff --git a/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/TypeDefExample.java b/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/TypeDefExample.java deleted file mode 100644 index be89bd1b60b..00000000000 --- a/atlas-examples/sample-app/src/main/java/org/apache/atlas/examples/sampleapp/TypeDefExample.java +++ /dev/null @@ -1,274 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.examples.sampleapp; - -import com.sun.jersey.core.util.MultivaluedMapImpl; -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.AtlasServiceException; -import org.apache.atlas.model.SearchFilter; -import org.apache.atlas.model.typedef.AtlasBaseTypeDef; -import org.apache.atlas.model.typedef.AtlasBusinessMetadataDef; -import org.apache.atlas.model.typedef.AtlasClassificationDef; -import org.apache.atlas.model.typedef.AtlasEntityDef; -import org.apache.atlas.model.typedef.AtlasEnumDef; -import org.apache.atlas.model.typedef.AtlasRelationshipDef; -import org.apache.atlas.model.typedef.AtlasStructDef; -import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef; -import org.apache.atlas.model.typedef.AtlasTypesDef; -import org.apache.atlas.type.AtlasTypeUtil; - -import javax.ws.rs.core.MultivaluedMap; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.apache.atlas.examples.sampleapp.SampleAppConstants.*; -import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.*; -import static org.apache.atlas.model.typedef.AtlasRelationshipDef.RelationshipCategory.AGGREGATION; -import static org.apache.atlas.model.typedef.AtlasRelationshipDef.RelationshipCategory.COMPOSITION; -import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality.SET; -import static org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE; -import static org.apache.atlas.type.AtlasTypeUtil.createBusinessMetadataDef; -import static org.apache.atlas.type.AtlasTypeUtil.createOptionalAttrDef; -import static org.apache.atlas.type.AtlasTypeUtil.createRelationshipEndDef; -import static org.apache.atlas.type.AtlasTypeUtil.createRelationshipTypeDef; -import static org.apache.atlas.type.AtlasTypeUtil.createTraitTypeDef; - -public class TypeDefExample { - private static final String[] SAMPLE_APP_TYPES = { - SampleAppConstants.DATABASE_TYPE, - SampleAppConstants.TABLE_TYPE, - SampleAppConstants.COLUMN_TYPE, - SampleAppConstants.PROCESS_TYPE, - SampleAppConstants.PII_TAG, - SampleAppConstants.CLASSIFIED_TAG, - SampleAppConstants.FINANCE_TAG, - SampleAppConstants.METRIC_TAG - }; - - private final AtlasClientV2 client; - private AtlasTypesDef typesDef; - - TypeDefExample(AtlasClientV2 client) { - this.client = client; - } - - public void createTypeDefinitions() throws Exception { - AtlasEntityDef databaseDef = createDatabaseDef(); - AtlasEntityDef tableDef = createTableDef(); - AtlasEntityDef columnDef = createColumnDef(); - AtlasEntityDef processDef = createProcessDef(); - AtlasStructDef serDeDef = createSerDeDef(); - AtlasEnumDef tableTypeDef = createTableTypeEnumDef(); - - List classificationDefs = createClassificationDefs(); - List businessMetadataDef = createBusinessMetadataDefs(); - List relationshipDefs = createAtlasRelationshipDef(); - - AtlasTypesDef typesDef = new AtlasTypesDef(Collections.singletonList(tableTypeDef), - Collections.singletonList(serDeDef), - classificationDefs, - Arrays.asList(databaseDef, tableDef, columnDef, processDef), - relationshipDefs, - businessMetadataDef); - - this.typesDef = batchCreateTypes(typesDef); - } - - public void printTypeDefinitions() throws AtlasServiceException { - for (String typeName : SAMPLE_APP_TYPES) { - MultivaluedMap searchParams = new MultivaluedMapImpl(); - - searchParams.add(SearchFilter.PARAM_NAME, typeName); - - SearchFilter searchFilter = new SearchFilter(searchParams); - - AtlasTypesDef typesDef = client.getAllTypeDefs(searchFilter); - - assert (!typesDef.isEmpty()); - - SampleApp.log("Created type: " + typeName); - } - } - - public void removeTypeDefinitions() throws AtlasServiceException { - if (typesDef != null) { - client.deleteAtlasTypeDefs(typesDef); - - typesDef = null; - - SampleApp.log("Deleted TypesDef successfully!"); - } - } - - private AtlasEntityDef createDatabaseDef() { - return AtlasTypeUtil.createClassTypeDef(SampleAppConstants.DATABASE_TYPE, - Collections.singleton(ENTITY_TYPE_DATASET), - AtlasTypeUtil.createOptionalAttrDef("locationUri", "string"), - AtlasTypeUtil.createOptionalAttrDef(ATTR_CREATE_TIME, "long"), - new AtlasAttributeDef(ATTR_RANDOM_TABLE, - AtlasBaseTypeDef.getArrayTypeName(SampleAppConstants.TABLE_TYPE), - true, AtlasAttributeDef.Cardinality.SET)); - } - - private AtlasEntityDef createTableDef() { - return AtlasTypeUtil.createClassTypeDef(SampleAppConstants.TABLE_TYPE, - Collections.singleton(ENTITY_TYPE_DATASET), - createOptionalAttrDef(ATTR_CREATE_TIME, "long"), - createOptionalAttrDef(ATTR_LAST_ACCESS_TIME, "date"), - createOptionalAttrDef(ATTR_TEMPORARY, "boolean"), - createOptionalAttrDef(ATTR_TABLE_TYPE, ENUM_TABLE_TYPE), - createOptionalAttrDef(ATTR_SERDE1, STRUCT_TYPE_SERDE), - createOptionalAttrDef(ATTR_SERDE2, STRUCT_TYPE_SERDE)); - } - - private AtlasEntityDef createColumnDef() { - return AtlasTypeUtil.createClassTypeDef(SampleAppConstants.COLUMN_TYPE, - Collections.singleton(ENTITY_TYPE_DATASET), - AtlasTypeUtil.createOptionalAttrDef(ATTR_DATA_TYPE, "string"), - AtlasTypeUtil.createOptionalAttrDef(ATTR_COMMENT, "string")); - } - - private AtlasEntityDef createProcessDef() { - return AtlasTypeUtil.createClassTypeDef(SampleAppConstants.PROCESS_TYPE, - Collections.singleton(ENTITY_TYPE_PROCESS), - AtlasTypeUtil.createOptionalAttrDef(ATTR_USERNAME, "string"), - AtlasTypeUtil.createOptionalAttrDef(ATTR_START_TIME, "long"), - AtlasTypeUtil.createOptionalAttrDef(ATTR_END_TIME, "long"), - AtlasTypeUtil.createRequiredAttrDef(ATTR_QUERY_TEXT, "string"), - AtlasTypeUtil.createRequiredAttrDef(ATTR_QUERY_PLAN, "string"), - AtlasTypeUtil.createRequiredAttrDef(ATTR_QUERY_ID, "string"), - AtlasTypeUtil.createRequiredAttrDef(ATTR_QUERY_GRAPH, "string")); - } - - private AtlasStructDef createSerDeDef() { - return AtlasTypeUtil.createStructTypeDef(SampleAppConstants.STRUCT_TYPE_SERDE, - AtlasTypeUtil.createRequiredAttrDef(SampleAppConstants.ATTR_NAME, "string"), - AtlasTypeUtil.createRequiredAttrDef(ATTR_SERDE, "string")); - } - - private AtlasEnumDef createTableTypeEnumDef() { - return new AtlasEnumDef(SampleAppConstants.ENUM_TABLE_TYPE, - SampleAppConstants.ATTR_DESCRIPTION, - Arrays.asList(new AtlasEnumDef.AtlasEnumElementDef("MANAGED", null, 1), - new AtlasEnumDef.AtlasEnumElementDef("EXTERNAL", null, 2))); - } - - private List createClassificationDefs() { - AtlasClassificationDef classification = createTraitTypeDef(SampleAppConstants.CLASSIFIED_TAG, Collections.emptySet(), AtlasTypeUtil.createRequiredAttrDef("tag", "string")); - AtlasClassificationDef pii = createTraitTypeDef(SampleAppConstants.PII_TAG, Collections.emptySet()); - AtlasClassificationDef finance = createTraitTypeDef(SampleAppConstants.FINANCE_TAG, Collections.emptySet()); - AtlasClassificationDef metric = createTraitTypeDef(SampleAppConstants.METRIC_TAG, Collections.emptySet()); - - return Arrays.asList(classification, pii, finance, metric); - } - - private List createBusinessMetadataDefs() { - String description = "description"; - - Map options = new HashMap<>(); - - options.put("maxStrLength", "20"); - options.put("applicableEntityTypes", "[\"" + SampleAppConstants.DATABASE_TYPE + "\",\"" + SampleAppConstants.TABLE_TYPE + "\"]"); - - AtlasBusinessMetadataDef bmWithAllTypes = createBusinessMetadataDef(SampleAppConstants.BUSINESS_METADATA_TYPE, - description, - "1.0", - createOptionalAttrDef(ATTR_ATTR1, ATLAS_TYPE_BOOLEAN, options, description), - createOptionalAttrDef(ATTR_ATTR2, ATLAS_TYPE_BYTE, options, description), - createOptionalAttrDef(ATTR_ATTR8, ATLAS_TYPE_STRING, options, description)); - - AtlasBusinessMetadataDef bmWithAllTypesMV = createBusinessMetadataDef(SampleAppConstants.BUSINESS_METADATA_TYPE_MV, - description, - "1.0", - createOptionalAttrDef(ATTR_ATTR11, "array", options, description), - createOptionalAttrDef(ATTR_ATTR18, "array", options, description)); - - return Arrays.asList(bmWithAllTypes, bmWithAllTypesMV); - } - - private List createAtlasRelationshipDef() { - AtlasRelationshipDef dbTablesDef = createRelationshipTypeDef(SampleAppConstants.TABLE_DATABASE_TYPE, SampleAppConstants.TABLE_DATABASE_TYPE, - "1.0", AGGREGATION, AtlasRelationshipDef.PropagateTags.NONE, - createRelationshipEndDef(SampleAppConstants.TABLE_TYPE, "db", SINGLE, false), - createRelationshipEndDef(SampleAppConstants.DATABASE_TYPE, "tables", SET, true)); - - AtlasRelationshipDef tableColumnsDef = createRelationshipTypeDef(SampleAppConstants.TABLE_COLUMNS_TYPE, SampleAppConstants.TABLE_COLUMNS_TYPE, - "1.0", COMPOSITION, AtlasRelationshipDef.PropagateTags.NONE, - createRelationshipEndDef(SampleAppConstants.TABLE_TYPE, "columns", SET, true), - createRelationshipEndDef(SampleAppConstants.COLUMN_TYPE, "table", SINGLE, false)); - - return Arrays.asList(dbTablesDef, tableColumnsDef); - } - - private AtlasTypesDef batchCreateTypes(AtlasTypesDef typesDef) throws AtlasServiceException { - AtlasTypesDef typesToCreate = new AtlasTypesDef(); - - for (AtlasEnumDef enumDef : typesDef.getEnumDefs()) { - if (client.typeWithNameExists(enumDef.getName())) { - SampleApp.log(enumDef.getName() + ": type already exists. Skipping"); - } else { - typesToCreate.getEnumDefs().add(enumDef); - } - } - - for (AtlasStructDef structDef : typesDef.getStructDefs()) { - if (client.typeWithNameExists(structDef.getName())) { - SampleApp.log(structDef.getName() + ": type already exists. Skipping"); - } else { - typesToCreate.getStructDefs().add(structDef); - } - } - - for (AtlasEntityDef entityDef : typesDef.getEntityDefs()) { - if (client.typeWithNameExists(entityDef.getName())) { - SampleApp.log(entityDef.getName() + ": type already exists. Skipping"); - } else { - typesToCreate.getEntityDefs().add(entityDef); - } - } - - for (AtlasClassificationDef classificationDef : typesDef.getClassificationDefs()) { - if (client.typeWithNameExists(classificationDef.getName())) { - SampleApp.log(classificationDef.getName() + ": type already exists. Skipping"); - } else { - typesToCreate.getClassificationDefs().add(classificationDef); - } - } - - for (AtlasRelationshipDef relationshipDef : typesDef.getRelationshipDefs()) { - if (client.typeWithNameExists(relationshipDef.getName())) { - SampleApp.log(relationshipDef.getName() + ": type already exists. Skipping"); - } else { - typesToCreate.getRelationshipDefs().add(relationshipDef); - } - } - - for (AtlasBusinessMetadataDef businessMetadataDef : typesDef.getBusinessMetadataDefs()) { - if (client.typeWithNameExists(businessMetadataDef.getName())) { - SampleApp.log(businessMetadataDef.getName() + ": type already exists. Skipping"); - } else { - typesToCreate.getBusinessMetadataDefs().add(businessMetadataDef); - } - } - - return client.createAtlasTypeDefs(typesToCreate); - } -} \ No newline at end of file diff --git a/atlas-examples/sample-app/src/main/python/README.md b/atlas-examples/sample-app/src/main/python/README.md deleted file mode 100644 index b199ecd6eb2..00000000000 --- a/atlas-examples/sample-app/src/main/python/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Python Sample App - -This is a Python sample app to showcase basic functionality of Atlas. We are using Python client -to call Atlas APIs. Make sure to install Atlas Python client first before trying to run this project. Currently, compatible with Python 3.5+ - -## Installation - -1. Using `setup.py` - -```bash -cd /atlas-examples/sample-app/src/main/python - -# To check if apache-atlas client is installed try the following command -python3 ->>> import apache_atlas ->>> - -# If there is no error, then client is installed otherwise follow client Readme file to install it first. -``` - - -To Run this project - -```bash -python sample_client.py -``` -This will prompt for url of the Atlas server, username and password. diff --git a/atlas-examples/sample-app/src/main/python/discovery_example.py b/atlas-examples/sample-app/src/main/python/discovery_example.py deleted file mode 100644 index 78f5337390e..00000000000 --- a/atlas-examples/sample-app/src/main/python/discovery_example.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env/python - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -import logging - -from utils import TABLE_TYPE - -LOG = logging.getLogger('discovery-example') - - -class DiscoveryExample: - DSL_QUERIES = {"from DataSet", "from Process"} - - def __init__(self, client): - self.typesDef = None - self.client = client - - def dsl_search(self): - for dsl_query in DiscoveryExample.DSL_QUERIES: - try: - result = self.client.discovery.dsl_search_with_params(dsl_query, 10, 0) - - if result: - entities_result = result.entities - - if entities_result: - LOG.info("query: '%s' retrieved: %s rows", dsl_query, len(entities_result)) - - except Exception as e: - LOG.exception("query: %s failed in dsl search", dsl_query) - - def quick_search(self, search_string): - try: - result = self.client.discovery.quick_search(search_string, TABLE_TYPE, False, 2, 0) - - if result: - LOG.info("Quick-search result: %s", result.searchResults) - - except Exception as e: - LOG.exception("query: '%s' failed in quick search", search_string) - - def basic_search(self, type_name, classification, query): - try: - result = self.client.discovery.basic_search(type_name, classification, query, False, None, 'ASCENDING', 2, 0) - - if result: - LOG.info("Basic-search result: %s", result) - - except Exception as e: - LOG.exception("query: '%s' failed in basic search", query) diff --git a/atlas-examples/sample-app/src/main/python/entity_example.py b/atlas-examples/sample-app/src/main/python/entity_example.py deleted file mode 100644 index cb2d98d4d91..00000000000 --- a/atlas-examples/sample-app/src/main/python/entity_example.py +++ /dev/null @@ -1,189 +0,0 @@ -#!/usr/bin/env/python - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -import json -import logging - -from apache_atlas.model.enums import EntityOperation -from apache_atlas.model.instance import AtlasEntityWithExtInfo, AtlasRelatedObjectId -from apache_atlas.utils import type_coerce - - -LOG = logging.getLogger('entity-example') - - -class EntityExample: - DATABASE_NAME = "employee_db_entity" - TABLE_NAME = "employee_table_entity" - PROCESS_NAME = "employee_process_entity" - METADATA_NAMESPACE_SUFFIX = "@cl1" - MANAGED_TABLE = "Managed" - ATTR_NAME = "name" - ATTR_DESCRIPTION = "description" - ATTR_QUALIFIED_NAME = "qualifiedName" - REFERENCEABLE_ATTRIBUTE_NAME = ATTR_QUALIFIED_NAME - ATTR_TIME_ID_COLUMN = "time_id" - ATTR_CUSTOMER_ID_COLUMN = "customer_id" - ATTR_COMPANY_ID_COLUMN = "company_id" - - def __init__(self, client): - self.client = client - self.entity_db = None - self.entity_table_us = None - self.entity_table_canada = None - self.entity_process = None - - def create_entities(self): - self.__create_db() - self.__create_us_table() - self.__create_canada_table() - self.__create_process() - - def get_table_entity(self): - if self.entity_table_us: - return self.entity_table_us - - return None - - def get_entity_by_guid(self, guid): - entity = self.client.entity.get_entity_by_guid(guid) - - LOG.info("Entity(guid=%s): typeName=%s, attr.name=%s", guid, entity.entity.typeName, entity.entity.attributes['name']) - - def remove_entities(self): - entity_list = [ self.entity_process.guid, self.entity_table_us.guid, self.entity_table_canada.guid, self.entity_db.guid ] - - self.client.entity.delete_entities_by_guids(entity_list) - - response = self.client.entity.purge_entities_by_guids(entity_list) - - if response is not None: - LOG.info("Purged entities") - else: - LOG.info("Purge failed!") - - def __create_db(self): - if not self.entity_db: - with open('request_json/entity_create_db.json') as f: - entity = type_coerce(json.load(f), AtlasEntityWithExtInfo) - - self.entity_db = self.__create_db_helper(entity) - - if self.entity_db: - LOG.info("Created database entity: guid=%s, attr.name=%s", self.entity_db.guid, self.entity_db.attributes['name']) - else: - LOG.info("Failed to create database entity") - - def __create_us_table(self): - if not self.entity_table_us: - with open('request_json/entity_create_table_us.json') as f: - entity = type_coerce(json.load(f), AtlasEntityWithExtInfo) - - self.entity_table_us = self.__create_table_helper(entity) - - if self.entity_table_us: - LOG.info("Created US table entity: guid=%s, attr.name=%s", self.entity_table_us.guid, self.entity_table_us.attributes['name']) - else: - LOG.info("Failed to create US table entity") - - def __create_canada_table(self): - if not self.entity_table_canada: - with open('request_json/entity_create_table_canada.json') as f: - entity = type_coerce(json.load(f), AtlasEntityWithExtInfo) - - self.entity_table_canada = self.__create_table_helper(entity) - - if self.entity_table_canada: - LOG.info("Created Canada table entity: guid=%s, attr.name=%s", self.entity_table_canada.guid, self.entity_table_canada.attributes['name']) - else: - LOG.info("Failed to create Canada table entity") - - def __create_process(self): - if not self.entity_process: - with open('request_json/entity_create_process.json') as f: - entity = type_coerce(json.load(f), AtlasEntityWithExtInfo) - - self.entity_process = self.__create_process_helper(entity) - - if self.entity_process: - LOG.info("Created process entity: guid=%s, attr.name=%s", self.entity_process.guid, self.entity_process.attributes['name']) - else: - LOG.info("Failed to createa process entity") - - def __create_db_helper(self, entity): - self.__create_entity(entity) - - return entity.entity - - def __create_table_helper(self, entity): - table = entity.entity - - if self.entity_db: - dbId = AtlasRelatedObjectId({ 'guid': self.entity_db.guid }) - - LOG.info("setting: table(%s).db=%s", table.guid, dbId) - - table.relationshipAttributes['db'] = dbId - - self.__create_entity(entity) - - return table - - def __create_process_helper(self, entity): - process = entity.entity - - process.relationshipAttributes = {} - - if self.entity_table_us: - process.relationshipAttributes['inputs'] = [ AtlasRelatedObjectId({ 'guid': self.entity_table_us.guid }) ] - - if self.entity_table_canada: - process.relationshipAttributes['outputs'] = [ AtlasRelatedObjectId({'guid': self.entity_table_canada.guid }) ] - - return self.__create_entity(entity) - - def __create_entity(self, entity): - try: - response = self.client.entity.create_entity(entity) - - guid = None - - if response and response.mutatedEntities: - if EntityOperation.CREATE.name in response.mutatedEntities: - header_list = response.mutatedEntities[EntityOperation.CREATE.name] - elif EntityOperation.UPDATE.name in response.mutatedEntities: - header_list = response.mutatedEntities[EntityOperation.UPDATE.name] - - if header_list and len(header_list) > 0: - guid = header_list[0].guid - elif response and response.guidAssignments: - if entity.entity is not None and entity.entity.guid is not None: - in_guid = entity.entity.guid - else: - in_guid = None - - if in_guid and response.guidAssignments[in_guid]: - guid = response.guidAssignments[in_guid] - - if guid: - entity.entity.guid = guid - except Exception as e: - LOG.exception("failed to create entity %s. error=%s", entity, e) - - return entity.entity if entity and entity.entity else None diff --git a/atlas-examples/sample-app/src/main/python/glossary_example.py b/atlas-examples/sample-app/src/main/python/glossary_example.py deleted file mode 100644 index 449c2bce779..00000000000 --- a/atlas-examples/sample-app/src/main/python/glossary_example.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env/python - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -import logging - -from apache_atlas.model.glossary import AtlasGlossary, AtlasGlossaryCategory, AtlasGlossaryTerm, AtlasGlossaryHeader - -LOG = logging.getLogger('glossary-example') - - -class GlossaryExample: - glossaryName = "EmployeeCountry" - - def __init__(self, client): - self.client = client - self.emp_glossary = None - self.emp_salary_term = None - self.emp_company_category = None - - def create_glossary(self): - glossary = AtlasGlossary({ 'name': GlossaryExample.glossaryName, 'shortDescription': 'This is a test Glossary' }) - self.emp_glossary = self.client.glossary.create_glossary(glossary) - - LOG.info("Created glossary with name: %s and guid: %s", self.emp_glossary.name, self.emp_glossary.guid) - - return self.emp_glossary - - def get_glossary_detail(self): - ext_info = self.client.glossary.get_glossary_ext_info(self.emp_glossary.guid) - - if ext_info: - LOG.info("Glossary extended info: %s; name: %s; language: %s", ext_info.guid, ext_info.name, ext_info.language) - - def create_glossary_term(self): - header = AtlasGlossaryHeader({ 'glossaryGuid': self.emp_glossary.guid, 'displayText': self.emp_glossary.name }) - term = AtlasGlossaryTerm({ 'name': 'EmpSalaryTerm', 'anchor': header }) - - self.emp_salary_term = self.client.glossary.create_glossary_term(term) - - if self.emp_salary_term: - LOG.info("Created Term for Employee Salary: %s with guid: %s", self.emp_salary_term.name, self.emp_salary_term.guid) - - def create_glossary_category(self): - header = AtlasGlossaryHeader({ 'glossaryGuid': self.emp_glossary.guid, 'displayText': self.emp_glossary.name }) - category = AtlasGlossaryCategory({ 'name': 'EmpSalaryCategory', 'anchor': header }) - - self.emp_company_category = self.client.glossary.create_glossary_category(category) - - if self.emp_company_category: - LOG.info("Created Category for Employee Category: %s with guid: %s", self.emp_company_category.name, self.emp_company_category.guid) - - def delete_glossary(self): - if not self.emp_glossary: - LOG.info("empGlossary is not present. Skipping the delete operation.") - - self.client.glossary.delete_glossary_by_guid(self.emp_glossary.guid) - - LOG.info("Delete is complete for Glossary!") \ No newline at end of file diff --git a/atlas-examples/sample-app/src/main/python/lineage_example.py b/atlas-examples/sample-app/src/main/python/lineage_example.py deleted file mode 100644 index 5341edaf049..00000000000 --- a/atlas-examples/sample-app/src/main/python/lineage_example.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env/python - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -import logging - -from apache_atlas.model.enums import LineageDirection - -LOG = logging.getLogger('lineage-example') - - -class LineageExample: - def __init__(self, client): - self.client = client - - def lineage(self, guid): - direction = LineageDirection.BOTH.name - lineage_info = self.client.lineage.get_lineage_info(guid, direction, 0) - - if not lineage_info: - LOG.info("Not able to find lineage info") - return - - relations = lineage_info.relations - guid_entity_map = lineage_info.guidEntityMap - - for relation in relations: - from_entity = guid_entity_map[relation.fromEntityId] - to_entity = guid_entity_map[relation.toEntityId] - - LOG.info("%s (%s) -> %s (%s)", from_entity.displayText, from_entity.typeName, to_entity.displayText, to_entity.typeName) \ No newline at end of file diff --git a/atlas-examples/sample-app/src/main/python/request_json/entity_create_db.json b/atlas-examples/sample-app/src/main/python/request_json/entity_create_db.json deleted file mode 100644 index f7dc5258d67..00000000000 --- a/atlas-examples/sample-app/src/main/python/request_json/entity_create_db.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "entity": { - "guid": "-1", - "typeName": "sample_db", - "attributes": { - "name": "employee_db", - "qualifiedName": "employee_db@cl1", - "description": "employee database", - "owner": "user", - "clusterName": "cl1", - "locationUri": "/hive/database/employee_db", - "createTime": 1607476058882 - } - } -} diff --git a/atlas-examples/sample-app/src/main/python/request_json/entity_create_process.json b/atlas-examples/sample-app/src/main/python/request_json/entity_create_process.json deleted file mode 100644 index 26addbbdcad..00000000000 --- a/atlas-examples/sample-app/src/main/python/request_json/entity_create_process.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "entity": { - "typeName": "sample_process", - "attributes": { - "name": "employee_process", - "description": "hive query for monthly avg salary", - "qualifiedName": "employee_process@cl1", - "userName": "user ETL", - "startTime": 1607476549507, - "endTime": 1607476552529, - "queryText": "create table as select ", - "queryId": "" - }, - "relationshipAttributes": { - "inputs": [ { "typeName": "sample_table", "uniqueAttributes": { "qualifiedName": "employee_db.employees_us@cl1" } } ], - "outputs": [ { "typeName": "sample_table", "uniqueAttributes": { "qualifiedName": "employee_db.employees_canada@cl1" } } ] - } - } -} diff --git a/atlas-examples/sample-app/src/main/python/request_json/entity_create_table_canada.json b/atlas-examples/sample-app/src/main/python/request_json/entity_create_table_canada.json deleted file mode 100644 index 25a114dc311..00000000000 --- a/atlas-examples/sample-app/src/main/python/request_json/entity_create_table_canada.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "entity": { - "guid": "-1", - "typeName": "sample_table", - "attributes": { - "name": "employees_canada", - "description": "Canada employees", - "qualifiedName": "employee_db.employees_canada@cl1", - "tableType": "Managed", - "serde1": { "typeName": "sample_serdeType", "attributes": { "name": "serde1", "serde": "serde1" } }, - "serde2": { "typeName": "sample_serdeType", "attributes": { "name": "serde2", "serde": "serde2" } } - }, - - "relationshipAttributes": { - "db": { "typeName": "sample_db", "uniqueAttributes": { "qualifiedName": "employee_db@cl1" } }, - "columns": [ - { "guid": "-2" }, - { "guid": "-3" }, - { "guid": "-4" } - ] - } - }, - - "referredEntities": { - "-2": { - "guid": "-2", - "typeName": "sample_column", - "attributes": { - "table": { "guid": "-1" }, - "name": "time_id", - "dataType": "int", - "comment": "time id", - "qualifiedName": "employee_db.employees_canada.time_id@cl1" - } - }, - "-3": { - "guid": "-3", - "typeName": "sample_column", - "attributes": { - "table": { "guid": "-1" }, - "name": "customer_id", - "dataType": "int", - "comment": "customer id", - "qualifiedName": "employee_db.employees_canada.customer_id@cl1" - } - }, - "-4": { - "guid": "-4", - "typeName": "sample_column", - "attributes": { - "table": { "guid": "-1" }, - "name": "company_id", - "dataType": "double", - "comment": "company id", - "qualifiedName": "employee_db.employees_canada.company_id@cl1" - } - } - } -} diff --git a/atlas-examples/sample-app/src/main/python/request_json/entity_create_table_us.json b/atlas-examples/sample-app/src/main/python/request_json/entity_create_table_us.json deleted file mode 100644 index 56ca736fecd..00000000000 --- a/atlas-examples/sample-app/src/main/python/request_json/entity_create_table_us.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "entity": { - "guid": "-1", - "typeName": "sample_table", - "attributes": { - "name": "employees_us", - "description": "US employees", - "qualifiedName": "employee_db.employees_us@cl1", - "tableType": "Managed", - "serde1": { "typeName": "sample_serdeType", "attributes": { "name": "serde1", "serde": "serde1" } }, - "serde2": { "typeName": "sample_serdeType", "attributes": { "name": "serde2", "serde": "serde2" } } - }, - - "relationshipAttributes": { - "db": { "typeName": "sample_db", "uniqueAttributes": { "qualifiedName": "employee_db@cl1" } }, - "columns": [ - { "guid": "-2" }, - { "guid": "-3" }, - { "guid": "-4" } - ] - } - }, - - "referredEntities": { - "-2": { - "guid": "-2", - "typeName": "sample_column", - "attributes": { - "name": "time_id", - "dataType": "int", - "comment": "time id", - "qualifiedName": "employee_db.employees_us.time_id@cl1", - "table": { "guid": "-1" } - } - }, - "-3": { - "guid": "-3", - "typeName": "sample_column", - "attributes": { - "name": "customer_id", - "dataType": "int", - "comment": "customer id", - "qualifiedName": "employee_db.employees_us.customer_id@cl1", - "table": { "guid": "-1" } - } - }, - "-4": { - "guid": "-4", - "typeName": "sample_column", - "attributes": { - "name": "company_id", - "dataType": "double", - "comment": "company id", - "qualifiedName": "employee_db.employees_us.company_id@cl1", - "table": { "guid": "-1" } - } - } - } -} diff --git a/atlas-examples/sample-app/src/main/python/request_json/typedef_create.json b/atlas-examples/sample-app/src/main/python/request_json/typedef_create.json deleted file mode 100644 index 70018adc853..00000000000 --- a/atlas-examples/sample-app/src/main/python/request_json/typedef_create.json +++ /dev/null @@ -1,190 +0,0 @@ -{ - "enumDefs": [ - { - "name": "sample_tableType", - "description": "sample_tableType", - "category": "ENUM", - "typeVersion": "1.0", - "elementDefs": [ - { "value": "MANAGED", "ordinal": 1 }, - { "value": "EXTERNAL", "ordinal": 2 } - ] - } - ], - "structDefs": [ - { - "name": "sample_serdeType", - "category": "STRUCT", - "typeVersion": "1.0", - "attributeDefs": [ - { "name": "name", "typeName": "string", "cardinality": "SINGLE", "isOptional": false, "isUnique": false, "isIndexable": true }, - { "name": "serde", "typeName": "string", "cardinality": "SINGLE", "isOptional": false, "isUnique": false, "isIndexable": true } - ] - } - ], - "classificationDefs": [ - { - "name": "sample_pii", - "category": "CLASSIFICATION", - "typeVersion": "1.0" - }, - { - "name": "sample_finance", - "category": "CLASSIFICATION", - "typeVersion": "1.0" - }, - { - "name": "sample_metric", - "category": "CLASSIFICATION", - "typeVersion": "1.0" - } - ], - "entityDefs": [ - { - "name": "sample_db", - "superTypes": [ "DataSet" ], - "category": "ENTITY", - "typeVersion": "1.0", - "attributeDefs": [ - { "name": "locationUri", "typeName": "string", "cardinality": "SINGLE", "isOptional": false, "isUnique": false, "isIndexable": true }, - { "name": "createTime", "typeName": "date", "cardinality": "SINGLE", "isOptional": false, "isUnique": false, "isIndexable": true } - ] - }, - { - "name": "sample_table", - "superTypes": [ "DataSet" ], - "category": "ENTITY", - "typeVersion": "1.0", - "attributeDefs": [ - { "name": "createTime", "typeName": "date", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": true }, - { "name": "tableType", "typeName": "sample_tableType", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": true }, - { "name": "temporary", "typeName": "boolean", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": false }, - { "name": "serde1", "typeName": "sample_serdeType", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": false }, - { "name": "serde2", "typeName": "sample_serdeType", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": false } - ] - }, - { - "name": "sample_column", - "superTypes": [ "DataSet" ], - "category": "ENTITY", - "typeVersion": "1.0", - "attributeDefs": [ - { "name": "dataType", "typeName": "string", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": true }, - { "name": "comment", "typeName": "string", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": true } - ] - }, - { - "name": "sample_process", - "superTypes": [ "Process" ], - "category": "ENTITY", - "typeVersion": "1.0", - "attributeDefs": [ - { "name": "userName", "typeName": "string", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": true }, - { "name": "startTime", "typeName": "long", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": true }, - { "name": "endTime", "typeName": "long", "cardinality": "SINGLE", "isOptional": true, "isUnique": false, "isIndexable": true }, - { "name": "queryText", "typeName": "string", "cardinality": "SINGLE", "isOptional": false, "isUnique": false, "isIndexable": true }, - { "name": "queryId", "typeName": "string", "cardinality": "SINGLE", "isOptional": false, "isUnique": false, "isIndexable": true } - ] - } - ], - "relationshipDefs": [ - { - "name": "sample_db_tables", - "description": "Tables of a db", - "category": "RELATIONSHIP", - "typeVersion": "1.0", - "relationshipCategory": "AGGREGATION", - "propagateTags": "NONE", - "endDef1": { "name": "db", "type": "sample_table", "cardinality": "SINGLE", "isContainer": false, "isLegacyAttribute": false }, - "endDef2": { "name": "tables", "type": "sample_db", "cardinality": "SET", "isContainer": true, "isLegacyAttribute": false } - }, - { - "name": "sample_table_columns", - "description": "Columns of a table", - "category": "RELATIONSHIP", - "typeVersion": "1.0", - "relationshipCategory": "COMPOSITION", - "propagateTags": "NONE", - "endDef1": { "name": "table", "type": "sample_column", "cardinality": "SINGLE", "isContainer": false, "isLegacyAttribute": false }, - "endDef2": { "name": "columns", "type": "sample_table", "cardinality": "SET", "isContainer": true, "isLegacyAttribute": false } - } - ], - "businessMetadataDefs": [ - { - "name": "sample_bm", - "description": "Sample business metadata", - "category": "BUSINESS_METADATA", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "attr1", - "typeName": "boolean", - "description": "Boolean attribute", - "cardinality": "SINGLE", - "isOptional": true, - "options": { - "applicableEntityTypes": "[ \"sample_db\", \"sample_table\" ]", - "maxStrLength": 50 - } - }, - { - "name": "attr2", - "typeName": "byte", - "description": "Byte attribute", - "cardinality": "SINGLE", - "isOptional": true, - "isUnique": false, - "isIndexable": true, - "options": { - "applicableEntityTypes": "[ \"sample_db\", \"sample_table\" ]", - "maxStrLength": 50 - } - }, - { - "name": "attr3", - "typeName": "string", - "description": "String attribute", - "cardinality": "SINGLE", - "isOptional": true, - "isUnique": false, - "isIndexable": true, - "searchWeight": 0, - "options": { - "applicableEntityTypes": "[ \"sample_db\", \"sample_table\" ]", - "maxStrLength": 50 - } - } - ] - }, - { - "name": "sample_bm_mv", - "description": "Sample business metadata with multi-value attributes", - "category": "BUSINESS_METADATA", - "typeVersion": "1.0", - "attributeDefs": [ - { - "name": "mv_attr1", - "typeName": "array", - "description": "Array of booleans", - "cardinality": "SINGLE", - "isOptional": true, - "options": { - "applicableEntityTypes": "[\"sample_db\",\"sample_table\"]", - "maxStrLength": 50 - } - }, - { - "name": "mv_attr2", - "typeName": "array", - "description": "Array of strings", - "cardinality": "SINGLE", - "isOptional": true, - "options": { - "applicableEntityTypes": "[ \"sample_db\", \"sample_table\" ]", - "maxStrLength": 50 - } - } - ] - } - ] -} diff --git a/atlas-examples/sample-app/src/main/python/sample_client.py b/atlas-examples/sample-app/src/main/python/sample_client.py deleted file mode 100644 index 33c430f4363..00000000000 --- a/atlas-examples/sample-app/src/main/python/sample_client.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env/python - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -import logging -import getpass - -from apache_atlas.client.base_client import AtlasClient -from typedef_example import TypeDefExample -from entity_example import EntityExample -from lineage_example import LineageExample -from glossary_example import GlossaryExample -from discovery_example import DiscoveryExample -from utils import METRIC_CLASSIFICATION, NAME - - -LOG = logging.getLogger('sample-example') - - -class SampleApp: - def __init__(self): - self.created_entity = None - - def main(self): - # Python3 - global input - try: input = raw_input - except NameError: pass - - url = input('Enter Atlas URL: ') - username = input('Enter username: ') - password = getpass.getpass('Enter password: ') - - client = AtlasClient(url, (username, password)) - - self.__typedef_example(client) - - self.__entity_example(client) - - self.__lineage_example(client) - - self.__discovery_example(client) - - self.__glossary_example(client) - - self.__entity_cleanup() - - - def __typedef_example(self, client): - LOG.info("\n---------- Creating Sample Types -----------") - - typedefExample = TypeDefExample(client) - - typedefExample.create_type_def() - - def __entity_example(self, client): - LOG.info("\n---------- Creating Sample Entities -----------") - - self.entityExample = EntityExample(client) - - self.entityExample.create_entities() - - self.created_entity = self.entityExample.get_table_entity() - - if self.created_entity and self.created_entity.guid: - self.entityExample.get_entity_by_guid(self.created_entity.guid) - - def __lineage_example(self, client): - LOG.info("\n---------- Lineage example -----------") - - lineage = LineageExample(client) - - if self.created_entity: - lineage.lineage(self.created_entity.guid) - else: - LOG.info("Create entity first to get lineage info") - - def __discovery_example(self, client): - LOG.info("\n---------- Search example -----------") - - discovery = DiscoveryExample(client) - - discovery.dsl_search() - - if not self.created_entity: - LOG.info("Create entity first to get search info") - return - - discovery.quick_search(self.created_entity.typeName) - - discovery.basic_search(self.created_entity.typeName, METRIC_CLASSIFICATION, self.created_entity.attributes[NAME]) - - def __glossary_example(self, client): - LOG.info("\n---------- Glossary Example -----------") - - glossary = GlossaryExample(client) - glossary_obj = glossary.create_glossary() - - if not glossary_obj: - LOG.info("Create glossary first") - return - - glossary.create_glossary_term() - glossary.get_glossary_detail() - glossary.create_glossary_category() - glossary.delete_glossary() - - def __entity_cleanup(self): - LOG.info("\n---------- Deleting Entities -----------") - - self.entityExample.remove_entities() - - -if __name__ == "__main__": - SampleApp().main() diff --git a/atlas-examples/sample-app/src/main/python/typedef_example.py b/atlas-examples/sample-app/src/main/python/typedef_example.py deleted file mode 100644 index 1aab7f1797f..00000000000 --- a/atlas-examples/sample-app/src/main/python/typedef_example.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env/python - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -import json -import logging -import utils - -from apache_atlas.utils import type_coerce -from apache_atlas.model.misc import SearchFilter -from apache_atlas.model.typedef import AtlasTypesDef - - -LOG = logging.getLogger('sample-example') - - -class TypeDefExample: - SAMPLE_APP_TYPES = [ - utils.DATABASE_TYPE, - utils.TABLE_TYPE, - utils.COLUMN_TYPE, - utils.PROCESS_TYPE, - utils.PII_TAG, - utils.FINANCE_TAG, - utils.METRIC_CLASSIFICATION - ] - - def __init__(self, client): - self.typesDef = None - self.client = client - - def create_type_def(self): - try: - if not self.typesDef: - with open('request_json/typedef_create.json') as f: - typedef = type_coerce(json.load(f), AtlasTypesDef) - self.typesDef = self.__create(typedef) - except Exception as e: - LOG.exception("Error in creating typeDef", exc_info=e) - - def print_typedefs(self): - for type_name in TypeDefExample.SAMPLE_APP_TYPES: - filter_params = {"name": type_name} - search = SearchFilter(filter_params) - response = self.client.typedef.get_all_typedefs(search) - - if response: - LOG.info("Created type: [%s]", type_name) - - def remove_typedefs(self): - if not self.typesDef: - LOG.info("There is no typeDef to delete.") - else: - for type_name in TypeDefExample.SAMPLE_APP_TYPES: - self.client.typedef.delete_type_by_name(type_name) - - self.typesDef = None - - LOG.info("Deleted typeDef successfully!") - - def __create(self, type_def): - types_to_create = AtlasTypesDef() - - types_to_create.enumDefs = [] - types_to_create.structDefs = [] - types_to_create.classificationDefs = [] - types_to_create.entityDefs = [] - types_to_create.relationshipDefs = [] - types_to_create.businessMetadataDefs = [] - - for enum_def in type_def.enumDefs: - if self.client.typedef.type_with_name_exists(enum_def.name): - LOG.info("Type with name %s already exists. Skipping.", enum_def.name) - else: - types_to_create.enumDefs.append(enum_def) - - for struct_def in type_def.structDefs: - if self.client.typedef.type_with_name_exists(struct_def.name): - LOG.info("Type with name %s already exists. Skipping.", struct_def.name) - else: - types_to_create.structDefs.append(struct_def) - - for classification_def in type_def.classificationDefs: - if self.client.typedef.type_with_name_exists(classification_def.name): - LOG.info("Type with name %s already exists. Skipping.", classification_def.name) - else: - types_to_create.classificationDefs.append(classification_def) - - for entity_def in type_def.entityDefs: - if self.client.typedef.type_with_name_exists(entity_def.name): - LOG.info("Type with name %s already exists. Skipping.", entity_def.name) - else: - types_to_create.entityDefs.append(entity_def) - - for relationship_def in type_def.relationshipDefs: - if self.client.typedef.type_with_name_exists(relationship_def.name): - LOG.info("Type with name %s already exists. Skipping.", relationship_def.name) - else: - types_to_create.relationshipDefs.append(relationship_def) - - for business_metadata_def in type_def.businessMetadataDefs: - if self.client.typedef.type_with_name_exists(business_metadata_def.name): - LOG.info("Type with name %s already exists. Skipping.", business_metadata_def.name) - else: - types_to_create.businessMetadataDefs.append(business_metadata_def) - - return self.client.typedef.create_atlas_typedefs(types_to_create) diff --git a/atlas-examples/sample-app/src/main/python/utils.py b/atlas-examples/sample-app/src/main/python/utils.py deleted file mode 100644 index c83472d7892..00000000000 --- a/atlas-examples/sample-app/src/main/python/utils.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env/python - -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -NAME = "name" -DESCRIPTION = "description" - -PII_TAG = "sample_pii" -FINANCE_TAG = "sample_finance" -METRIC_CLASSIFICATION = "sample_metric" - -DATABASE_TYPE = "sample_db" -PROCESS_TYPE = "sample_process" -TABLE_TYPE = "sample_table" -COLUMN_TYPE = "sample_column" - -TABLE_DATABASE_TYPE = "sample_db_tables" -TABLE_COLUMNS_TYPE = "sample_table_columns" -ENUM_TABLE_TYPE = "sample_tableType" -BUSINESS_METADATA_TYPE = "sample_bm" -BUSINESS_METADATA_TYPE_MV = "sample_bm_mv" -STRUCT_TYPE_SERDE = "sample_serdeType" diff --git a/atlas-examples/sample-app/src/main/resources/atlas-application.properties b/atlas-examples/sample-app/src/main/resources/atlas-application.properties deleted file mode 100644 index d24c663fd36..00000000000 --- a/atlas-examples/sample-app/src/main/resources/atlas-application.properties +++ /dev/null @@ -1,25 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -# - -######### Security Properties ######### - -# SSL config -atlas.enableTLS=false - -######### Server Properties ######### -atlas.rest.address=http://localhost:31000 \ No newline at end of file diff --git a/atlas-hub/atlas_config.py.patch b/atlas-hub/atlas_config.py.patch new file mode 100644 index 00000000000..381e2f86886 --- /dev/null +++ b/atlas-hub/atlas_config.py.patch @@ -0,0 +1,79 @@ +--- atlas_config.py.orig 2019-05-03 08:22:00.000000000 +0300 ++++ atlas_config.py 2020-01-16 02:14:31.660601445 +0300 +@@ -500,15 +500,18 @@ + + def wait_for_startup(confdir, wait): + count = 0 ++ started = False + host = get_atlas_url_host(confdir) + port = get_atlas_url_port(confdir) +- while True: ++ pid_file = pidFile(atlasDir()) ++ ++ while not started: + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(1) + s.connect((host, int(port))) + s.close() +- break ++ started = True + except Exception as e: + # Wait for 1 sec before next ping + sys.stdout.write('.') +@@ -516,11 +519,20 @@ + sleep(1) + + if count > wait: +- s.close() +- break ++ s.close() ++ sys.stdout.write('\nAtlas Web-UI startup timed out! But, wait for it...') ++ sys.stdout.flush() ++ break ++ ++ if not os.path.exists(pid_file): ++ sys.stdout.write('\nApache Atlas startup failed!\nCheck logs: /opt/apache-atlas-2.0.0/logs/application.log') ++ sys.stdout.flush() ++ exit() ++ break + + count = count + 1 + ++ + sys.stdout.write('\n') + + def run_zookeeper(dir, action, logdir = None, wait=True): +@@ -555,14 +567,14 @@ + + if zk_url is None: + if port is None: +- cmd = [os.path.join(dir, solrScript), action] ++ cmd = [os.path.join(dir, solrScript), action, '-force'] + else: +- cmd = [os.path.join(dir, solrScript), action, '-p', str(port)] ++ cmd = [os.path.join(dir, solrScript), action, '-force', '-p', str(port)] + else: + if port is None: +- cmd = [os.path.join(dir, solrScript), action, '-z', zk_url] ++ cmd = [os.path.join(dir, solrScript), action, '-force', '-z', zk_url] + else: +- cmd = [os.path.join(dir, solrScript), action, '-z', zk_url, '-p', port] ++ cmd = [os.path.join(dir, solrScript), action, '-force', '-z', zk_url, '-p', port] + + return runProcess(cmd, logdir, False, wait) + +@@ -572,7 +584,7 @@ + if IS_WINDOWS: + solrScript = "solr.cmd" + +- cmd = [os.path.join(dir, solrScript), 'create', '-c', index, '-d', confdir, '-shards', solrShards(), '-replicationFactor', solrReplicationFactor()] ++ cmd = [os.path.join(dir, solrScript), 'create', '-c', index, '-d', confdir, '-shards', solrShards(), '-replicationFactor', solrReplicationFactor(), '-force'] + + return runProcess(cmd, logdir, False, wait) + +@@ -691,3 +703,4 @@ + windowsPath = subprocess.Popen(cygpathArgs, stdout=subprocess.PIPE).communicate()[0] + windowsPath = windowsPath.strip() + return windowsPath ++ diff --git a/atlas-hub/atlas_start.py.patch b/atlas-hub/atlas_start.py.patch new file mode 100644 index 00000000000..de4a646553f --- /dev/null +++ b/atlas-hub/atlas_start.py.patch @@ -0,0 +1,62 @@ +--- atlas_start.py.orig 2019-05-03 08:22:00.000000000 +0300 ++++ atlas_start.py 2020-01-16 01:37:16.147611498 +0300 +@@ -18,6 +18,9 @@ + import os + import sys + import traceback ++import os.path ++import time ++from time import sleep + + import atlas_config as mc + +@@ -114,6 +117,9 @@ + mc.configure_hbase(atlas_home) + mc.run_hbase_action(mc.hbaseBinDir(atlas_home), "start", hbase_conf_dir, logdir) + print "hbase started." ++ if is_setup: ++ print "Sleeping 60s due too setup (init run)..." ++ sleep(60) + + #solr setup + if mc.is_solr_local(confdir): +@@ -128,6 +134,9 @@ + + mc.run_solr(mc.solrBinDir(atlas_home), "start", mc.get_solr_zk_url(confdir), mc.solrPort(), logdir) + print "solr started." ++ if is_setup: ++ print "Sleeping 60s due too setup (init run)..." ++ sleep(60) + + print "setting up solr collections..." + mc.create_solr_collection(mc.solrBinDir(atlas_home), mc.solrConfDir(atlas_home), "vertex_index", logdir) +@@ -145,8 +154,27 @@ + web_app_path = mc.convertCygwinPath(web_app_path) + if not is_setup: + start_atlas_server(atlas_classpath, atlas_pid_file, jvm_logdir, jvm_opts_list, web_app_path) +- mc.wait_for_startup(confdir, 300) +- print "Apache Atlas Server started!!!\n" ++ mc.wait_for_startup(confdir, 600) ++ print "Apache Atlas Server process started!\n" ++ ++ atlas_pid_file = mc.pidFile(atlas_home) ++ try: ++ pf = file(atlas_pid_file, 'r') ++ pid = int(pf.read().strip()) ++ pf.close() ++ print("Running Apache Atlas with PID " + str(pid) + "...\n") ++ except: ++ pid = None ++ if not pid: ++ sys.stderr.write("No PID file found! Server is not running?\nCheck logs: /opt/apache-atlas-2.0.0/logs/application.log\n\n") ++ return ++ ++ ++ while os.path.exists(atlas_pid_file): ++ time.sleep(1) ++ ++ print "Apache Atlas stopped!\n" ++ + else: + process = mc.java("org.apache.atlas.web.setup.AtlasSetup", [], atlas_classpath, jvm_opts_list, jvm_logdir) + return process.wait() diff --git a/atlas-hub/pre-conf/atlas-application.properties b/atlas-hub/pre-conf/atlas-application.properties new file mode 100644 index 00000000000..f24db9c99cc --- /dev/null +++ b/atlas-hub/pre-conf/atlas-application.properties @@ -0,0 +1,288 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +######### Graph Database Configs ######### + +# Graph Database + +#Configures the graph database to use. Defaults to JanusGraph +#atlas.graphdb.backend=org.apache.atlas.repository.graphdb.janus.AtlasJanusGraphDatabase + +# Graph Storage +# Set atlas.graph.storage.backend to the correct value for your desired storage +# backend. Possible values: +# +# hbase +# cassandra +# embeddedcassandra - Should only be set by building Atlas with -Pdist,embedded-cassandra-solr +# berkeleyje +# +# See the configuration documentation for more information about configuring the various storage backends. +# +atlas.graph.storage.backend=hbase2 +atlas.graph.storage.hbase.table=apache_atlas_janus + +#Hbase +#For standalone mode , specify localhost +#for distributed mode, specify zookeeper quorum here +atlas.graph.storage.hostname=localhost +atlas.graph.storage.hbase.regions-per-server=1 +atlas.graph.storage.lock.wait-time=10000 + +# Gremlin Query Optimizer +# +# Enables rewriting gremlin queries to maximize performance. This flag is provided as +# a possible way to work around any defects that are found in the optimizer until they +# are resolved. +#atlas.query.gremlinOptimizerEnabled=true + +# Delete handler +# +# This allows the default behavior of doing "soft" deletes to be changed. +# +# Allowed Values: +# org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1 - all deletes are "soft" deletes +# org.apache.atlas.repository.store.graph.v1.HardDeleteHandlerV1 - all deletes are "hard" deletes +# +#atlas.DeleteHandlerV1.impl=org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1 + +# Entity audit repository +# +# This allows the default behavior of logging entity changes to hbase to be changed. +# +# Allowed Values: +# org.apache.atlas.repository.audit.HBaseBasedAuditRepository - log entity changes to hbase +# org.apache.atlas.repository.audit.CassandraBasedAuditRepository - log entity changes to cassandra +# org.apache.atlas.repository.audit.NoopEntityAuditRepository - disable the audit repository +# +atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.HBaseBasedAuditRepository + +# if Cassandra is used as a backend for audit from the above property, uncomment and set the following +# properties appropriately. If using the embedded cassandra profile, these properties can remain +# commented out. +# atlas.EntityAuditRepository.keyspace=atlas_audit +# atlas.EntityAuditRepository.replicationFactor=1 + + +# Graph Search Index +atlas.graph.index.search.backend=solr + +#Solr +#Solr cloud mode properties +atlas.graph.index.search.solr.mode=cloud +atlas.graph.index.search.solr.zookeeper-url=localhost:2181 +atlas.graph.index.search.solr.zookeeper-connect-timeout=60000 +atlas.graph.index.search.solr.zookeeper-session-timeout=60000 +atlas.graph.index.search.solr.wait-searcher=true + +#Solr http mode properties +#atlas.graph.index.search.solr.mode=http +#atlas.graph.index.search.solr.http-urls=http://localhost:8983/solr + +# Solr-specific configuration property +atlas.graph.index.search.max-result-set-size=150 + +######### Notification Configs ######### +atlas.notification.embedded=true +atlas.kafka.data=${sys:atlas.home}/data/kafka +atlas.kafka.zookeeper.connect=localhost:9026 +atlas.kafka.bootstrap.servers=localhost:9027 +atlas.kafka.zookeeper.session.timeout.ms=400 +atlas.kafka.zookeeper.connection.timeout.ms=200 +atlas.kafka.zookeeper.sync.time.ms=20 +atlas.kafka.auto.commit.interval.ms=1000 +atlas.kafka.hook.group.id=atlas + +atlas.kafka.enable.auto.commit=false +atlas.kafka.auto.offset.reset=earliest +atlas.kafka.session.timeout.ms=30000 +atlas.kafka.offsets.topic.replication.factor=1 +atlas.kafka.poll.timeout.ms=1000 + +atlas.notification.create.topics=true +atlas.notification.replicas=1 +atlas.notification.topics=ATLAS_HOOK,ATLAS_ENTITIES +atlas.notification.log.failed.messages=true +atlas.notification.consumer.retry.interval=500 +atlas.notification.hook.retry.interval=1000 +# Enable for Kerberized Kafka clusters +#atlas.notification.kafka.service.principal=kafka/_HOST@EXAMPLE.COM +#atlas.notification.kafka.keytab.location=/etc/security/keytabs/kafka.service.keytab + +## Server port configuration +#atlas.server.http.port=21000 +#atlas.server.https.port=21443 + +######### Security Properties ######### + +# SSL config +atlas.enableTLS=false + +#truststore.file=/path/to/truststore.jks +#cert.stores.credential.provider.path=jceks://file/path/to/credentialstore.jceks + +#following only required for 2-way SSL +#keystore.file=/path/to/keystore.jks + +# Authentication config + +atlas.authentication.method.kerberos=false +atlas.authentication.method.file=false + +atlas.authentication.method.keycloak=true +atlas.authentication.method.keycloak.file=${sys:atlas.home}/conf/keycloak.json + +#### ldap.type= LDAP or AD +atlas.authentication.method.ldap.type=none + +#### user credentials file +atlas.authentication.method.file.filename=${sys:atlas.home}/conf/users-credentials.properties + +### groups from UGI +#atlas.authentication.method.ldap.ugi-groups=true + +######## LDAP properties ######### +#atlas.authentication.method.ldap.url=ldap://:389 +#atlas.authentication.method.ldap.userDNpattern=uid={0},ou=People,dc=example,dc=com +#atlas.authentication.method.ldap.groupSearchBase=dc=example,dc=com +#atlas.authentication.method.ldap.groupSearchFilter=(member=uid={0},ou=Users,dc=example,dc=com) +#atlas.authentication.method.ldap.groupRoleAttribute=cn +#atlas.authentication.method.ldap.base.dn=dc=example,dc=com +#atlas.authentication.method.ldap.bind.dn=cn=Manager,dc=example,dc=com +#atlas.authentication.method.ldap.bind.password= +#atlas.authentication.method.ldap.referral=ignore +#atlas.authentication.method.ldap.user.searchfilter=(uid={0}) +#atlas.authentication.method.ldap.default.role= + + +######### Active directory properties ####### +#atlas.authentication.method.ldap.ad.domain=example.com +#atlas.authentication.method.ldap.ad.url=ldap://:389 +#atlas.authentication.method.ldap.ad.base.dn=(sAMAccountName={0}) +#atlas.authentication.method.ldap.ad.bind.dn=CN=team,CN=Users,DC=example,DC=com +#atlas.authentication.method.ldap.ad.bind.password= +#atlas.authentication.method.ldap.ad.referral=ignore +#atlas.authentication.method.ldap.ad.user.searchfilter=(sAMAccountName={0}) +#atlas.authentication.method.ldap.ad.default.role= + +######### JAAS Configuration ######## + +#atlas.jaas.KafkaClient.loginModuleName = com.sun.security.auth.module.Krb5LoginModule +#atlas.jaas.KafkaClient.loginModuleControlFlag = required +#atlas.jaas.KafkaClient.option.useKeyTab = true +#atlas.jaas.KafkaClient.option.storeKey = true +#atlas.jaas.KafkaClient.option.serviceName = kafka +#atlas.jaas.KafkaClient.option.keyTab = /etc/security/keytabs/atlas.service.keytab +#atlas.jaas.KafkaClient.option.principal = atlas/_HOST@EXAMPLE.COM + +######### Server Properties ######### +atlas.rest.address=http://localhost:21000 +# If enabled and set to true, this will run setup steps when the server starts +#atlas.server.run.setup.on.start=false + +######### Entity Audit Configs ######### +atlas.audit.hbase.tablename=apache_atlas_entity_audit +atlas.audit.zookeeper.session.timeout.ms=1000 +atlas.audit.hbase.zookeeper.quorum=localhost:2181 + +######### High Availability Configuration ######## +atlas.server.ha.enabled=false +#### Enabled the configs below as per need if HA is enabled ##### +#atlas.server.ids=id1 +#atlas.server.address.id1=localhost:21000 +#atlas.server.ha.zookeeper.connect=localhost:2181 +#atlas.server.ha.zookeeper.retry.sleeptime.ms=1000 +#atlas.server.ha.zookeeper.num.retries=3 +#atlas.server.ha.zookeeper.session.timeout.ms=20000 +## if ACLs need to be set on the created nodes, uncomment these lines and set the values ## +#atlas.server.ha.zookeeper.acl=: +#atlas.server.ha.zookeeper.auth=: + + + +######### Atlas Authorization ######### +atlas.authorizer.impl=ranger +atlas.authorizer.simple.authz.policy.file=atlas-simple-authz-policy.json + +######### Type Cache Implementation ######## +# A type cache class which implements +# org.apache.atlas.typesystem.types.cache.TypeCache. +# The default implementation is org.apache.atlas.typesystem.types.cache.DefaultTypeCache which is a local in-memory type cache. +#atlas.TypeCache.impl= + +######### Performance Configs ######### +#atlas.graph.storage.lock.retries=10 +#atlas.graph.storage.cache.db-cache-time=120000 + +######### CSRF Configs ######### +atlas.rest-csrf.enabled=true +atlas.rest-csrf.browser-useragents-regex=^Mozilla.*,^Opera.*,^Chrome.* +atlas.rest-csrf.methods-to-ignore=GET,OPTIONS,HEAD,TRACE +atlas.rest-csrf.custom-header=X-XSRF-HEADER + +############ KNOX Configs ################ +#atlas.sso.knox.browser.useragent=Mozilla,Chrome,Opera +#atlas.sso.knox.enabled=true +#atlas.sso.knox.providerurl=https://:8443/gateway/knoxsso/api/v1/websso +#atlas.sso.knox.publicKey= + +############ Atlas Metric/Stats configs ################ +# Format: atlas.metric.query.. +atlas.metric.query.cache.ttlInSecs=900 +#atlas.metric.query.general.typeCount= +#atlas.metric.query.general.typeUnusedCount= +#atlas.metric.query.general.entityCount= +#atlas.metric.query.general.tagCount= +#atlas.metric.query.general.entityDeleted= +# +#atlas.metric.query.entity.typeEntities= +#atlas.metric.query.entity.entityTagged= +# +#atlas.metric.query.tags.entityTags= + +######### Compiled Query Cache Configuration ######### + +# The size of the compiled query cache. Older queries will be evicted from the cache +# when we reach the capacity. + +#atlas.CompiledQueryCache.capacity=1000 + +# Allows notifications when items are evicted from the compiled query +# cache because it has become full. A warning will be issued when +# the specified number of evictions have occurred. If the eviction +# warning threshold <= 0, no eviction warnings will be issued. + +#atlas.CompiledQueryCache.evictionWarningThrottle=0 + + +######### Full Text Search Configuration ######### + +#Set to false to disable full text search. +#atlas.search.fulltext.enable=true + +######### Gremlin Search Configuration ######### + +#Set to false to disable gremlin search. +atlas.search.gremlin.enable=false + + +########## Add http headers ########### + +#atlas.headers.Access-Control-Allow-Origin=* +#atlas.headers.Access-Control-Allow-Methods=GET,OPTIONS,HEAD,PUT,POST +#atlas.headers.= diff --git a/atlas-hub/pre-conf/atlas-auth/atlas-atlas-audit.xml b/atlas-hub/pre-conf/atlas-auth/atlas-atlas-audit.xml new file mode 100755 index 00000000000..3ed501c3de5 --- /dev/null +++ b/atlas-hub/pre-conf/atlas-auth/atlas-atlas-audit.xml @@ -0,0 +1,139 @@ + + + + + + xasecure.audit.is.enabled + true + + + + + + xasecure.audit.destination.solr + false + + + + xasecure.audit.destination.solr.urls + NONE + + + + xasecure.audit.destination.solr.zookeepers + + + + + xasecure.audit.destination.solr.collection + NONE + + + + + + xasecure.audit.destination.hdfs + false + + + + xasecure.audit.destination.hdfs.dir + hdfs://__REPLACE__NAME_NODE_HOST:8020/ranger/audit + + + + xasecure.audit.destination.hdfs.subdir + %app-type%/%time:yyyyMMdd% + + + + xasecure.audit.destination.hdfs.filename.format + %app-type%_ranger_audit_%hostname%.log + + + + xasecure.audit.destination.hdfs.file.rollover.sec + 86400 + + + + + + + xasecure.audit.destination.log4j + true + + + + xasecure.audit.destination.log4j.logger + AUTH_AUDIT + + + + + xasecure.audit.destination.elasticsearch + false + + + xasecure.audit.elasticsearch.is.enabled + true/ + + + xasecure.audit.destination.elasticsearch.urls + atlas-elasticsearch-master.atlas.svc.cluster.local + + + xasecure.audit.destination.elasticsearch.index + ranger-audit + + diff --git a/atlas-hub/pre-conf/atlas-auth/atlas-atlas-security-changes.cfg b/atlas-hub/pre-conf/atlas-auth/atlas-atlas-security-changes.cfg new file mode 100755 index 00000000000..8fd6e092740 --- /dev/null +++ b/atlas-hub/pre-conf/atlas-auth/atlas-atlas-security-changes.cfg @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# +# Change the original policy parameter to work with policy manager based. +# +# +atlas.plugin.atlas.service.name %REPOSITORY_NAME% mod create-if-not-exists + diff --git a/atlas-hub/pre-conf/atlas-auth/atlas-atlas-security.xml b/atlas-hub/pre-conf/atlas-auth/atlas-atlas-security.xml new file mode 100755 index 00000000000..6b16b6ee1ee --- /dev/null +++ b/atlas-hub/pre-conf/atlas-auth/atlas-atlas-security.xml @@ -0,0 +1,88 @@ + + + + + + atlas.plugin.atlas.service.name + atlas + + Name of the Ranger service containing policies for this YARN instance + + + + + atlas.plugin.atlas.policy.source.impl + org.apache.atlas.authz.admin.client.AtlasAuthRESTClient + + Class to retrieve policies from the source + + + + + atlas.plugin.atlas.authz.rest.url + localhost:21000/api/atlas/v2/auth + + URL to Ranger Admin + + + + + atlas.plugin.atlas.policy.rest.ssl.config.file + /etc/atlas/conf/ranger-policymgr-ssl.xml + + Path to the file containing SSL details to contact Ranger Admin + + + + + atlas.plugin.atlas.policy.pollIntervalMs + 30000 + + How often to poll for changes in policies? + + + + + atlas.plugin.atlas.policy.cache.dir + /etc/atlas/atlasdev/policycache + + Directory where Ranger policies are cached after successful retrieval from the source + + + + + atlas.plugin.atlas.policy.rest.client.connection.timeoutMs + 120000 + + RangerRestClient Connection Timeout in Milli Seconds + + + + + atlas.plugin.atlas.policy.rest.client.read.timeoutMs + 120000 + + AtlasAuth read Timeout in Milli Seconds + + + + + atlas.plugin.atlas.policyengine.option.disable.tag.retriever + true + + diff --git a/atlas-hub/pre-conf/atlas-env.sh b/atlas-hub/pre-conf/atlas-env.sh new file mode 100644 index 00000000000..0986d18f9fd --- /dev/null +++ b/atlas-hub/pre-conf/atlas-env.sh @@ -0,0 +1,68 @@ +#!/usr/bin/env bash +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# +# The java implementation to use. If JAVA_HOME is not found we expect java and jar to be in path +export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 + +# any additional java opts you want to set. This will apply to both client and server operations +#export ATLAS_OPTS= + +# any additional java opts that you want to set for client only +#export ATLAS_CLIENT_OPTS= + +# java heap size we want to set for the client. Default is 1024MB +#export ATLAS_CLIENT_HEAP= + +# any additional opts you want to set for atlas service. +#export ATLAS_SERVER_OPTS= + +# indicative values for large number of metadata entities (equal or more than 10,000s) +#export ATLAS_SERVER_OPTS="-server -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+PrintTenuringDistribution -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=dumps/atlas_server.hprof -Xloggc:logs/gc-worker.log -verbose:gc -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=1m -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintGCTimeStamps" + +# java heap size we want to set for the atlas server. Default is 1024MB +#export ATLAS_SERVER_HEAP= + +# indicative values for large number of metadata entities (equal or more than 10,000s) for JDK 8 +#export ATLAS_SERVER_HEAP="-Xms15360m -Xmx15360m -XX:MaxNewSize=5120m -XX:MetaspaceSize=100M -XX:MaxMetaspaceSize=512m" + +# What is is considered as atlas home dir. Default is the base locaion of the installed software +#export ATLAS_HOME_DIR= + +# Where log files are stored. Defatult is logs directory under the base install location +#export ATLAS_LOG_DIR= + +# Where pid files are stored. Defatult is logs directory under the base install location +#export ATLAS_PID_DIR= + +# where the atlas titan db data is stored. Defatult is logs/data directory under the base install location +#export ATLAS_DATA_DIR= + +# Where do you want to expand the war file. By Default it is in /server/webapp dir under the base install dir. +#export ATLAS_EXPANDED_WEBAPP_DIR= + +# indicates whether or not a local instance of HBase should be started for Atlas +export MANAGE_LOCAL_HBASE=true + +# indicates whether or not a local instance of Solr should be started for Atlas +export MANAGE_LOCAL_SOLR=true + +# indicates whether or not cassandra is the embedded backend for Atlas +export MANAGE_EMBEDDED_CASSANDRA=false + +# indicates whether or not a local instance of Elasticsearch should be started for Atlas +export MANAGE_LOCAL_ELASTICSEARCH=false diff --git a/atlas-hub/pre-conf/atlas-logback.xml b/atlas-hub/pre-conf/atlas-logback.xml new file mode 100644 index 00000000000..3a7b709e285 --- /dev/null +++ b/atlas-hub/pre-conf/atlas-logback.xml @@ -0,0 +1,237 @@ + + + + + + + + + logback: %d %-5p - [%t:%X{context-key}] - traceId:[%X{trace_id}] ~ %m (%C{1}:%L)%n + + + + INFO + + + + + + true + * + true + true + + + + + + filter + atlas-audit + + + + logback: %d %-5p - [%t:%X{context-key}] - X-Atlan-Request-Id:[%X{X-Atlan-Request-Id}] - traceId:[%X{trace_id}] ~ %m (%C{1}:%L)%n + + + + INFO + + + + + + + filter + atlas-auth-audit + + + + logback: %d %-5p - [%t:%X{context-key}] - X-Atlan-Request-Id:[%X{X-Atlan-Request-Id}] - traceId:[%X{trace_id}] ~ %m (%C{1}:%L)%n + + + + INFO + + + + + + + filter + atlas-application + + + + logback: %d %-5p - [%t:%X{context-key}] - X-Atlan-Request-Id:[%X{X-Atlan-Request-Id}] - traceId:[%X{trace_id}] ~ %m (%C{1}:%L)%n + + + + INFO + + + + + + + filter + atlas-perf + + + + logback: %d %-5p - [%t:%X{context-key}] - X-Atlan-Request-Id:[%X{X-Atlan-Request-Id}] - traceId:[%X{trace_id}] ~ %m (%C{1}:%L)%n + + + + INFO + + + + + + + filter + atlas-ranger + + + + logback: %d %-5p - [%t:%X{context-key}] - X-Atlan-Request-Id:[%X{X-Atlan-Request-Id}] - traceId:[%X{trace_id}] ~ %m (%C{1}:%L)%n + + + + INFO + + + + + + + filter + atlas-metrics + + + + logback: %d %-5p - [%t:%X{context-key}] - X-Atlan-Request-Id:[%X{X-Atlan-Request-Id}] - traceId:[%X{trace_id}] ~ %m (%C{1}:%L)%n + + + + INFO + + + + + + + filter + atlas-tasks + + + + logback: %d %-5p - [%t:%X{context-key}] - X-Atlan-Request-Id:[%X{X-Atlan-Request-Id}] - traceId:[%X{trace_id}] ~ %m (%C{1}:%L)%n + + + + INFO + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/atlas-hub/pre-conf/atlas-script-application.properties b/atlas-hub/pre-conf/atlas-script-application.properties new file mode 100644 index 00000000000..342d56a7133 --- /dev/null +++ b/atlas-hub/pre-conf/atlas-script-application.properties @@ -0,0 +1,325 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +######### Graph Database Configs ######### + +# Graph Database + +#Configures the graph database to use. Defaults to JanusGraph +#atlas.graphdb.backend=org.apache.atlas.repository.graphdb.janus.AtlasJanusGraphDatabase + +# Graph Storage +# Set atlas.graph.storage.backend to the correct value for your desired storage +# backend. Possible values: +# +# hbase +# cassandra +# embeddedcassandra - Should only be set by building Atlas with -Pdist,embedded-cassandra-solr +# berkeleyje +# +# See the configuration documentation for more information about configuring the various storage backends. +# +# atlas.graph.storage.backend=hbase2 +# atlas.graph.storage.hbase.table=apache_atlas_janus + +#Hbase +#For standalone mode , specify localhost +#for distributed mode, specify zookeeper quorum here +# atlas.graph.storage.hostname= +# atlas.graph.storage.hbase.regions-per-server=1 +# atlas.graph.storage.lock.wait-time=10000 + +#In order to use Cassandra as a backend, comment out the hbase specific properties above, and uncomment the +#the following properties +#atlas.graph.storage.clustername= +#atlas.graph.storage.port= +atlas.graph.storage.backend=cql +atlas.graph.storage.hostname=atlas-cassandra.atlas.svc.cluster.local +atlas.graph.storage.cql.keyspace=atlas +atlas.graph.storage.cql.replication-factor=3 +atlas.graph.storage.clustername=cassandra +atlas.graph.storage.port=9042 +atlas.graph.query.fast-property=true +atlas.graph.query.batch=true +atlas.graph.storage.cql.remote-core-connections-per-host=5 +atlas.graph.storage.cql.remote-max-connections-per-host=5 +# Gremlin Query Optimizer +# +# Enables rewriting gremlin queries to maximize performance. This flag is provided as +# a possible way to work around any defects that are found in the optimizer until they +# are resolved. +#atlas.query.gremlinOptimizerEnabled=true + +# Delete handler +# +# This allows the default behavior of doing "soft" deletes to be changed. +# +# Allowed Values: +# org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1 - all deletes are "soft" deletes +# org.apache.atlas.repository.store.graph.v1.HardDeleteHandlerV1 - all deletes are "hard" deletes +# +atlas.DeleteHandlerV1.impl=org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1 + +# Entity audit repository +# +# This allows the default behavior of logging entity changes to hbase to be changed. +# +# Allowed Values: +# org.apache.atlas.repository.audit.HBaseBasedAuditRepository - log entity changes to hbase +# org.apache.atlas.repository.audit.CassandraBasedAuditRepository - log entity changes to cassandra +# org.apache.atlas.repository.audit.NoopEntityAuditRepository - disable the audit repository +# +atlas.EntityAuditRepository.impl=org.apache.atlas.repository.audit.CassandraBasedAuditRepository +atlas.EntityAuditRepository.keyspace=atlas_audit +atlas.EntityAuditRepository.replicationFactor=1 +# if Cassandra is used as a backend for audit from the above property, uncomment and set the following +# properties appropriately. If using the embedded cassandra profile, these properties can remain +# commented out. +# atlas.EntityAuditRepository.keyspace=atlas_audit +# atlas.EntityAuditRepository.replicationFactor=1 + + +# Graph Search Index +atlas.graph.index.search.backend=elasticsearch + +#Solr +#Solr cloud mode properties +# atlas.graph.index.search.solr.mode=cloud +# atlas.graph.index.search.solr.zookeeper-url= +# atlas.graph.index.search.solr.zookeeper-connect-timeout=60000 +# atlas.graph.index.search.solr.zookeeper-session-timeout=60000 +# atlas.graph.index.search.solr.wait-searcher=true +#Solr http mode properties +#atlas.graph.index.search.solr.mode=http +#atlas.graph.index.search.solr.http-urls=http://localhost:8983/solr + +# ElasticSearch support (Tech Preview) +# Comment out above solr configuration, and uncomment the following two lines. Additionally, make sure the +# hostname field is set to a comma delimited set of elasticsearch master nodes, or an ELB that fronts the masters. +# +# Elasticsearch does not provide authentication out of the box, but does provide an option with the X-Pack product +# https://www.elastic.co/products/x-pack/security +# +# Alternatively, the JanusGraph documentation provides some tips on how to secure Elasticsearch without additional +# plugins: http://docs.janusgraph.org/latest/elasticsearch.html + +atlas.graph.index.search.hostname=atlas-elasticsearch-master.atlas.svc.cluster.local:9200 +atlas.graph.index.search.elasticsearch.client-only=true +atlas.graph.index.search.elasticsearch.retry_on_conflict=5 + +# Solr-specific configuration property +# atlas.graph.index.search.max-result-set-size=150 + +######### Notification Configs ######### +atlas.notification.embedded=true +atlas.kafka.data=${sys:atlas.home}/data/kafka +atlas.kafka.zookeeper.connect=localhost:9026 +atlas.kafka.bootstrap.servers=localhost:9027 +atlas.kafka.zookeeper.session.timeout.ms=400 +atlas.kafka.zookeeper.connection.timeout.ms=200 +atlas.kafka.zookeeper.sync.time.ms=20 +atlas.kafka.auto.commit.interval.ms=1000 +atlas.kafka.hook.group.id=atlas + +atlas.kafka.enable.auto.commit=false +atlas.kafka.auto.offset.reset=earliest +atlas.kafka.session.timeout.ms=30000 +atlas.kafka.offsets.topic.replication.factor=1 +atlas.kafka.poll.timeout.ms=1000 + +atlas.notification.create.topics=true +atlas.notification.replicas=1 +atlas.notification.topics=ATLAS_HOOK,ATLAS_ENTITIES +atlas.notification.log.failed.messages=true +atlas.notification.consumer.retry.interval=500 +atlas.notification.hook.retry.interval=1000 +# Enable for Kerberized Kafka clusters +#atlas.notification.kafka.service.principal=kafka/_HOST@EXAMPLE.COM +#atlas.notification.kafka.keytab.location=/etc/security/keytabs/kafka.service.keytab + +## Server port configuration +#atlas.server.http.port=21000 +#atlas.server.https.port=21443 + +######### Security Properties ######### + +# SSL config +atlas.enableTLS=false + +#truststore.file=/path/to/truststore.jks +#cert.stores.credential.provider.path=jceks://file/path/to/credentialstore.jceks + +#following only required for 2-way SSL +#keystore.file=/path/to/keystore.jks + +# Authentication config + +atlas.authentication.method.kerberos=false +atlas.authentication.method.file=false + +atlas.authentication.method.keycloak=true +atlas.authentication.method.keycloak.file=${sys:atlas.home}/conf/keycloak.json +atlas.authentication.method.keycloak.ugi-groups=false +atlas.authentication.method.keycloak.groups_claim=groups + +#### ldap.type= LDAP or AD +atlas.authentication.method.ldap.type=none + +#### user credentials file +atlas.authentication.method.file.filename=${sys:atlas.home}/conf/users-credentials.properties + +### groups from UGI +#atlas.authentication.method.ldap.ugi-groups=true + +######## LDAP properties ######### +#atlas.authentication.method.ldap.url=ldap://:389 +#atlas.authentication.method.ldap.userDNpattern=uid={0},ou=People,dc=example,dc=com +#atlas.authentication.method.ldap.groupSearchBase=dc=example,dc=com +#atlas.authentication.method.ldap.groupSearchFilter=(member=uid={0},ou=Users,dc=example,dc=com) +#atlas.authentication.method.ldap.groupRoleAttribute=cn +#atlas.authentication.method.ldap.base.dn=dc=example,dc=com +#atlas.authentication.method.ldap.bind.dn=cn=Manager,dc=example,dc=com +#atlas.authentication.method.ldap.bind.password= +#atlas.authentication.method.ldap.referral=ignore +#atlas.authentication.method.ldap.user.searchfilter=(uid={0}) +#atlas.authentication.method.ldap.default.role= + + +######### Active directory properties ####### +#atlas.authentication.method.ldap.ad.domain=example.com +#atlas.authentication.method.ldap.ad.url=ldap://:389 +#atlas.authentication.method.ldap.ad.base.dn=(sAMAccountName={0}) +#atlas.authentication.method.ldap.ad.bind.dn=CN=team,CN=Users,DC=example,DC=com +#atlas.authentication.method.ldap.ad.bind.password= +#atlas.authentication.method.ldap.ad.referral=ignore +#atlas.authentication.method.ldap.ad.user.searchfilter=(sAMAccountName={0}) +#atlas.authentication.method.ldap.ad.default.role= + +######### JAAS Configuration ######## + +#atlas.jaas.KafkaClient.loginModuleName = com.sun.security.auth.module.Krb5LoginModule +#atlas.jaas.KafkaClient.loginModuleControlFlag = required +#atlas.jaas.KafkaClient.option.useKeyTab = true +#atlas.jaas.KafkaClient.option.storeKey = true +#atlas.jaas.KafkaClient.option.serviceName = kafka +#atlas.jaas.KafkaClient.option.keyTab = /etc/security/keytabs/atlas.service.keytab +#atlas.jaas.KafkaClient.option.principal = atlas/_HOST@EXAMPLE.COM + +######### Server Properties ######### +atlas.rest.address=http://localhost:21000 +# If enabled and set to true, this will run setup steps when the server starts +#atlas.server.run.setup.on.start=false + +######### Entity Audit Configs ######### +atlas.audit.hbase.tablename=apache_atlas_entity_audit +atlas.audigit.zookeeper.session.timeout.ms=1000 +atlas.audit.hbase.zookeeper.quorum=localhost:2181 + +######### High Availability Configuration ######## +atlas.server.ha.enabled=false +#### Enabled the configs below as per need if HA is enabled ##### +#atlas.server.ids=id1 +#atlas.server.address.id1=localhost:21000 +#atlas.server.ha.zookeeper.connect=localhost:2181 +#atlas.server.ha.zookeeper.retry.sleeptime.ms=1000 +#atlas.server.ha.zookeeper.num.retries=3 +#atlas.server.ha.zookeeper.session.timeout.ms=20000 +## if ACLs need to be set on the created nodes, uncomment these lines and set the values ## +#atlas.server.ha.zookeeper.acl=: +#atlas.server.ha.zookeeper.auth=: + +######### Atlas Authorization ######### +atlas.authorizer.impl=org.apache.ranger.authorization.atlas.authorizer.RangerAtlasAuthorizer +atlas.authorizer.simple.authz.policy.file=atlas-simple-authz-policy.json + +######### Type Cache Implementation ######## +# A type cache class which implements +# org.apache.atlas.typesystem.types.cache.TypeCache. +# The default implementation is org.apache.atlas.typesystem.types.cache.DefaultTypeCache which is a local in-memory type cache. +#atlas.TypeCache.impl= + +######### Performance Configs ######### +atlas.graph.storage.lock.retries=5 +atlas.graph.storage.cache.db-cache-time=120000 +atlas.graph.cache.db-cache-time=120000 +atlas.graph.cache.db-cache-size=0.7 +atlas.graph.cache.db-cache=true +atlas.webserver.minthreads=40 +# Maximum number of threads in the atlas web server +atlas.webserver.maxthreads=200 +# Keepalive time in secs for the thread pool of the atlas web server +atlas.webserver.keepalivetimesecs=60 +# Queue size for the requests(when max threads are busy) for the atlas web server +atlas.webserver.queuesize=100 +######### CSRF Configs ######### +atlas.rest-csrf.enabled=true +atlas.rest-csrf.browser-useragents-regex=^Mozilla.*,^Opera.*,^Chrome.* +atlas.rest-csrf.methods-to-ignore=GET,OPTIONS,HEAD,TRACE +atlas.rest-csrf.custom-header=X-XSRF-HEADER + +############ KNOX Configs ################ +#atlas.sso.knox.browser.useragent=Mozilla,Chrome,Opera +#atlas.sso.knox.enabled=true +#atlas.sso.knox.providerurl=https://:8443/gateway/knoxsso/api/v1/websso +#atlas.sso.knox.publicKey= + +############ Atlas Metric/Stats configs ################ +# Format: atlas.metric.query.. +atlas.metric.query.cache.ttlInSecs=900 +#atlas.metric.query.general.typeCount= +#atlas.metric.query.general.typeUnusedCount= +#atlas.metric.query.general.entityCount= +#atlas.metric.query.general.tagCount= +#atlas.metric.query.general.entityDeleted= +# +#atlas.metric.query.entity.typeEntities= +#atlas.metric.query.entity.entityTagged= +# +#atlas.metric.query.tags.entityTags= + +######### Compiled Query Cache Configuration ######### + +# The size of the compiled query cache. Older queries will be evicted from the cache +# when we reach the capacity. + +#atlas.CompiledQueryCache.capacity=1000 + +# Allows notifications when items are evicted from the compiled query +# cache because it has become full. A warning will be issued when +# the specified number of evictions have occurred. If the eviction +# warning threshold <= 0, no eviction warnings will be issued. + +#atlas.CompiledQueryCache.evictionWarningThrottle=0 + + +######### Full Text Search Configuration ######### + +#Set to false to disable full text search. +#atlas.search.fulltext.enable=true + +######### Gremlin Search Configuration ######### + +#Set to false to disable gremlin search. +atlas.search.gremlin.enable=false + + +########## Add http headers ########### + +#atlas.headers.Access-Control-Allow-Origin=* +#atlas.headers.Access-Control-Allow-Methods=GET,OPTIONS,HEAD,PUT,POST +#atlas.headers.= \ No newline at end of file diff --git a/atlas-hub/pre-conf/atlas-simple-authz-policy.json b/atlas-hub/pre-conf/atlas-simple-authz-policy.json new file mode 100644 index 00000000000..9c81fa11a72 --- /dev/null +++ b/atlas-hub/pre-conf/atlas-simple-authz-policy.json @@ -0,0 +1,84 @@ +{ + "roles": { + "ROLE_ADMIN": { + "adminPermissions": [ + { + "privileges": [ ".*" ] + } + ], + "typePermissions": [ + { + "privileges": [ ".*" ], + "typeCategories": [ ".*" ], + "typeNames": [ ".*" ] + } + ], + "entityPermissions": [ + { + "privileges": [ ".*" ], + "entityTypes": [ ".*" ], + "entityIds": [ ".*" ], + "classifications": [ ".*" ] + } + ], + "relationshipPermissions": [ + { + "privileges": [ ".*" ], + "relationshipTypes": [ ".*" ], + "end1EntityType": [ ".*" ], + "end1EntityId": [ ".*" ], + "end1EntityClassification": [ ".*" ], + "end2EntityType": [ ".*" ], + "end2EntityId": [ ".*" ], + "end2EntityClassification": [ ".*" ] + } + ] + }, + + "DATA_SCIENTIST": { + "entityPermissions": [ + { + "privileges": [ "entity-read", "entity-read-classification" ], + "entityTypes": [ ".*" ], + "entityIds": [ ".*" ], + "classifications": [ ".*" ] + } + ] + }, + + "DATA_STEWARD": { + "entityPermissions": [ + { + "privileges": [ "entity-read", "entity-create", "entity-update", "entity-read-classification", "entity-add-classification", "entity-update-classification", "entity-remove-classification" ], + "entityTypes": [ ".*" ], + "entityIds": [ ".*" ], + "classifications": [ ".*" ] + } + ], + "relationshipPermissions": [ + { + "privileges": [ "add-relationship", "update-relationship", "remove-relationship" ], + "relationshipTypes": [ ".*" ], + "end1EntityType": [ ".*" ], + "end1EntityId": [ ".*" ], + "end1EntityClassification": [ ".*" ], + "end2EntityType": [ ".*" ], + "end2EntityId": [ ".*" ], + "end2EntityClassification": [ ".*" ] + } + ] + } + }, + + "userRoles": { + "admin": [ "ROLE_ADMIN" ], + "rangertagsync": [ "DATA_SCIENTIST" ] + }, + + "groupRoles": { + "ROLE_ADMIN": [ "ROLE_ADMIN" ], + "hadoop": [ "DATA_STEWARD" ], + "DATA_STEWARD": [ "DATA_STEWARD" ], + "RANGER_TAG_SYNC": [ "DATA_SCIENTIST" ] + } +} diff --git a/atlas-hub/pre-conf/cassandra.yml.template b/atlas-hub/pre-conf/cassandra.yml.template new file mode 100644 index 00000000000..a661c60e3b4 --- /dev/null +++ b/atlas-hub/pre-conf/cassandra.yml.template @@ -0,0 +1,683 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. + +# Cassandra storage config YAML +# Used when JanusGraph runs with Cassandra embedded inside its own JVM +# +# NOTE: IT IS NOT RECOMMENDED TO USE EMBEDDED CASSANDRA IN A PRODUCTION +# DEPLOYMENT. CASSANDRA SHOULD BE INSTALLED AND RUN SEPARATELY. +# + +# NOTE: +# See http://wiki.apache.org/cassandra/StorageConfiguration for +# full explanations of configuration directives +# + +# The name of the cluster. This is mainly used to prevent machines in +# one logical cluster from joining another. +cluster_name: 'JanusGraph' + +# This defines the number of tokens randomly assigned to this node on the ring +# The more tokens, relative to other nodes, the larger the proportion of data +# that this node will store. You probably want all nodes to have the same number +# of tokens assuming they have equal hardware capability. +# +# If you leave this unspecified, Cassandra will use the default of 1 token for legacy compatibility, +# and will use the initial_token as described below. +# +# Specifying initial_token will override this setting. +# +# If you already have a cluster with 1 token per node, and wish to migrate to +# multiple tokens per node, see http://wiki.apache.org/cassandra/Operations +num_tokens: 256 + +# initial_token allows you to specify tokens manually. While you can use # it with +# vnodes (num_tokens > 1, above) -- in which case you should provide a +# comma-separated list -- it's primarily used when adding nodes # to legacy clusters +# that do not have vnodes enabled. +# initial_token: + +# May either be "true" or "false" to enable globally, or contain a list +# of data centers to enable per-datacenter. +# hinted_handoff_enabled: DC1,DC2 +# See http://wiki.apache.org/cassandra/HintedHandoff +hinted_handoff_enabled: true +# this defines the maximum amount of time a dead host will have hints +# generated. After it has been dead this long, new hints for it will not be +# created until it has been seen alive and gone down again. +max_hint_window_in_ms: 10800000 # 3 hours +# Maximum throttle in KBs per second, per delivery thread. This will be +# reduced proportionally to the number of nodes in the cluster. (If there +# are two nodes in the cluster, each delivery thread will use the maximum +# rate; if there are three, each will throttle to half of the maximum, +# since we expect two nodes to be delivering hints simultaneously.) +hinted_handoff_throttle_in_kb: 1024 +# Number of threads with which to deliver hints; +# Consider increasing this number when you have multi-dc deployments, since +# cross-dc handoff tends to be slower +max_hints_delivery_threads: 2 + +# Maximum throttle in KBs per second, total. This will be +# reduced proportionally to the number of nodes in the cluster. +batchlog_replay_throttle_in_kb: 1024 + +# Authentication backend, implementing IAuthenticator; used to identify users +# Out of the box, Cassandra provides org.apache.cassandra.auth.{AllowAllAuthenticator, +# PasswordAuthenticator}. +# +# - AllowAllAuthenticator performs no checks - set it to disable authentication. +# - PasswordAuthenticator relies on username/password pairs to authenticate +# users. It keeps usernames and hashed passwords in system_auth.credentials table. +# Please increase system_auth keyspace replication factor if you use this authenticator. +authenticator: AllowAllAuthenticator + +# Authorization backend, implementing IAuthorizer; used to limit access/provide permissions +# Out of the box, Cassandra provides org.apache.cassandra.auth.{AllowAllAuthorizer, +# CassandraAuthorizer}. +# +# - AllowAllAuthorizer allows any action to any user - set it to disable authorization. +# - CassandraAuthorizer stores permissions in system_auth.permissions table. Please +# increase system_auth keyspace replication factor if you use this authorizer. +authorizer: AllowAllAuthorizer + +# Validity period for permissions cache (fetching permissions can be an +# expensive operation depending on the authorizer, CassandraAuthorizer is +# one example). Defaults to 2000, set to 0 to disable. +# Will be disabled automatically for AllowAllAuthorizer. +permissions_validity_in_ms: 2000 + +# The partitioner is responsible for distributing rows (by key) across +# nodes in the cluster. Any IPartitioner may be used, including your +# own as long as it is on the classpath. Out of the box, Cassandra +# provides org.apache.cassandra.dht.{Murmur3Partitioner, RandomPartitioner +# ByteOrderedPartitioner, OrderPreservingPartitioner (deprecated)}. +# +# - RandomPartitioner distributes rows across the cluster evenly by md5. +# This is the default prior to 1.2 and is retained for compatibility. +# - Murmur3Partitioner is similar to RandomPartioner but uses Murmur3_128 +# Hash Function instead of md5. When in doubt, this is the best option. +# - ByteOrderedPartitioner orders rows lexically by key bytes. BOP allows +# scanning rows in key order, but the ordering can generate hot spots +# for sequential insertion workloads. +# - OrderPreservingPartitioner is an obsolete form of BOP, that stores +# - keys in a less-efficient format and only works with keys that are +# UTF8-encoded Strings. +# - CollatingOPP collates according to EN,US rules rather than lexical byte +# ordering. Use this as an example if you need custom collation. +# +# See http://wiki.apache.org/cassandra/Operations for more on +# partitioners and token selection. +partitioner: org.apache.cassandra.dht.Murmur3Partitioner + +# Directories where Cassandra should store data on disk. Cassandra +# will spread data evenly across them, subject to the granularity of +# the configured compaction strategy. +data_file_directories: + - ${atlas_home}/data/cassandra/data + +# commit log +commitlog_directory: ${atlas_home}/data/cassandra/commitlog + +# policy for data disk failures: +# stop: shut down gossip and Thrift, leaving the node effectively dead, but +# can still be inspected via JMX. +# best_effort: stop using the failed disk and respond to requests based on +# remaining available sstables. This means you WILL see obsolete +# data at CL.ONE! +# ignore: ignore fatal errors and let requests fail, as in pre-1.2 Cassandra +disk_failure_policy: stop + +# policy for commit disk failures: +# stop: shut down gossip and Thrift, leaving the node effectively dead, but +# can still be inspected via JMX. +# stop_commit: shutdown the commit log, letting writes collect but +# continuing to service reads, as in pre-2.0.5 Cassandra +# ignore: ignore fatal errors and let the batches fail +commit_failure_policy: stop + +# Maximum size of the key cache in memory. +# +# Each key cache hit saves 1 seek and each row cache hit saves 2 seeks at the +# minimum, sometimes more. The key cache is fairly tiny for the amount of +# time it saves, so it's worthwhile to use it at large numbers. +# The row cache saves even more time, but must contain the entire row, +# so it is extremely space-intensive. It's best to only use the +# row cache if you have hot rows or static rows. +# +# NOTE: if you reduce the size, you may not get you hottest keys loaded on startup. +# +# Default value is empty to make it "auto" (min(5% of Heap (in MB), 100MB)). Set to 0 to disable key cache. +key_cache_size_in_mb: + +# Duration in seconds after which Cassandra should +# save the key cache. Caches are saved to saved_caches_directory as +# specified in this configuration file. +# +# Saved caches greatly improve cold-start speeds, and is relatively cheap in +# terms of I/O for the key cache. Row cache saving is much more expensive and +# has limited use. +# +# Default is 14400 or 4 hours. +key_cache_save_period: 14400 + +# Number of keys from the key cache to save +# Disabled by default, meaning all keys are going to be saved +# key_cache_keys_to_save: 100 + +# Maximum size of the row cache in memory. +# NOTE: if you reduce the size, you may not get you hottest keys loaded on startup. +# +# Default value is 0, to disable row caching. +row_cache_size_in_mb: 0 + +# Duration in seconds after which Cassandra should +# safe the row cache. Caches are saved to saved_caches_directory as specified +# in this configuration file. +# +# Saved caches greatly improve cold-start speeds, and is relatively cheap in +# terms of I/O for the key cache. Row cache saving is much more expensive and +# has limited use. +# +# Default is 0 to disable saving the row cache. +row_cache_save_period: 0 + +# Number of keys from the row cache to save +# Disabled by default, meaning all keys are going to be saved +# row_cache_keys_to_save: 100 + +# The off-heap memory allocator. Affects storage engine metadata as +# well as caches. Experiments show that JEMAlloc saves some memory +# than the native GCC allocator (i.e., JEMalloc is more +# fragmentation-resistant). +# +# Supported values are: NativeAllocator, JEMallocAllocator +# +# If you intend to use JEMallocAllocator you have to install JEMalloc as library and +# modify cassandra-env.sh as directed in the file. +# +# Defaults to NativeAllocator +# memory_allocator: NativeAllocator + +# saved caches +saved_caches_directory: ${atlas_home}/data/cassandra/saved_caches + +# commitlog_sync may be either "periodic" or "batch." +# When in batch mode, Cassandra won't ack writes until the commit log +# has been fsynced to disk. It will wait up to +# commitlog_sync_batch_window_in_ms milliseconds for other writes, before +# performing the sync. +# +# commitlog_sync: batch +# commitlog_sync_batch_window_in_ms: 50 +# +# the other option is "periodic" where writes may be acked immediately +# and the CommitLog is simply synced every commitlog_sync_period_in_ms +# milliseconds. By default this allows 1024*(CPU cores) pending +# entries on the commitlog queue. If you are writing very large blobs, +# you should reduce that; 16*cores works reasonably well for 1MB blobs. +# It should be at least as large as the concurrent_writes setting. +commitlog_sync: periodic +commitlog_sync_period_in_ms: 10000 +# commitlog_periodic_queue_size: + +# The size of the individual commitlog file segments. A commitlog +# segment may be archived, deleted, or recycled once all the data +# in it (potentially from each columnfamily in the system) has been +# flushed to sstables. +# +# The default size is 32, which is almost always fine, but if you are +# archiving commitlog segments (see commitlog_archiving.properties), +# then you probably want a finer granularity of archiving; 8 or 16 MB +# is reasonable. +commitlog_segment_size_in_mb: 32 + +# any class that implements the SeedProvider interface and has a +# constructor that takes a Map of parameters will do. +seed_provider: + # Addresses of hosts that are deemed contact points. + # Cassandra nodes use this list of hosts to find each other and learn + # the topology of the ring. You must change this if you are running + # multiple nodes! + - class_name: org.apache.cassandra.locator.SimpleSeedProvider + parameters: + # seeds is actually a comma-delimited list of addresses. + # Ex: ",," + - seeds: "127.0.0.1" + +# For workloads with more data than can fit in memory, Cassandra's +# bottleneck will be reads that need to fetch data from +# disk. "concurrent_reads" should be set to (16 * number_of_drives) in +# order to allow the operations to enqueue low enough in the stack +# that the OS and drives can reorder them. +# +# On the other hand, since writes are almost never IO bound, the ideal +# number of "concurrent_writes" is dependent on the number of cores in +# your system; (8 * number_of_cores) is a good rule of thumb. +concurrent_reads: 32 +concurrent_writes: 32 + +# Total memory to use for sstable-reading buffers. Defaults to +# the smaller of 1/4 of heap or 512MB. +# file_cache_size_in_mb: 512 + +# Total memory to use for memtables. Cassandra will flush the largest +# memtable when this much memory is used. +# If omitted, Cassandra will set it to 1/4 of the heap. +# memtable_total_space_in_mb: 2048 + +# Total space to use for commitlogs. Since commitlog segments are +# mmapped, and hence use up address space, the default size is 32 +# on 32-bit JVMs, and 1024 on 64-bit JVMs. +# +# If space gets above this value (it will round up to the next nearest +# segment multiple), Cassandra will flush every dirty CF in the oldest +# segment and remove it. So a small total commitlog space will tend +# to cause more flush activity on less-active columnfamilies. +# commitlog_total_space_in_mb: 4096 + +# This sets the amount of memtable flush writer threads. These will +# be blocked by disk io, and each one will hold a memtable in memory +# while blocked. If you have a large heap and many data directories, +# you can increase this value for better flush performance. +# By default this will be set to the amount of data directories defined. +#memtable_flush_writers: 1 + +# Whether to, when doing sequential writing, fsync() at intervals in +# order to force the operating system to flush the dirty +# buffers. Enable this to avoid sudden dirty buffer flushing from +# impacting read latencies. Almost always a good idea on SSDs; not +# necessarily on platters. +trickle_fsync: false +trickle_fsync_interval_in_kb: 10240 + +# TCP port, for commands and data +storage_port: 7000 + +# SSL port, for encrypted communication. Unused unless enabled in +# encryption_options +ssl_storage_port: 7001 + +# Address to bind to and tell other Cassandra nodes to connect to. You +# _must_ change this if you want multiple nodes to be able to +# communicate! +# +# Leaving it blank leaves it up to InetAddress.getLocalHost(). This +# will always do the Right Thing _if_ the node is properly configured +# (hostname, name resolution, etc), and the Right Thing is to use the +# address associated with the hostname (it might not be). +# +# Setting this to 0.0.0.0 is always wrong. +listen_address: localhost + +# Address to broadcast to other Cassandra nodes +# Leaving this blank will set it to the same value as listen_address +# broadcast_address: 1.2.3.4 + +# Internode authentication backend, implementing IInternodeAuthenticator; +# used to allow/disallow connections from peer nodes. +# internode_authenticator: org.apache.cassandra.auth.AllowAllInternodeAuthenticator + +# Whether to start the native transport server. +# Please note that the address on which the native transport is bound is the +# same as the rpc_address. The port however is different and specified below. +start_native_transport: true +# port for the CQL native transport to listen for clients on +native_transport_port: 9042 +# The maximum threads for handling requests when the native transport is used. +# This is similar to rpc_max_threads though the default differs slightly (and +# there is no native_transport_min_threads, idle threads will always be stopped +# after 30 seconds). +# native_transport_max_threads: 128 +# +# The maximum size of allowed frame. Frame (requests) larger than this will +# be rejected as invalid. The default is 256MB. +# native_transport_max_frame_size_in_mb: 256 + +# Whether to start the thrift rpc server. +start_rpc: true + +# The address to bind the Thrift RPC service and native transport +# server -- clients connect here. +# +# Leaving this blank has the same effect it does for ListenAddress, +# (i.e. it will be based on the configured hostname of the node). +# +# Note that unlike ListenAddress above, it is allowed to specify 0.0.0.0 +# here if you want to listen on all interfaces, but that will break clients +# that rely on node auto-discovery. +rpc_address: localhost +# port for Thrift to listen for clients on +rpc_port: 9160 + +# enable or disable keepalive on rpc connections +rpc_keepalive: true + +# Cassandra provides two out-of-the-box options for the RPC Server: +# +# sync -> One thread per thrift connection. For a very large number of clients, memory +# will be your limiting factor. On a 64 bit JVM, 180KB is the minimum stack size +# per thread, and that will correspond to your use of virtual memory (but physical memory +# may be limited depending on use of stack space). +# +# hsha -> Stands for "half synchronous, half asynchronous." All thrift clients are handled +# asynchronously using a small number of threads that does not vary with the amount +# of thrift clients (and thus scales well to many clients). The rpc requests are still +# synchronous (one thread per active request). +# +# The default is sync because on Windows hsha is about 30% slower. On Linux, +# sync/hsha performance is about the same, with hsha of course using less memory. +# +# Alternatively, can provide your own RPC server by providing the fully-qualified class name +# of an o.a.c.t.TServerFactory that can create an instance of it. +rpc_server_type: sync + +# Uncomment rpc_min|max_thread to set request pool size limits. +# +# Regardless of your choice of RPC server (see above), the number of maximum requests in the +# RPC thread pool dictates how many concurrent requests are possible (but if you are using the sync +# RPC server, it also dictates the number of clients that can be connected at all). +# +# The default is unlimited and thus provides no protection against clients overwhelming the server. You are +# encouraged to set a maximum that makes sense for you in production, but do keep in mind that +# rpc_max_threads represents the maximum number of client requests this server may execute concurrently. +# +# rpc_min_threads: 16 +# rpc_max_threads: 2048 + +# uncomment to set socket buffer sizes on rpc connections +# rpc_send_buff_size_in_bytes: +# rpc_recv_buff_size_in_bytes: + +# Uncomment to set socket buffer size for internode communication +# Note that when setting this, the buffer size is limited by net.core.wmem_max +# and when not setting it it is defined by net.ipv4.tcp_wmem +# See: +# /proc/sys/net/core/wmem_max +# /proc/sys/net/core/rmem_max +# /proc/sys/net/ipv4/tcp_wmem +# /proc/sys/net/ipv4/tcp_wmem +# and: man tcp +# internode_send_buff_size_in_bytes: +# internode_recv_buff_size_in_bytes: + +# Frame size for thrift (maximum message length). +thrift_framed_transport_size_in_mb: 15 + +# Set to true to have Cassandra create a hard link to each sstable +# flushed or streamed locally in a backups/ subdirectory of the +# keyspace data. Removing these links is the operator's +# responsibility. +incremental_backups: false + +# Whether or not to take a snapshot before each compaction. Be +# careful using this option, since Cassandra won't clean up the +# snapshots for you. Mostly useful if you're paranoid when there +# is a data format change. +snapshot_before_compaction: false + +# Whether or not a snapshot is taken of the data before keyspace truncation +# or dropping of column families. The STRONGLY advised default of true +# should be used to provide data safety. If you set this flag to false, you will +# lose data on truncation or drop. +auto_snapshot: true + +# When executing a scan, within or across a partition, we need to keep the +# tombstones seen in memory so we can return them to the coordinator, which +# will use them to make sure other replicas also know about the deleted rows. +# With workloads that generate a lot of tombstones, this can cause performance +# problems and even exaust the server heap. +# (http://www.datastax.com/dev/blog/cassandra-anti-patterns-queues-and-queue-like-datasets) +# Adjust the thresholds here if you understand the dangers and want to +# scan more tombstones anyway. These thresholds may also be adjusted at runtime +# using the StorageService mbean. +tombstone_warn_threshold: 1000 +tombstone_failure_threshold: 100000 + +# Add column indexes to a row after its contents reach this size. +# Increase if your column values are large, or if you have a very large +# number of columns. The competing causes are, Cassandra has to +# deserialize this much of the row to read a single column, so you want +# it to be small - at least if you do many partial-row reads - but all +# the index data is read for each access, so you don't want to generate +# that wastefully either. +column_index_size_in_kb: 64 + +# Number of simultaneous compactions to allow, NOT including +# validation "compactions" for anti-entropy repair. Simultaneous +# compactions can help preserve read performance in a mixed read/write +# workload, by mitigating the tendency of small sstables to accumulate +# during a single long running compactions. The default is usually +# fine and if you experience problems with compaction running too +# slowly or too fast, you should look at +# compaction_throughput_mb_per_sec first. +# +# concurrent_compactors defaults to the number of cores. +# Uncomment to make compaction mono-threaded, the pre-0.8 default. +#concurrent_compactors: 1 + +# Throttles compaction to the given total throughput across the entire +# system. The faster you insert data, the faster you need to compact in +# order to keep the sstable count down, but in general, setting this to +# 16 to 32 times the rate you are inserting data is more than sufficient. +# Setting this to 0 disables throttling. Note that this account for all types +# of compaction, including validation compaction. +compaction_throughput_mb_per_sec: 16 + +# Throttles all outbound streaming file transfers on this node to the +# given total throughput in Mbps. This is necessary because Cassandra does +# mostly sequential IO when streaming data during bootstrap or repair, which +# can lead to saturating the network connection and degrading rpc performance. +# When unset, the default is 200 Mbps or 25 MB/s. +# stream_throughput_outbound_megabits_per_sec: 200 + +# How long the coordinator should wait for read operations to complete +read_request_timeout_in_ms: 5000 +# How long the coordinator should wait for seq or index scans to complete +range_request_timeout_in_ms: 10000 +# How long the coordinator should wait for writes to complete +write_request_timeout_in_ms: 2000 +# How long a coordinator should continue to retry a CAS operation +# that contends with other proposals for the same row +cas_contention_timeout_in_ms: 1000 +# How long the coordinator should wait for truncates to complete +# (This can be much longer, because unless auto_snapshot is disabled +# we need to flush first so we can snapshot before removing the data.) +truncate_request_timeout_in_ms: 60000 +# The default timeout for other, miscellaneous operations +request_timeout_in_ms: 10000 + +# Enable operation timeout information exchange between nodes to accurately +# measure request timeouts. If disabled, replicas will assume that requests +# were forwarded to them instantly by the coordinator, which means that +# under overload conditions we will waste that much extra time processing +# already-timed-out requests. +# +# Warning: before enabling this property make sure to ntp is installed +# and the times are synchronized between the nodes. +cross_node_timeout: false + +# Enable socket timeout for streaming operation. +# When a timeout occurs during streaming, streaming is retried from the start +# of the current file. This _can_ involve re-streaming an important amount of +# data, so you should avoid setting the value too low. +# Default value is 0, which never timeout streams. +# streaming_socket_timeout_in_ms: 0 + +# phi value that must be reached for a host to be marked down. +# most users should never need to adjust this. +# phi_convict_threshold: 8 + +# endpoint_snitch -- Set this to a class that implements +# IEndpointSnitch. The snitch has two functions: +# - it teaches Cassandra enough about your network topology to route +# requests efficiently +# - it allows Cassandra to spread replicas around your cluster to avoid +# correlated failures. It does this by grouping machines into +# "datacenters" and "racks." Cassandra will do its best not to have +# more than one replica on the same "rack" (which may not actually +# be a physical location) +# +# IF YOU CHANGE THE SNITCH AFTER DATA IS INSERTED INTO THE CLUSTER, +# YOU MUST RUN A FULL REPAIR, SINCE THE SNITCH AFFECTS WHERE REPLICAS +# ARE PLACED. +# +# Out of the box, Cassandra provides +# - SimpleSnitch: +# Treats Strategy order as proximity. This improves cache locality +# when disabling read repair, which can further improve throughput. +# Only appropriate for single-datacenter deployments. +# - PropertyFileSnitch: +# Proximity is determined by rack and data center, which are +# explicitly configured in cassandra-topology.properties. +# - GossipingPropertyFileSnitch +# The rack and datacenter for the local node are defined in +# cassandra-rackdc.properties and propagated to other nodes via gossip. If +# cassandra-topology.properties exists, it is used as a fallback, allowing +# migration from the PropertyFileSnitch. +# - RackInferringSnitch: +# Proximity is determined by rack and data center, which are +# assumed to correspond to the 3rd and 2nd octet of each node's +# IP address, respectively. Unless this happens to match your +# deployment conventions (as it did Facebook's), this is best used +# as an example of writing a custom Snitch class. +# - Ec2Snitch: +# Appropriate for EC2 deployments in a single Region. Loads Region +# and Availability Zone information from the EC2 API. The Region is +# treated as the datacenter, and the Availability Zone as the rack. +# Only private IPs are used, so this will not work across multiple +# Regions. +# - Ec2MultiRegionSnitch: +# Uses public IPs as broadcast_address to allow cross-region +# connectivity. (Thus, you should set seed addresses to the public +# IP as well.) You will need to open the storage_port or +# ssl_storage_port on the public IP firewall. (For intra-Region +# traffic, Cassandra will switch to the private IP after +# establishing a connection.) +# +# You can use a custom Snitch by setting this to the full class name +# of the snitch, which will be assumed to be on your classpath. +endpoint_snitch: SimpleSnitch + +# controls how often to perform the more expensive part of host score +# calculation +dynamic_snitch_update_interval_in_ms: 100 +# controls how often to reset all host scores, allowing a bad host to +# possibly recover +dynamic_snitch_reset_interval_in_ms: 600000 +# if set greater than zero and read_repair_chance is < 1.0, this will allow +# 'pinning' of replicas to hosts in order to increase cache capacity. +# The badness threshold will control how much worse the pinned host has to be +# before the dynamic snitch will prefer other replicas over it. This is +# expressed as a double which represents a percentage. Thus, a value of +# 0.2 means Cassandra would continue to prefer the static snitch values +# until the pinned host was 20% worse than the fastest. +dynamic_snitch_badness_threshold: 0.1 + +# request_scheduler -- Set this to a class that implements +# RequestScheduler, which will schedule incoming client requests +# according to the specific policy. This is useful for multi-tenancy +# with a single Cassandra cluster. +# NOTE: This is specifically for requests from the client and does +# not affect inter node communication. +# org.apache.cassandra.scheduler.NoScheduler - No scheduling takes place +# org.apache.cassandra.scheduler.RoundRobinScheduler - Round robin of +# client requests to a node with a separate queue for each +# request_scheduler_id. The scheduler is further customized by +# request_scheduler_options as described below. +request_scheduler: org.apache.cassandra.scheduler.NoScheduler + +# Scheduler Options vary based on the type of scheduler +# NoScheduler - Has no options +# RoundRobin +# - throttle_limit -- The throttle_limit is the number of in-flight +# requests per client. Requests beyond +# that limit are queued up until +# running requests can complete. +# The value of 80 here is twice the number of +# concurrent_reads + concurrent_writes. +# - default_weight -- default_weight is optional and allows for +# overriding the default which is 1. +# - weights -- Weights are optional and will default to 1 or the +# overridden default_weight. The weight translates into how +# many requests are handled during each turn of the +# RoundRobin, based on the scheduler id. +# +# request_scheduler_options: +# throttle_limit: 80 +# default_weight: 5 +# weights: +# Keyspace1: 1 +# Keyspace2: 5 + +# request_scheduler_id -- An identifier based on which to perform +# the request scheduling. Currently the only valid option is keyspace. +# request_scheduler_id: keyspace + +# Enable or disable inter-node encryption +# Default settings are TLS v1, RSA 1024-bit keys (it is imperative that +# users generate their own keys) TLS_RSA_WITH_AES_128_CBC_SHA as the cipher +# suite for authentication, key exchange and encryption of the actual data transfers. +# NOTE: No custom encryption options are enabled at the moment +# The available internode options are : all, none, dc, rack +# +# If set to dc cassandra will encrypt the traffic between the DCs +# If set to rack cassandra will encrypt the traffic between the racks +# +# The passwords used in these options must match the passwords used when generating +# the keystore and truststore. For instructions on generating these files, see: +# http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html#CreateKeystore +# +server_encryption_options: + internode_encryption: none + keystore: conf/.keystore + keystore_password: cassandra + truststore: conf/.truststore + truststore_password: cassandra + # More advanced defaults below: + # protocol: TLS + # algorithm: SunX509 + # store_type: JKS + # cipher_suites: [TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA] + # require_client_auth: false + +# enable or disable client/server encryption. +client_encryption_options: + enabled: false + keystore: conf/.keystore + keystore_password: cassandra + # require_client_auth: false + # Set trustore and truststore_password if require_client_auth is true + # truststore: conf/.truststore + # truststore_password: cassandra + # More advanced defaults below: + # protocol: TLS + # algorithm: SunX509 + # store_type: JKS + # cipher_suites: [TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA] + +# internode_compression controls whether traffic between nodes is +# compressed. +# can be: all - all traffic is compressed +# dc - traffic between different datacenters is compressed +# none - nothing is compressed. +internode_compression: all + +# Enable or disable tcp_nodelay for inter-dc communication. +# Disabling it will result in larger (but fewer) network packets being sent, +# reducing overhead from the TCP protocol itself, at the cost of increasing +# latency if you block for cross-datacenter responses. +inter_dc_tcp_nodelay: false + diff --git a/atlas-hub/pre-conf/hbase/hbase-site.xml.template b/atlas-hub/pre-conf/hbase/hbase-site.xml.template new file mode 100644 index 00000000000..d599c20c1de --- /dev/null +++ b/atlas-hub/pre-conf/hbase/hbase-site.xml.template @@ -0,0 +1,44 @@ + + + + + + hbase.rootdir + ${url_prefix}${atlas_data}/hbase-root + + + hbase.zookeeper.property.dataDir + ${atlas_data}/hbase-zookeeper-data + + + hbase.master.info.port + 61510 + + + hbase.regionserver.info.port + 61530 + + + hbase.master.port + 61500 + + + hbase.regionserver.port + 61520 + + diff --git a/atlas-hub/pre-conf/keycloak.json b/atlas-hub/pre-conf/keycloak.json new file mode 100644 index 00000000000..bda2493dd3c --- /dev/null +++ b/atlas-hub/pre-conf/keycloak.json @@ -0,0 +1,11 @@ +#we dont use this one. Its only here for reference. We use this file from config map in helm chart +{ + "realm": "KEYCLOAK_REALM", + "auth-server-url": "AUTH_SERVER_URL", + "ssl-required": "external", + "resource": "KEYCLOAK_ATLAS_RESOURCE", + "public-client": true, + "confidential-port": 443, + "principal-attribute": "preferred_username", + "autodetect-bearer-only": true +} diff --git a/atlas-hub/pre-conf/users-credentials.properties b/atlas-hub/pre-conf/users-credentials.properties new file mode 100644 index 00000000000..3fc3bb1723f --- /dev/null +++ b/atlas-hub/pre-conf/users-credentials.properties @@ -0,0 +1,3 @@ +#username=group::sha256-password +admin=ADMIN::8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918 +rangertagsync=RANGER_TAG_SYNC::e3f67240f5117d1753c940dae9eea772d36ed5fe9bd9c94a300e40413f1afb9d diff --git a/atlas-hub/pre-conf/zookeeper/zoo.cfg.template b/atlas-hub/pre-conf/zookeeper/zoo.cfg.template new file mode 100644 index 00000000000..ac281a3b897 --- /dev/null +++ b/atlas-hub/pre-conf/zookeeper/zoo.cfg.template @@ -0,0 +1,45 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +# The number of milliseconds of each tick +tickTime=2000 +# The number of ticks that the initial +# synchronization phase can take +initLimit=10 +# The number of ticks that can pass between +# sending a request and getting an acknowledgement +syncLimit=5 +# the directory where the snapshot is stored. +# do not use /tmp for storage, /tmp here is just +# example sakes. +dataDir=${atlas_home}/data/zookeeper/data +# the port at which the clients will connect +clientPort=2181 +# the maximum number of client connections. +# increase this if you need to handle more clients +#maxClientCnxns=60 +# +# Be sure to read the maintenance section of the +# administrator guide before turning on autopurge. +# +# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance +# +# The number of snapshots to retain in dataDir +#autopurge.snapRetainCount=3 +# Purge task interval in hours +# Set to "0" to disable auto purge feature +#autopurge.purgeInterval=1 diff --git a/tools/atlas-index-repair/src/main/resources/repair_index.py b/atlas-hub/repair_index.py old mode 100755 new mode 100644 similarity index 97% rename from tools/atlas-index-repair/src/main/resources/repair_index.py rename to atlas-hub/repair_index.py index 0333dadca7e..bbdc85442e0 --- a/tools/atlas-index-repair/src/main/resources/repair_index.py +++ b/atlas-hub/repair_index.py @@ -106,10 +106,10 @@ def main(): if is_hbase and mc.is_hbase_local(confdir): - print("configured for local hbase.") + print "configured for local hbase." mc.configure_hbase(atlas_home) mc.run_hbase_action(mc.hbaseBinDir(atlas_home), "start", hbase_conf_dir, logdir) - print("hbase started.") + print "hbase started." web_app_path = os.path.join(web_app_dir, "atlas") if (mc.isCygwin()): @@ -146,8 +146,8 @@ def java(classname, args, classpath, jvm_opts_list): try: returncode = main() except Exception as e: - print("Exception: %s " % str(e)) - print(traceback.format_exc()) + print "Exception: %s " % str(e) + print traceback.format_exc() returncode = -1 sys.exit(returncode) diff --git a/atlas-hub/start.sh b/atlas-hub/start.sh new file mode 100755 index 00000000000..3af1debd2b6 --- /dev/null +++ b/atlas-hub/start.sh @@ -0,0 +1,25 @@ +#!/bin/sh +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +sudo docker run -d \ + -p 21000:21000 \ + -v ${PWD}/pre-conf:/opt/apache-atlas-2.0.0/conf \ + --name atlas \ + apache-atlas:2.0.0 \ + /opt/apache-atlas-2.0.0/bin/atlas_start.py diff --git a/atlas-hub/stop.sh b/atlas-hub/stop.sh new file mode 100755 index 00000000000..8186feea459 --- /dev/null +++ b/atlas-hub/stop.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# + +sudo docker exec -ti atlas /opt/apache-atlas-2.0.0/bin/atlas_stop.py \ No newline at end of file diff --git a/auth-agents-common/pom.xml b/auth-agents-common/pom.xml new file mode 100644 index 00000000000..0908cdf2025 --- /dev/null +++ b/auth-agents-common/pom.xml @@ -0,0 +1,142 @@ + + + + + apache-atlas + org.apache.atlas + 3.0.0-SNAPSHOT + + 4.0.0 + + auth-agents-common + + + 17 + 17 + + 1.9.13 + 32.0.1-jre + + + + + org.apache.atlas + atlas-intg + ${project.version} + + + + org.apache.atlas + atlas-repository + ${project.version} + + + + org.apache.atlas + client-auth + ${project.version} + + + + org.apache.atlas + auth-common + ${project.version} + + + + org.apache.atlas + auth-audits + ${project.version} + + + + javax.servlet + javax.servlet-api + + + + com.sun.jersey + jersey-client + + + + org.codehaus.jackson + jackson-jaxrs + ${jackson-jaxrs.version} + + + + com.google.guava + guava + ${guava.version} + + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + ${maven-shade-plugin} + + + package + + shade + + + false + true + + + *:* + + **/*.md + **/*.txt + **/*.yml + **/*.properties + + + + + + org.slf4j:* + com.google.api.grpc:* + org.janusgraph:* + com.google.protobuf:* + com.squareup.okhttp:* + org.apache.lucene:* + org.apache.hbase:* + com.datastax.oss:* + org.apache.tinkerpop + org.keycloak:* + + + + + + + + + + \ No newline at end of file diff --git a/auth-agents-common/src/main/java/org/apache/atlas/authorization/config/RangerAdminConfig.java b/auth-agents-common/src/main/java/org/apache/atlas/authorization/config/RangerAdminConfig.java new file mode 100644 index 00000000000..c20ed1e2fba --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/authorization/config/RangerAdminConfig.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.authorization.config; + +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.security.KeyStore; + +public class RangerAdminConfig extends RangerConfiguration { + private static final Logger LOG = LoggerFactory.getLogger(RangerAdminConfig.class); + + private static volatile RangerAdminConfig sInstance = null; + private final boolean isFipsEnabled; + + public static RangerAdminConfig getInstance() { + RangerAdminConfig ret = RangerAdminConfig.sInstance; + + if (ret == null) { + synchronized (RangerAdminConfig.class) { + ret = RangerAdminConfig.sInstance; + + if (ret == null) { + ret = RangerAdminConfig.sInstance = new RangerAdminConfig(); + } + } + } + + return ret; + } + + private RangerAdminConfig() { + super(); + addAdminResources(); + String storeType = KeyStore.getDefaultType(); + isFipsEnabled = StringUtils.equalsIgnoreCase("bcfks", storeType) ? true : false; + } + + private boolean addAdminResources() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> addAdminResources()"); + } + + String defaultCfg = "ranger-admin-default-site.xml"; + String addlCfg = "ranger-admin-site.xml"; + String coreCfg = "core-site.xml"; + + boolean ret = true; + + if (!addResourceIfReadable(defaultCfg)) { + ret = false; + } + + if (!addResourceIfReadable(addlCfg)) { + ret = false; + } + + if (!addResourceIfReadable(coreCfg)){ + ret = false; + } + + if (! ret) { + LOG.error("Could not add ranger-admin resources to RangerAdminConfig."); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== addAdminResources(), result=" + ret); + } + + return ret; + } + + public boolean isFipsEnabled() { + return isFipsEnabled; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/authorization/config/RangerAuditConfig.java b/auth-agents-common/src/main/java/org/apache/atlas/authorization/config/RangerAuditConfig.java new file mode 100644 index 00000000000..8a742fd3291 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/authorization/config/RangerAuditConfig.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.authorization.config; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RangerAuditConfig extends RangerConfiguration { + private static final Logger LOG = LoggerFactory.getLogger(RangerAuditConfig.class); + + private final boolean initSuccess; + + public RangerAuditConfig() { + this("standalone"); + } + + public RangerAuditConfig(String serviceName) { + super(); + + initSuccess = addAuditResources(serviceName); + } + + public boolean isInitSuccess() { return initSuccess; } + + private boolean addAuditResources(String serviceName) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> addAuditResources()"); + } + + String defaultCfg = "ranger-" + serviceName + "-audit.xml"; + + boolean ret = true; + + if (!addResourceIfReadable(defaultCfg)) { + LOG.error("Could not add " + defaultCfg + " to RangerAuditConfig."); + ret = false; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== addAuditResources(), result=" + ret); + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/authorization/config/RangerConfiguration.java b/auth-agents-common/src/main/java/org/apache/atlas/authorization/config/RangerConfiguration.java new file mode 100644 index 00000000000..44b0043c32d --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/authorization/config/RangerConfiguration.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.authorization.config; + +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.conf.Configuration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Properties; + +import static org.apache.atlas.ApplicationProperties.ATLAS_CONFIGURATION_DIRECTORY_PROPERTY; + + +public class RangerConfiguration extends Configuration { + private static final Logger LOG = LoggerFactory.getLogger(RangerConfiguration.class); + + protected RangerConfiguration() { + super(false); + } + + public boolean addResourceIfReadable(String aResourceName) { + boolean ret = false; + + if(LOG.isDebugEnabled()) { + LOG.debug("==> addResourceIfReadable(" + aResourceName + ")"); + } + + URL fUrl = getFileLocation(aResourceName); + if (fUrl != null) { + if(LOG.isInfoEnabled()) { + LOG.info("addResourceIfReadable(" + aResourceName + "): resource file is " + fUrl); + } + + try { + addResource(fUrl); + ret = true; + } catch (Exception e) { + LOG.error("Unable to load the resource name [" + aResourceName + "]. Ignoring the resource:" + fUrl); + if (LOG.isDebugEnabled()) { + LOG.debug("Resource loading failed for " + fUrl, e); + } + } + } else { + LOG.warn("addResourceIfReadable(" + aResourceName + "): couldn't find resource file location"); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== addResourceIfReadable(" + aResourceName + "), result=" + ret); + } + return ret; + } + + public Properties getProperties() { + return getProps(); + } + + private URL getFileLocation(String fileName) { + String confLocation = System.getProperty(ATLAS_CONFIGURATION_DIRECTORY_PROPERTY); + URL lurl = null; + if (!StringUtils.isEmpty(fileName)) { + lurl = RangerConfiguration.class.getClassLoader().getResource(fileName); + + if (lurl == null ) { + lurl = RangerConfiguration.class.getClassLoader().getResource("/" + fileName); + } + + if (lurl == null ) { + File f = null; + if (StringUtils.isNotEmpty(confLocation)) { + f = new File(confLocation, fileName); + } else { + f = new File(fileName); + } + + if (f.exists()) { + try { + lurl = f.toURI().toURL(); + } catch (MalformedURLException e) { + LOG.error("Unable to load the resource name [" + fileName + "]. Ignoring the resource:" + f.getPath()); + } + } else { + if(LOG.isDebugEnabled()) { + LOG.debug("Conf file path " + fileName + " does not exists"); + } + } + } + } + return lurl; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/authorization/config/RangerPluginConfig.java b/auth-agents-common/src/main/java/org/apache/atlas/authorization/config/RangerPluginConfig.java new file mode 100644 index 00000000000..c89cd8baaa1 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/authorization/config/RangerPluginConfig.java @@ -0,0 +1,220 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.authorization.config; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.atlas.authorization.utils.RangerUtil; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngineOptions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + + +public class RangerPluginConfig extends RangerConfiguration { + private static final Logger LOG = LoggerFactory.getLogger(RangerPluginConfig.class); + + private static final char RANGER_TRUSTED_PROXY_IPADDRESSES_SEPARATOR_CHAR = ','; + + private final String serviceType; + private final String serviceName; + private final String appId; + private final String clusterName; + private final String clusterType; + private final RangerPolicyEngineOptions policyEngineOptions; + private final boolean useForwardedIPAddress; + private final String[] trustedProxyAddresses; + private final String propertyPrefix; + private boolean isFallbackSupported; + private Set auditExcludedUsers = Collections.emptySet(); + private Set auditExcludedGroups = Collections.emptySet(); + private Set auditExcludedRoles = Collections.emptySet(); + private Set superUsers = Collections.emptySet(); + private Set superGroups = Collections.emptySet(); + private Set serviceAdmins = Collections.emptySet(); + + + public RangerPluginConfig(String serviceType, String serviceName, String appId, String clusterName, String clusterType, RangerPolicyEngineOptions policyEngineOptions) { + super(); + + this.serviceType = serviceType; + this.appId = StringUtils.isEmpty(appId) ? serviceType : appId; + this.propertyPrefix = "atlas.plugin." + serviceType; + this.serviceName = StringUtils.isEmpty(serviceName) ? this.get(propertyPrefix + ".service.name") : serviceName; + + addResourcesForServiceName(this.serviceType, this.serviceName); + + String trustedProxyAddressString = this.get(propertyPrefix + ".trusted.proxy.ipaddresses"); + + if (RangerUtil.isEmpty(clusterName)) { + clusterName = this.get(propertyPrefix + ".access.cluster.name", ""); + + if (RangerUtil.isEmpty(clusterName)) { + clusterName = this.get(propertyPrefix + ".ambari.cluster.name", ""); + } + } + + if (RangerUtil.isEmpty(clusterType)) { + clusterType = this.get(propertyPrefix + ".access.cluster.type", ""); + + if (RangerUtil.isEmpty(clusterType)) { + clusterType = this.get(propertyPrefix + ".ambari.cluster.type", ""); + } + } + + this.clusterName = clusterName; + this.clusterType = clusterType; + this.useForwardedIPAddress = this.getBoolean(propertyPrefix + ".use.x-forwarded-for.ipaddress", false); + this.trustedProxyAddresses = StringUtils.split(trustedProxyAddressString, RANGER_TRUSTED_PROXY_IPADDRESSES_SEPARATOR_CHAR); + + if (trustedProxyAddresses != null) { + for (int i = 0; i < trustedProxyAddresses.length; i++) { + trustedProxyAddresses[i] = trustedProxyAddresses[i].trim(); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug(propertyPrefix + ".use.x-forwarded-for.ipaddress:" + useForwardedIPAddress); + LOG.debug(propertyPrefix + ".trusted.proxy.ipaddresses:[" + StringUtils.join(trustedProxyAddresses, ", ") + "]"); + } + + if (useForwardedIPAddress && StringUtils.isBlank(trustedProxyAddressString)) { + LOG.warn("Property " + propertyPrefix + ".use.x-forwarded-for.ipaddress" + " is set to true, and Property " + propertyPrefix + ".trusted.proxy.ipaddresses" + " is not set"); + LOG.warn("Ranger plugin will trust RemoteIPAddress and treat first X-Forwarded-Address in the access-request as the clientIPAddress"); + } + + if (policyEngineOptions == null) { + policyEngineOptions = new RangerPolicyEngineOptions(); + + policyEngineOptions.configureForPlugin(this, propertyPrefix); + } + + this.policyEngineOptions = policyEngineOptions; + + LOG.info(policyEngineOptions.toString()); + } + + public String getServiceType() { + return serviceType; + } + + public String getAppId() { + return appId; + } + + public String getServiceName() { + return serviceName; + } + + public String getClusterName() { + return clusterName; + } + + public String getClusterType() { + return clusterType; + } + + public boolean isUseForwardedIPAddress() { + return useForwardedIPAddress; + } + + public String[] getTrustedProxyAddresses() { + return trustedProxyAddresses; + } + + public String getPropertyPrefix() { + return propertyPrefix; + } + + public boolean getIsFallbackSupported() { + return isFallbackSupported; + } + + public void setIsFallbackSupported(boolean isFallbackSupported) { + this.isFallbackSupported = isFallbackSupported; + } + + public RangerPolicyEngineOptions getPolicyEngineOptions() { + return policyEngineOptions; + } + + public void setAuditExcludedUsersGroupsRoles(Set users, Set groups, Set roles) { + auditExcludedUsers = CollectionUtils.isEmpty(users) ? Collections.emptySet() : new HashSet<>(users); + auditExcludedGroups = CollectionUtils.isEmpty(groups) ? Collections.emptySet() : new HashSet<>(groups); + auditExcludedRoles = CollectionUtils.isEmpty(roles) ? Collections.emptySet() : new HashSet<>(roles); + + if (LOG.isDebugEnabled()) { + LOG.debug("auditExcludedUsers=" + auditExcludedUsers + ", auditExcludedGroups=" + auditExcludedGroups + ", auditExcludedRoles=" + auditExcludedRoles); + } + } + + public void setSuperUsersGroups(Set users, Set groups) { + superUsers = CollectionUtils.isEmpty(users) ? Collections.emptySet() : new HashSet<>(users); + superGroups = CollectionUtils.isEmpty(groups) ? Collections.emptySet() : new HashSet<>(groups); + + if (LOG.isDebugEnabled()) { + LOG.debug("superUsers=" + superUsers + ", superGroups=" + superGroups); + } + } + + public void setServiceAdmins(Set users) { + serviceAdmins = CollectionUtils.isEmpty(users) ? Collections.emptySet() : new HashSet<>(users); + } + + public boolean isAuditExcludedUser(String userName) { + return auditExcludedUsers.contains(userName); + } + + public boolean hasAuditExcludedGroup(Set userGroups) { + return userGroups != null && userGroups.size() > 0 && auditExcludedGroups.size() > 0 && CollectionUtils.containsAny(userGroups, auditExcludedGroups); + } + + public boolean hasAuditExcludedRole(Set userRoles) { + return userRoles != null && userRoles.size() > 0 && auditExcludedRoles.size() > 0 && CollectionUtils.containsAny(userRoles, auditExcludedRoles); + } + + public boolean isSuperUser(String userName) { + return superUsers.contains(userName); + } + + public boolean hasSuperGroup(Set userGroups) { + return userGroups != null && userGroups.size() > 0 && superGroups.size() > 0 && CollectionUtils.containsAny(userGroups, superGroups); + } + + public boolean isServiceAdmin(String userName) { + return serviceAdmins.contains(userName); + } + + // load service specific config overrides, if config files are available + private void addResourcesForServiceName(String serviceType, String serviceName) { + if (StringUtils.isNotBlank(serviceType) && StringUtils.isNotBlank(serviceName)) { + String serviceAuditCfg = "atlas-" + serviceName + "-audit.xml"; + String serviceSecurityCfg = "atlas-" + serviceName + "-security.xml"; + String serviceSslCfg = "atlas-" + serviceName + "-policymgr-ssl.xml"; + + addResourceIfReadable(serviceAuditCfg); + addResourceIfReadable(serviceSecurityCfg); + addResourceIfReadable(serviceSslCfg); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/authorization/utils/RangerUtil.java b/auth-agents-common/src/main/java/org/apache/atlas/authorization/utils/RangerUtil.java new file mode 100644 index 00000000000..3b3d6ae10ef --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/authorization/utils/RangerUtil.java @@ -0,0 +1,178 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.authorization.utils; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; +import org.apache.atlas.plugin.model.AuditFilter; +import org.apache.atlas.plugin.model.RangerValiditySchedule; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; + +public class RangerUtil { + + private static final Log LOG = LogFactory.getLog(RangerUtil.class); + + private static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT+0"); + + private static final ThreadLocal gson = new ThreadLocal() { + @Override + protected Gson initialValue() { + return new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z").create(); + } + }; + + public static String objectToJson(Object object) { + String ret = null; + + if(object != null) { + try { + ret = gson.get().toJson(object); + } catch(Exception excp) { + LOG.warn("objectToJson() failed to convert object to Json", excp); + } + } + + return ret; + } + + public static List jsonToRangerValiditySchedule(String jsonStr) { + try { + Type listType = new TypeToken>() {}.getType(); + return gson.get().fromJson(jsonStr, listType); + } catch (Exception e) { + LOG.error("Cannot get List from " + jsonStr, e); + return null; + } + } + + public static List jsonToAuditFilterList(String jsonStr) { + try { + Type listType = new TypeToken>() {}.getType(); + return gson.get().fromJson(jsonStr, listType); + } catch (Exception e) { + LOG.error("failed to create audit filters from: " + jsonStr, e); + return null; + } + } + + + public static String toString(List arr) { + String ret = ""; + + if(arr != null && !arr.isEmpty()) { + ret = arr.get(0); + for(int i = 1; i < arr.size(); i++) { + ret += (", " + arr.get(i)); + } + } + + return ret; + } + + public static boolean isEmpty(String str) { + return str == null || str.trim().isEmpty(); + } + + public static Date getUTCDateForLocalDate(Date date) { + Calendar local = Calendar.getInstance(); + int offset = local.getTimeZone().getOffset(local.getTimeInMillis()); + + GregorianCalendar utc = new GregorianCalendar(gmtTimeZone); + + utc.setTimeInMillis(date.getTime()); + utc.add(Calendar.MILLISECOND, -offset); + + return utc.getTime(); + } + + public static Map toStringObjectMap(Map map) { + Map ret = null; + + if (map != null) { + ret = new HashMap<>(map.size()); + + for (Map.Entry e : map.entrySet()) { + ret.put(e.getKey(), e.getValue()); + } + } + + return ret; + } + + public static Set toSet(String str) { + Set values = new HashSet(); + if (StringUtils.isNotBlank(str)) { + for (String item : str.split(",")) { + if (StringUtils.isNotBlank(item)) { + values.add(StringUtils.trim(item)); + } + } + } + return values; + } + + public static List toList(String str) { + List values; + if (StringUtils.isNotBlank(str)) { + values = new ArrayList<>(); + for (String item : str.split(",")) { + if (StringUtils.isNotBlank(item)) { + values.add(StringUtils.trim(item)); + } + } + } else { + values = Collections.emptyList(); + } + return values; + } + + public static List getURLs(String configURLs) { + List configuredURLs = new ArrayList<>(); + if(configURLs!=null) { + String[] urls = configURLs.split(","); + for (String strUrl : urls) { + if (StringUtils.isNotEmpty(StringUtils.trimToEmpty(strUrl))) { + if (strUrl.endsWith("/")) { + strUrl = strUrl.substring(0, strUrl.length() - 1); + } + configuredURLs.add(strUrl); + } + } + } + return configuredURLs; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/authz/admin/client/AtlasAuthAdminClient.java b/auth-agents-common/src/main/java/org/apache/atlas/authz/admin/client/AtlasAuthAdminClient.java new file mode 100644 index 00000000000..b1da5963e7a --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/authz/admin/client/AtlasAuthAdminClient.java @@ -0,0 +1,16 @@ +package org.apache.atlas.authz.admin.client; + +import org.apache.atlas.authorization.config.RangerPluginConfig; +import org.apache.atlas.plugin.util.RangerRoles; +import org.apache.atlas.plugin.util.RangerUserStore; +import org.apache.atlas.plugin.util.ServicePolicies; + +public interface AtlasAuthAdminClient { + void init(RangerPluginConfig config); + + ServicePolicies getServicePoliciesIfUpdated(long lastUpdatedTimeInMillis, boolean usePolicyDelta) throws Exception; + + RangerRoles getRolesIfUpdated(long lastUpdatedTimeInMillis) throws Exception; + + RangerUserStore getUserStoreIfUpdated(long lastUpdateTimeInMillis) throws Exception; +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/authz/admin/client/AtlasAuthRESTClient.java b/auth-agents-common/src/main/java/org/apache/atlas/authz/admin/client/AtlasAuthRESTClient.java new file mode 100644 index 00000000000..7c376165354 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/authz/admin/client/AtlasAuthRESTClient.java @@ -0,0 +1,143 @@ +package org.apache.atlas.authz.admin.client; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.apache.atlas.authorization.config.RangerPluginConfig; +import org.apache.atlas.authorization.utils.RangerUtil; +import org.apache.atlas.plugin.util.RangerRoles; +import org.apache.atlas.plugin.util.RangerUserStore; +import org.apache.atlas.plugin.util.ServicePolicies; +import org.apache.atlas.type.AtlasType; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.client.utils.URIBuilder; + +import javax.servlet.http.HttpServletResponse; +import java.net.InetAddress; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.UnknownHostException; +import java.util.concurrent.TimeUnit; + +public class AtlasAuthRESTClient implements AtlasAuthAdminClient { + private static final Log LOG = LogFactory.getLog(AtlasAuthRESTClient.class); + private static final int MAX_PLUGIN_ID_LEN = 255; + private static final String SCHEME = "http"; + private String serviceName; + private String pluginId; + private OkHttpClient httpClient; + private String adminUrl; + + private static final String PARAM_LAST_UPDATED_TIME = "lastUpdatedTime"; + private static final String PARAM_PLUGIN_ID = "pluginId"; + private static final String PARAM_USE_POLICY_DELTA = "usePolicyDelta"; + + @Override + public void init(RangerPluginConfig config) { + this.serviceName = config.getServiceName(); + this.pluginId = getPluginId(serviceName, config.getAppId()); + adminUrl = getAdminUrl(config); + + initClient(config); + } + + public String getPluginId(String serviceName, String appId) { + String hostName = null; + + try { + hostName = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + LOG.error("ERROR: Unable to find hostname for the agent ", e); + hostName = "unknownHost"; + } + + String ret = hostName + "-" + serviceName; + + if(StringUtils.isNotEmpty(appId)) { + ret = appId + "@" + ret; + } + + if (ret.length() > MAX_PLUGIN_ID_LEN ) { + ret = ret.substring(0,MAX_PLUGIN_ID_LEN); + } + + return ret ; + } + + @Override + public ServicePolicies getServicePoliciesIfUpdated(long lastUpdatedTimeInMillis, boolean usePolicyDelta) throws Exception { + URI uri = buildURI("/download/policies/" + serviceName, lastUpdatedTimeInMillis, usePolicyDelta); + return sendRequestAndGetResponse(uri, ServicePolicies.class); + } + + @Override + public RangerRoles getRolesIfUpdated(long lastUpdatedTimeInMillis) throws Exception { + URI uri = buildURI("/download/roles/" + serviceName, lastUpdatedTimeInMillis, false); + return sendRequestAndGetResponse(uri, RangerRoles.class); + } + + @Override + public RangerUserStore getUserStoreIfUpdated(long lastUpdatedTimeInMillis) throws Exception { + URI uri = buildURI("/download/users/" + serviceName, lastUpdatedTimeInMillis, false); + return sendRequestAndGetResponse(uri, RangerUserStore.class); + } + + private void initClient(RangerPluginConfig config) { + this.httpClient = new OkHttpClient(); + + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + builder.readTimeout(config.getLong(config.getPropertyPrefix() + ".policy.rest.client.read.timeoutMs", 20000), TimeUnit.MILLISECONDS); + this.httpClient = builder.build(); + } + + private T sendRequestAndGetResponse(URI uri, Class responseClass) throws Exception { + Request request = new Request.Builder().url(uri.toURL()).build(); + + try (Response response = httpClient.newCall(request).execute()) { + if (response.code() == HttpServletResponse.SC_OK) { + String responseBody = response.body().string(); + if (StringUtils.isNotEmpty(responseBody)) { + return AtlasType.fromJson(responseBody, responseClass); + } else { + LOG.warn("AtlasAuthRESTClient.sendRequestAndGetResponse(): Empty response from Atlas Auth"); + } + } else { + if (response.code() == HttpServletResponse.SC_NO_CONTENT || response.code() == HttpServletResponse.SC_NOT_MODIFIED) { + LOG.info("AtlasAuthRESTClient.sendRequestAndGetResponse(): " + response.code()); + } else { + LOG.error("AtlasAuthRESTClient.sendRequestAndGetResponse(): HTTP error: " + response.code()); + } + } + } + + return null; + } + + private URI buildURI(String path, long lastUpdatedTimeInMillis, boolean usePolicyDelta) throws URISyntaxException { + return new URIBuilder() + .setScheme(SCHEME) + .setHost(adminUrl) + .setPath(path) + .setParameter(PARAM_LAST_UPDATED_TIME, String.valueOf(lastUpdatedTimeInMillis)) + .setParameter(PARAM_PLUGIN_ID, pluginId) + .setParameter(PARAM_USE_POLICY_DELTA, String.valueOf(usePolicyDelta)) + .build(); + } + + private String getAdminUrl(RangerPluginConfig config) { + String url = ""; + String tmpUrl = config.get(config.getPropertyPrefix() + ".authz.rest.url"); + + if (!RangerUtil.isEmpty(tmpUrl)) { + url = tmpUrl.trim(); + } + + if (url.endsWith("/")) { + url = url.substring(0, url.length() - 1); + } + + return url; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/audit/RangerDefaultAuditHandler.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/audit/RangerDefaultAuditHandler.java new file mode 100644 index 00000000000..2def5eb6e20 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/audit/RangerDefaultAuditHandler.java @@ -0,0 +1,310 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.audit; + +import org.apache.atlas.type.AtlasType; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.conf.Configuration; +import org.apache.atlas.audit.model.AuthzAuditEvent; +import org.apache.atlas.audit.provider.AuditHandler; +import org.apache.atlas.audit.provider.MiscUtil; +import org.apache.atlas.plugin.contextenricher.RangerTagForEval; +import org.apache.atlas.plugin.policyengine.*; +import org.apache.atlas.plugin.service.RangerBasePlugin; +import org.apache.atlas.plugin.util.RangerAccessRequestUtil; +import org.apache.atlas.plugin.util.RangerRESTUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + + +public class RangerDefaultAuditHandler implements RangerAccessResultProcessor { + private static final Logger LOG = LoggerFactory.getLogger(RangerDefaultAuditHandler.class); + + private static final String CONF_AUDIT_ID_STRICT_UUID = "xasecure.audit.auditid.strict.uuid"; + private static final boolean DEFAULT_AUDIT_ID_STRICT_UUID = false; + + + private final boolean auditIdStrictUUID; + protected final String moduleName = null; + private final RangerRESTUtils restUtils = new RangerRESTUtils(); + private long sequenceNumber = 0; + private String UUID = MiscUtil.generateUniqueId(); + private AtomicInteger counter = new AtomicInteger(0); + + + + public RangerDefaultAuditHandler() { + auditIdStrictUUID = DEFAULT_AUDIT_ID_STRICT_UUID; + } + + public RangerDefaultAuditHandler(Configuration config) { + auditIdStrictUUID = config.getBoolean(CONF_AUDIT_ID_STRICT_UUID, DEFAULT_AUDIT_ID_STRICT_UUID); + } + + @Override + public void processResult(RangerAccessResult result) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> AtlasDefaultAccessAuditHandler.processResult(" + result + ")"); + } + + AuthzAuditEvent event = getAuthzEvents(result); + + logAuthzAudit(event); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== AtlasDefaultAccessAuditHandler.processResult(" + result + ")"); + } + } + + @Override + public void processResults(Collection results) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> AtlasDefaultAccessAuditHandler.processResults(" + results + ")"); + } + + Collection events = getAuthzEvents(results); + + if (events != null) { + logAuthzAudits(events); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== AtlasDefaultAccessAuditHandler.processResults(" + results + ")"); + } + } + + public AuthzAuditEvent getAuthzEvents(RangerAccessResult result) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> AtlasDefaultAccessAuditHandler.getAuthzEvents(" + result + ")"); + } + + AuthzAuditEvent ret = null; + + RangerAccessRequest request = result != null ? result.getAccessRequest() : null; + + if(request != null && result != null && result.getIsAudited()) { + //RangerServiceDef serviceDef = result.getServiceDef(); + RangerAccessResource resource = request.getResource(); + String resourceType = resource == null ? null : resource.getLeafName(); + String resourcePath = resource == null ? null : resource.getAsString(); + + ret = createAuthzAuditEvent(); + + ret.setRepositoryName(result.getServiceName()); + ret.setRepositoryType(result.getServiceType()); + ret.setResourceType(resourceType); + ret.setResourcePath(resourcePath); + ret.setRequestData(request.getRequestData()); + ret.setEventTime(request.getAccessTime() != null ? request.getAccessTime() : new Date()); + ret.setUser(request.getUser()); + ret.setAction(request.getAccessType()); + ret.setAccessResult((short) (result.getIsAllowed() ? 1 : 0)); + ret.setPolicyId(result.getPolicyId()); + ret.setAccessType(request.getAction()); + ret.setClientIP(request.getClientIPAddress()); + ret.setClientType(request.getClientType()); + ret.setSessionId(request.getSessionId()); + ret.setAclEnforcer(moduleName); + Set tags = getTags(request); + if (tags != null) { + ret.setTags(tags); + } + ret.setAdditionalInfo(getAdditionalInfo(request)); + ret.setClusterName(request.getClusterName()); + ret.setZoneName(result.getZoneName()); + ret.setAgentHostname(restUtils.getAgentHostname()); + ret.setPolicyVersion(result.getPolicyVersion()); + + populateDefaults(ret); + + result.setAuditLogId(ret.getEventId()); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== AtlasDefaultAccessAuditHandler.getAuthzEvents(" + result + "): " + ret); + } + + return ret; + } + + public Collection getAuthzEvents(Collection results) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> AtlasDefaultAccessAuditHandler.getAuthzEvents(" + results + ")"); + } + + List ret = null; + + if(results != null) { + // TODO: optimize the number of audit logs created + for(RangerAccessResult result : results) { + AuthzAuditEvent event = getAuthzEvents(result); + + if(event == null) { + continue; + } + + if(ret == null) { + ret = new ArrayList<>(); + } + + ret.add(event); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== AtlasDefaultAccessAuditHandler.getAuthzEvents(" + results + "): " + ret); + } + + return ret; + } + + public void logAuthzAudit(AuthzAuditEvent auditEvent) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> AtlasDefaultAccessAuditHandler.logAuthzAudit(" + auditEvent + ")"); + } + + if(auditEvent != null) { + populateDefaults(auditEvent); + + AuditHandler auditProvider = RangerBasePlugin.getAuditProvider(auditEvent.getRepositoryName()); + if (auditProvider == null || !auditProvider.log(auditEvent)) { + MiscUtil.logErrorMessageByInterval(LOG, "fail to log audit event " + auditEvent); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== AtlasDefaultAccessAuditHandler.logAuthzAudit(" + auditEvent + ")"); + } + } + + private void populateDefaults(AuthzAuditEvent auditEvent) { + if( auditEvent.getAclEnforcer() == null || auditEvent.getAclEnforcer().isEmpty()) { + auditEvent.setAclEnforcer("ranger-acl"); + } + + if (auditEvent.getAgentHostname() == null || auditEvent.getAgentHostname().isEmpty()) { + auditEvent.setAgentHostname(MiscUtil.getHostname()); + } + + if (auditEvent.getLogType() == null || auditEvent.getLogType().isEmpty()) { + auditEvent.setLogType("AtlasAuthZAudit"); + } + + if (auditEvent.getEventId() == null || auditEvent.getEventId().isEmpty()) { + auditEvent.setEventId(generateNextAuditEventId()); + } + + if (auditEvent.getAgentId() == null) { + auditEvent.setAgentId(MiscUtil.getApplicationType()); + } + + auditEvent.setSeqNum(sequenceNumber++); + } + + public void logAuthzAudits(Collection auditEvents) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> AtlasDefaultAccessAuditHandler.logAuthzAudits(" + auditEvents + ")"); + } + + if(auditEvents != null) { + for(AuthzAuditEvent auditEvent : auditEvents) { + logAuthzAudit(auditEvent); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== AtlasDefaultAccessAuditHandler.logAuthzAudits(" + auditEvents + ")"); + } + } + + public AuthzAuditEvent createAuthzAuditEvent() { + return new AuthzAuditEvent(); + } + + protected final Set getTags(RangerAccessRequest request) { + Set ret = null; + Set tags = RangerAccessRequestUtil.getRequestTagsFromContext(request.getContext()); + + if (CollectionUtils.isNotEmpty(tags)) { + ret = new HashSet<>(); + + for (RangerTagForEval tag : tags) { + ret.add(writeObjectAsString(tag)); + } + } + + return ret; + } + + public String getAdditionalInfo(RangerAccessRequest request) { + if (StringUtils.isBlank(request.getRemoteIPAddress()) && CollectionUtils.isEmpty(request.getForwardedAddresses())) { + return null; + } + StringBuilder sb = new StringBuilder(); + sb.append("{\"remote-ip-address\":").append(request.getRemoteIPAddress()) + .append(", \"forwarded-ip-addresses\":[").append(StringUtils.join(request.getForwardedAddresses(), ", ")).append("]"); + + return sb.toString(); + } + + private String generateNextAuditEventId() { + final String ret; + + if (auditIdStrictUUID) { + ret = MiscUtil.generateGuid(); + } else { + int nextId = counter.getAndIncrement(); + + if (nextId == Integer.MAX_VALUE) { + // reset UUID and counter + UUID = MiscUtil.generateUniqueId(); + counter = new AtomicInteger(0); + } + + ret = UUID + "-" + Integer.toString(nextId); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("generateNextAuditEventId(): " + ret); + } + + return ret; + } + + private String writeObjectAsString(Serializable obj) { + String jsonStr = StringUtils.EMPTY; + try { + jsonStr = AtlasType.toJson(obj); + } catch (Exception e) { + LOG.error("Cannot create JSON string for object:[" + obj + "]", e); + } + return jsonStr; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/classloader/RangerPluginClassLoader.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/classloader/RangerPluginClassLoader.java new file mode 100644 index 00000000000..0fcd1003d3e --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/classloader/RangerPluginClassLoader.java @@ -0,0 +1,347 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.classloader; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineFactory; +import javax.script.ScriptEngineManager; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Enumeration; +import java.util.List; + +public class RangerPluginClassLoader extends URLClassLoader { + private static final Logger LOG = LoggerFactory.getLogger(RangerPluginClassLoader.class); + + ThreadLocal preActivateClassLoader = new ThreadLocal<>(); + + private static volatile RangerPluginClassLoader me = null; + private static MyClassLoader componentClassLoader = null; + + public RangerPluginClassLoader(String pluginType, Class pluginClass ) throws Exception { + super(RangerPluginClassLoaderUtil.getInstance().getPluginFilesForServiceTypeAndPluginclass(pluginType, pluginClass), null); + componentClassLoader = new MyClassLoader(Thread.currentThread().getContextClassLoader()); + } + + public static RangerPluginClassLoader getInstance(final String pluginType, final Class pluginClass ) throws Exception { + RangerPluginClassLoader ret = me; + if ( ret == null) { + synchronized(RangerPluginClassLoader.class) { + ret = me; + if (ret == null && pluginClass != null) { + me = ret = new RangerPluginClassLoader(pluginType,pluginClass); + } + } + } + return ret; + } + + @Override + public Class findClass(String name) throws ClassNotFoundException { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerPluginClassLoader.findClass(" + name + ")"); + } + + Class ret = null; + + try { + // first we try to find a class inside the child classloader + if(LOG.isDebugEnabled()) { + LOG.debug("RangerPluginClassLoader.findClass(" + name + "): calling childClassLoader().findClass() "); + } + + ret = super.findClass(name); + } catch( Throwable e ) { + // Use the Component ClassLoader findclass to load when childClassLoader fails to find + if(LOG.isDebugEnabled()) { + LOG.debug("RangerPluginClassLoader.findClass(" + name + "): calling componentClassLoader.findClass()"); + } + + MyClassLoader savedClassLoader = getComponentClassLoader(); + if (savedClassLoader != null) { + ret = savedClassLoader.findClass(name); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPluginClassLoader.findClass(" + name + "): " + ret); + } + return ret; + } + + @Override + public synchronized Class loadClass(String name) throws ClassNotFoundException { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPluginClassLoader.loadClass(" + name + ")" ); + } + + Class ret = null; + + try { + // first we try to load a class inside the child classloader + if (LOG.isDebugEnabled()) { + LOG.debug("RangerPluginClassLoader.loadClass(" + name + "): calling childClassLoader.findClass()"); + } + ret = super.loadClass(name); + } catch(Throwable e) { + // Use the Component ClassLoader loadClass to load when childClassLoader fails to find + if (LOG.isDebugEnabled()) { + LOG.debug("RangerPluginClassLoader.loadClass(" + name + "): calling componentClassLoader.loadClass()"); + } + + MyClassLoader savedClassLoader = getComponentClassLoader(); + + if(savedClassLoader != null) { + ret = savedClassLoader.loadClass(name); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPluginClassLoader.loadClass(" + name + "): " + ret); + } + + return ret; + } + + @Override + public URL findResource(String name) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerPluginClassLoader.findResource(" + name + ") "); + } + + URL ret = super.findResource(name); + + if (ret == null) { + if(LOG.isDebugEnabled()) { + LOG.debug("RangerPluginClassLoader.findResource(" + name + "): calling componentClassLoader.getResources()"); + } + + MyClassLoader savedClassLoader = getComponentClassLoader(); + if (savedClassLoader != null) { + ret = savedClassLoader.getResource(name); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPluginClassLoader.findResource(" + name + "): " + ret); + } + + return ret; + } + + @Override + public Enumeration findResources(String name) throws IOException { + Enumeration ret = null; + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerPluginClassLoader.findResources(" + name + ") "); + } + + ret = new MergeEnumeration(findResourcesUsingChildClassLoader(name),findResourcesUsingComponentClassLoader(name)); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPluginClassLoader.findResources(" + name + ") "); + } + + return ret; + } + + public Enumeration findResourcesUsingChildClassLoader(String name) { + + Enumeration ret = null; + + try { + if(LOG.isDebugEnabled()) { + LOG.debug("RangerPluginClassLoader.findResourcesUsingChildClassLoader(" + name + "): calling childClassLoader.findResources()"); + } + + ret = super.findResources(name); + + } catch ( Throwable t) { + //Ignore any exceptions. Null / Empty return is handle in following statements + if(LOG.isDebugEnabled()) { + LOG.debug("RangerPluginClassLoader.findResourcesUsingChildClassLoader(" + name + "): class not found in child. Falling back to componentClassLoader", t); + } + } + return ret; + } + + public Enumeration findResourcesUsingComponentClassLoader(String name) { + + Enumeration ret = null; + + try { + + if(LOG.isDebugEnabled()) { + LOG.debug("RangerPluginClassLoader.findResourcesUsingComponentClassLoader(" + name + "): calling componentClassLoader.getResources()"); + } + + MyClassLoader savedClassLoader = getComponentClassLoader(); + + if (savedClassLoader != null) { + ret = savedClassLoader.getResources(name); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPluginClassLoader.findResourcesUsingComponentClassLoader(" + name + "): " + ret); + } + } catch( Throwable t) { + if(LOG.isDebugEnabled()) { + LOG.debug("RangerPluginClassLoader.findResourcesUsingComponentClassLoader(" + name + "): class not found in componentClassLoader.", t); + } + } + + return ret; + } + + public void activate() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerPluginClassLoader.activate()"); + } + + //componentClassLoader.set(new MyClassLoader(Thread.currentThread().getContextClassLoader())); + + preActivateClassLoader.set(Thread.currentThread().getContextClassLoader()); + + Thread.currentThread().setContextClassLoader(this); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPluginClassLoader.activate()"); + } + } + + public void deactivate() { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerPluginClassLoader.deactivate()"); + } + + ClassLoader classLoader = preActivateClassLoader.get(); + + if (classLoader != null) { + preActivateClassLoader.remove(); + } else { + MyClassLoader savedClassLoader = getComponentClassLoader(); + if (savedClassLoader != null && savedClassLoader.getParent() != null) { + classLoader = savedClassLoader.getParent(); + } + } + + if (classLoader != null) { + Thread.currentThread().setContextClassLoader(classLoader); + } else { + LOG.warn("RangerPluginClassLoader.deactivate() was not successful. Couldn't not get the saved classLoader..."); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPluginClassLoader.deactivate()"); + } + } + + private MyClassLoader getComponentClassLoader() { + return componentClassLoader; + //return componentClassLoader.get(); + } + + static class MyClassLoader extends ClassLoader { + public MyClassLoader(ClassLoader realClassLoader) { + super(realClassLoader); + } + + @Override + public Class findClass(String name) throws ClassNotFoundException { //NOPMD + return super.findClass(name); + } + } + + static class MergeEnumeration implements Enumeration { //NOPMD + + Enumeration e1 = null; + Enumeration e2 = null; + + public MergeEnumeration(Enumeration e1, Enumeration e2 ) { + this.e1 = e1; + this.e2 = e2; + } + + @Override + public boolean hasMoreElements() { + return ( (e1 != null && e1.hasMoreElements() ) || ( e2 != null && e2.hasMoreElements()) ); + } + + @Override + public URL nextElement() { + URL ret = null; + if (e1 != null && e1.hasMoreElements()) + ret = e1.nextElement(); + else if ( e2 != null && e2.hasMoreElements() ) { + ret = e2.nextElement(); + } + return ret; + } + } + + public ScriptEngine getScriptEngine(String engineName) { + + final ScriptEngine ret; + + ClassLoader classLoader = preActivateClassLoader.get(); + + if (classLoader == null) { + MyClassLoader savedClassLoader = getComponentClassLoader(); + if (savedClassLoader != null && savedClassLoader.getParent() != null) { + classLoader = savedClassLoader.getParent(); + } + } + + ScriptEngineManager manager = classLoader != null ? new ScriptEngineManager(classLoader) : new ScriptEngineManager(); + + if (LOG.isDebugEnabled()) { + + List factories = manager.getEngineFactories(); + + if (factories == null || factories.size() == 0) { + LOG.debug("List of scriptEngineFactories is empty!!"); + + } else { + for (ScriptEngineFactory factory : factories) { + LOG.debug("engineName=" + factory.getEngineName() + ", language=" + factory.getLanguageName()); + + } + } + } + + ret = manager.getEngineByName(engineName); + + if (ret == null) { + LOG.error("scriptEngine for JavaScript is null!!"); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("scriptEngine for JavaScript:[" + ret + "]"); + } + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/classloader/RangerPluginClassLoaderUtil.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/classloader/RangerPluginClassLoaderUtil.java new file mode 100644 index 00000000000..9167ff9fe71 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/classloader/RangerPluginClassLoaderUtil.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.classloader; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.net.URI; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +public class RangerPluginClassLoaderUtil { + + private static final Logger LOG = LoggerFactory.getLogger(RangerPluginClassLoaderUtil.class); + + private static volatile RangerPluginClassLoaderUtil config = null; + private static String rangerPluginLibDir = "ranger-%-plugin-impl"; + + public static RangerPluginClassLoaderUtil getInstance() { + RangerPluginClassLoaderUtil result = config; + if (result == null) { + synchronized (RangerPluginClassLoaderUtil.class) { + result = config; + if (result == null) { + config = result = new RangerPluginClassLoaderUtil(); + } + } + } + return result; + } + + + public URL[] getPluginFilesForServiceTypeAndPluginclass( String serviceType, Class pluginClass) throws Exception { + + URL[] ret = null; + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerPluginClassLoaderUtil.getPluginFilesForServiceTypeAndPluginclass(" + serviceType + ")" + " Pluging Class :" + pluginClass.getName()); + } + + String[] libDirs = new String[] { getPluginImplLibPath(serviceType, pluginClass) }; + + ret = getPluginFiles(libDirs); + + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPluginClassLoaderUtil.getPluginFilesForServiceTypeAndPluginclass(" + serviceType + ")" + " Pluging Class :" + pluginClass.getName()); + } + + return ret; + + } + + private URL[] getPluginFiles(String[] libDirs) throws Exception { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerPluginClassLoaderUtil.getPluginFiles()"); + } + + List ret = new ArrayList(); + for ( String libDir : libDirs) { + getFilesInDirectory(libDir,ret); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPluginClassLoaderUtil.getPluginFilesForServiceType(): " + ret.size() + " files"); + } + + return ret.toArray(new URL[] { }); + } + + private void getFilesInDirectory(String dirPath, List files) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerPluginClassLoaderUtil.getPluginFiles()"); + } + + if ( dirPath != null) { + try { + + File[] dirFiles = new File(dirPath).listFiles(); + + if(dirFiles != null) { + for(File dirFile : dirFiles) { + try { + if (!dirFile.canRead()) { + LOG.error("getFilesInDirectory('" + dirPath + "'): " + dirFile.getAbsolutePath() + " is not readable!"); + } + + URL jarPath = dirFile.toURI().toURL(); + + LOG.info("getFilesInDirectory('" + dirPath + "'): adding " + dirFile.getAbsolutePath()); + + files.add(jarPath); + } catch(Exception excp) { + LOG.warn("getFilesInDirectory('" + dirPath + "'): failed to get URI for file " + dirFile.getAbsolutePath(), excp); + } + } + } + } catch(Exception excp) { + LOG.warn("getFilesInDirectory('" + dirPath + "'): error", excp); + } + } else { + LOG.warn("getFilesInDirectory('" + dirPath + "'): could not find directory in path " + dirPath); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPluginClassLoaderUtil.getFilesInDirectory(" + dirPath + ")"); + } + } + + private String getPluginImplLibPath(String serviceType, Class pluginClass) throws Exception { + + String ret = null; + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerPluginClassLoaderUtil.getPluginImplLibPath for Class (" + pluginClass.getName() + ")"); + } + + URI uri = pluginClass.getProtectionDomain().getCodeSource().getLocation().toURI(); + + Path path = Paths.get(URI.create(uri.toString())); + + ret = path.getParent().toString() + File.separatorChar + rangerPluginLibDir.replaceAll("%", serviceType); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPluginClassLoaderUtil.getPluginImplLibPath for Class (" + pluginClass.getName() + " PATH :" + ret + ")"); + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/AtlanExcludeResourceByType.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/AtlanExcludeResourceByType.java new file mode 100644 index 00000000000..9de969ad138 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/AtlanExcludeResourceByType.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.*; + + +public class AtlanExcludeResourceByType extends RangerAbstractConditionEvaluator { + private static final Log LOG = LogFactory.getLog(AtlanExcludeResourceByType.class); + protected Set excludeEntityTypes = new HashSet<>(); + public static final String RESOURCE_ENTITY_TYPE = "entity-type"; + public static final String RESOURCE_END_ONE_ENTITY_TYPE = "end-one-entity-type"; + public static final String RESOURCE_END_TWO_ENTITY_TYPE = "end-two-entity-type"; + + + @Override + public void init() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> AtlanExcludeResourceByType.init(" + condition + ")"); + } + + super.init(); + + if (condition != null ) { + for (String value : condition.getValues()) { + excludeEntityTypes.add(value.trim()); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== AtlanExcludeResourceByType.init(" + condition + ")"); + } + } + + @Override + public boolean isMatched(RangerAccessRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> AtlanExcludeResourceByType.isMatched(" + condition + ")"); + } + + boolean ret = true; + RangerAccessRequest readOnlyRequest = request.getReadOnlyCopy(); + + Set entityTypes = new HashSet<>(); + Object entityType = readOnlyRequest.getResource().getValue(RESOURCE_ENTITY_TYPE); + Object endOneEntityType = readOnlyRequest.getResource().getValue(RESOURCE_END_ONE_ENTITY_TYPE); + Object endTwoEntityType = readOnlyRequest.getResource().getValue(RESOURCE_END_TWO_ENTITY_TYPE); + + if (entityType != null) { + entityTypes.addAll(convertToSet(entityType)); + } else if (endOneEntityType != null) { + entityTypes.addAll(convertToSet(endOneEntityType)); + } else if (endTwoEntityType != null) { + entityTypes.addAll(convertToSet(endTwoEntityType)); + } + + if (!entityTypes.isEmpty()) { + ret = excludeEntityTypes.stream().noneMatch(entityTypes::contains); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== AtlanExcludeResourceByType.isMatched(" + condition + "): " + ret); + } + return ret; + } + + private Set convertToSet(Object obj) { + if (obj instanceof Object[]) { + return new HashSet<>(Arrays.asList((Object[]) obj)); + } else if (obj instanceof Collection) { + return new HashSet<>((Collection) obj); + } + return Collections.emptySet(); + } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/AtlanHasAnyRole.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/AtlanHasAnyRole.java new file mode 100644 index 00000000000..79413ecb100 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/AtlanHasAnyRole.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +public class AtlanHasAnyRole extends RangerAbstractConditionEvaluator { + private static final Log LOG = LogFactory.getLog(AtlanHasAnyRole.class); + + protected Set excludedRoles = new HashSet<>(); + + @Override + public void init() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> AtlanHasAnyRole.init(" + condition + ")"); + } + + super.init(); + + if (condition != null ) { + for (String value : condition.getValues()) { + excludedRoles.add(value.trim()); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== AtlanHasAnyRole.init(" + condition + ")"); + } + } + + @Override + public boolean isMatched(RangerAccessRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> AtlanHasAnyRole.isMatched(" + condition + ")"); + } + + boolean ret = false; + + RangerAccessRequest readOnlyRequest = request.getReadOnlyCopy(); + Set currentRoles = ((Set) readOnlyRequest.getContext().get("token:ROLES")); + + if (CollectionUtils.isNotEmpty(currentRoles)) { + ret = !excludedRoles.stream().anyMatch(excludedRole -> currentRoles.stream().anyMatch(x -> Objects.equals(x, excludedRole))); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== AtlanHasAnyRole.isMatched(" + condition + "): " + ret); + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAbstractConditionEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAbstractConditionEvaluator.java new file mode 100644 index 00000000000..8fa0aea9c53 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAbstractConditionEvaluator.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemCondition; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerPolicyConditionDef; + +public abstract class RangerAbstractConditionEvaluator implements RangerConditionEvaluator { + protected RangerServiceDef serviceDef; + protected RangerPolicyConditionDef conditionDef; + protected RangerPolicyItemCondition condition; + + @Override + public void setServiceDef(RangerServiceDef serviceDef) { + this.serviceDef = serviceDef; + } + + @Override + public void setConditionDef(RangerPolicyConditionDef conditionDef) { + this.conditionDef = conditionDef; + } + + @Override + public void setPolicyItemCondition(RangerPolicyItemCondition condition) { + this.condition = condition; + } + + @Override + public void init() { + } + + public RangerPolicyItemCondition getPolicyItemCondition() { return condition; } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAccessedFromClusterCondition.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAccessedFromClusterCondition.java new file mode 100644 index 00000000000..a1d29d03cdf --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAccessedFromClusterCondition.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; + + +public class RangerAccessedFromClusterCondition extends RangerAbstractConditionEvaluator { + private static final Log LOG = LogFactory.getLog(RangerAccessedFromClusterCondition.class); + + private boolean isAlwaysTrue = false; + + @Override + public void init() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerAccessedFromClusterCondition.init(" + condition + ")"); + } + + super.init(); + + isAlwaysTrue = CollectionUtils.isEmpty(condition.getValues()); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerAccessedFromClusterCondition.init(" + condition + ")"); + } + } + + @Override + public boolean isMatched(RangerAccessRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerAccessedFromClusterCondition.isMatched(" + condition + ")"); + } + + final boolean ret; + + if (isAlwaysTrue || request.getClusterName() == null) { + ret = isAlwaysTrue; + } else { + ret = condition.getValues().contains(request.getClusterName()); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerAccessedFromClusterCondition.isMatched(" + condition + "): " + ret); + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAccessedFromClusterTypeCondition.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAccessedFromClusterTypeCondition.java new file mode 100644 index 00000000000..cd5242ac516 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAccessedFromClusterTypeCondition.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; + +public class RangerAccessedFromClusterTypeCondition extends RangerAbstractConditionEvaluator{ + private static final Log LOG = LogFactory.getLog(RangerAccessedFromClusterTypeCondition.class); + + private boolean isAlwaysTrue = false; + + @Override + public void init() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerAccessedFromClusterTypeCondition.init(" + condition + ")"); + } + + super.init(); + + isAlwaysTrue = CollectionUtils.isEmpty(condition.getValues()); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerAccessedFromClusterTypeCondition.init(" + condition + ")"); + } + } + @Override + public boolean isMatched(RangerAccessRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerAccessedFromClusterTypeCondition.isMatched(" + condition + ")"); + } + + final boolean ret; + + if (isAlwaysTrue || request.getClusterType() == null) { + ret = isAlwaysTrue; + } else { + ret = condition.getValues().contains(request.getClusterType()); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerAccessedFromClusterTypeCondition.isMatched(" + condition + "): " + ret); + } + + return ret; + } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAccessedNotFromClusterCondition.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAccessedNotFromClusterCondition.java new file mode 100644 index 00000000000..fea4eddfdca --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAccessedNotFromClusterCondition.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; + + +public class RangerAccessedNotFromClusterCondition extends RangerAbstractConditionEvaluator { + private static final Log LOG = LogFactory.getLog(RangerAccessedNotFromClusterCondition.class); + + private boolean isAlwaysTrue = false; + + @Override + public void init() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerAccessedNotFromClusterCondition.init(" + condition + ")"); + } + + super.init(); + + isAlwaysTrue = CollectionUtils.isEmpty(condition.getValues()); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerAccessedNotFromClusterCondition.init(" + condition + ")"); + } + } + + @Override + public boolean isMatched(RangerAccessRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerAccessedNotFromClusterCondition.isMatched(" + condition + ")"); + } + + final boolean ret; + + if (isAlwaysTrue || request.getClusterName() == null) { + ret = true; + } else { + ret = !condition.getValues().contains(request.getClusterName()); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerAccessedNotFromClusterCondition.isMatched(" + condition + "): " + ret); + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAccessedNotFromClusterTypeCondition.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAccessedNotFromClusterTypeCondition.java new file mode 100644 index 00000000000..0c3ff007423 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAccessedNotFromClusterTypeCondition.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; + +public class RangerAccessedNotFromClusterTypeCondition extends RangerAbstractConditionEvaluator{ + private static final Log LOG = LogFactory.getLog(RangerAccessedNotFromClusterTypeCondition.class); + + private boolean isAlwaysTrue = false; + + @Override + public void init() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerAccessedNotFromClusterTypeCondition.init(" + condition + ")"); + } + + super.init(); + + isAlwaysTrue = CollectionUtils.isEmpty(condition.getValues()); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerAccessedNotFromClusterTypeCondition.init(" + condition + ")"); + } + } + + @Override + public boolean isMatched(RangerAccessRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerAccessedNotFromClusterTypeCondition.isMatched(" + condition + ")"); + } + + final boolean ret; + + if (isAlwaysTrue || request.getClusterType() == null) { + ret = true; + } else { + ret = !condition.getValues().contains(request.getClusterType()); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerAccessedNotFromClusterTypeCondition.isMatched(" + condition + "): " + ret); + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAnyOfExpectedTagsPresentConditionEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAnyOfExpectedTagsPresentConditionEvaluator.java new file mode 100644 index 00000000000..6e5b8311a0c --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerAnyOfExpectedTagsPresentConditionEvaluator.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +// Policy Condition to check if resource Tags does contain any of the policy Condition Tags + +public class RangerAnyOfExpectedTagsPresentConditionEvaluator extends RangerAbstractConditionEvaluator { + + private static final Log LOG = LogFactory.getLog(RangerAnyOfExpectedTagsPresentConditionEvaluator.class); + + private final Set policyConditionTags = new HashSet<>(); + + @Override + public void init() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerAnyOfExpectedTagsPresentConditionEvaluator.init(" + condition + ")"); + } + + super.init(); + + if (condition != null ) { + for (String value : condition.getValues()) { + policyConditionTags.add(value.trim()); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerAnyOfExpectedTagsPresentConditionEvaluator.init(" + condition + "): Tags[" + policyConditionTags + "]"); + } + } + + @Override + public boolean isMatched(RangerAccessRequest request) { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerAnyOfExpectedTagsPresentConditionEvaluator.isMatched(" + request + ")"); + } + + boolean matched = false; + + RangerAccessRequest readOnlyRequest = request.getReadOnlyCopy(); + RangerScriptExecutionContext context = new RangerScriptExecutionContext(readOnlyRequest); + Set resourceTags = context.getAllTagTypes(); + + if (resourceTags != null) { + // check if resource Tags does contain any of the policy Condition Tags + matched = (!Collections.disjoint(resourceTags, policyConditionTags)); + } + + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerAnyOfExpectedTagsPresentConditionEvaluator.isMatched(" + request+ "): " + matched); + } + + return matched; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerConditionEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerConditionEvaluator.java new file mode 100644 index 00000000000..6160bd17b61 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerConditionEvaluator.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemCondition; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerPolicyConditionDef; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; + +public interface RangerConditionEvaluator { + void setConditionDef(RangerPolicyConditionDef conditionDef); + + void setPolicyItemCondition(RangerPolicyItemCondition condition); + + void setServiceDef(RangerServiceDef serviceDef); + + void init(); + + boolean isMatched(RangerAccessRequest request); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerContextAttributeValueInCondition.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerContextAttributeValueInCondition.java new file mode 100644 index 00000000000..9d06f0ca802 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerContextAttributeValueInCondition.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; + +import java.util.Map; + +public class RangerContextAttributeValueInCondition extends RangerAbstractConditionEvaluator { + private static final Log LOG = LogFactory.getLog(RangerContextAttributeValueInCondition.class); + + protected String attributeName; + + @Override + public void init() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerContextAttributeValueInCondition.init(" + condition + ")"); + } + + super.init(); + + Map evalOptions = conditionDef. getEvaluatorOptions(); + + if (MapUtils.isNotEmpty(evalOptions)) { + attributeName = evalOptions.get("attributeName"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerContextAttributeValueInCondition.init(" + condition + ")"); + } + } + + @Override + public boolean isMatched(RangerAccessRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerContextAttributeValueInCondition.isMatched(" + condition + ")"); + } + + boolean ret = true; + + if(attributeName != null && condition != null && CollectionUtils.isNotEmpty(condition.getValues())) { + Object val = request.getContext().get(attributeName); + + if(val != null) { + ret = condition.getValues().contains(val); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerContextAttributeValueInCondition.isMatched(" + condition + "): " + ret); + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerContextAttributeValueNotInCondition.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerContextAttributeValueNotInCondition.java new file mode 100644 index 00000000000..3adfd97fd25 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerContextAttributeValueNotInCondition.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; + +import java.util.Map; + +public class RangerContextAttributeValueNotInCondition extends RangerAbstractConditionEvaluator { + private static final Log LOG = LogFactory.getLog(RangerContextAttributeValueNotInCondition.class); + + protected String attributeName; + + @Override + public void init() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerContextAttributeValueNotInCondition.init(" + condition + ")"); + } + + super.init(); + + Map evalOptions = conditionDef. getEvaluatorOptions(); + + if (MapUtils.isNotEmpty(evalOptions)) { + attributeName = evalOptions.get("attributeName"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerContextAttributeValueNotInCondition.init(" + condition + ")"); + } + } + + @Override + public boolean isMatched(RangerAccessRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerContextAttributeValueNotInCondition.isMatched(" + condition + ")"); + } + + boolean ret = true; + + if(attributeName != null && condition != null && CollectionUtils.isNotEmpty(condition.getValues())) { + Object val = request.getContext().get(attributeName); + + if(val != null) { + ret = !condition.getValues().contains(val); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerContextAttributeValueNotInCondition.isMatched(" + condition + "): " + ret); + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerIpMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerIpMatcher.java new file mode 100644 index 00000000000..ed87b8a34d1 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerIpMatcher.java @@ -0,0 +1,216 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Credits: Large parts of this file have been lifted as is from org.apache.atlas.pdp.knox.URLBasedAuthDB. Credits for those are due to Dilli Arumugam. + * @author alal + */ +public class RangerIpMatcher extends RangerAbstractConditionEvaluator { + private static final Log LOG = LogFactory.getLog(RangerIpMatcher.class); + private List _exactIps = new ArrayList<>(); + private List _wildCardIps = new ArrayList<>(); + private boolean _allowAny; + + @Override + public void init() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerIpMatcher.init(" + condition + ")"); + } + + super.init(); + + // NOTE: this evaluator does not use conditionDef! + if (condition == null) { + LOG.debug("init: null policy condition! Will match always!"); + _allowAny = true; + } else if (CollectionUtils.isEmpty(condition.getValues())) { + LOG.debug("init: empty conditions collection on policy condition! Will match always!"); + _allowAny = true; + } else if (condition.getValues().contains("*")) { + _allowAny = true; + LOG.debug("init: wildcard value found. Will match always."); + } else { + for (String ip : condition.getValues()) { + String digestedIp = digestPolicyIp(ip); + if (digestedIp.isEmpty()) { + LOG.debug("init: digested ip was empty! Will match always"); + _allowAny = true; + } else if (digestedIp.equals(ip)) { + _exactIps.add(ip); + } else { + _wildCardIps.add(digestedIp); + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerIpMatcher.init(" + condition + "): exact-ips[" + _exactIps + "], wildcard-ips[" + _wildCardIps + "]"); + } + } + + @Override + public boolean isMatched(final RangerAccessRequest request) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerIpMatcher.isMatched(" + request + ")"); + } + + boolean ipMatched = true; + if (_allowAny) { + LOG.debug("isMatched: allowAny flag is true. Matched!"); + } else { + String requestIp = extractIp(request); + if (requestIp == null) { + LOG.debug("isMatched: couldn't get ip address from request. Ok. Implicitly matched!"); + } else { + ipMatched = isWildcardMatched(_wildCardIps, requestIp) || isExactlyMatched(_exactIps, requestIp); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerIpMatcher.isMatched(" + request+ "): " + ipMatched); + } + + return ipMatched; + } + + /** + * Pre-digests the policy ip address to drop any trailing wildcard specifiers such that a simple beginsWith match can be done to check for match during authorization calls + * @param ip + * @return + */ + static final Pattern allWildcards = Pattern.compile("^((\\*(\\.\\*)*)|(\\*(:\\*)*))$"); // "*", "*.*", "*.*.*", "*:*", "*:*:*", etc. + static final Pattern trailingWildcardsIp4 = Pattern.compile("(\\.\\*)+$"); // "blah.*", "blah.*.*", etc. + static final Pattern trailingWildcardsIp6 = Pattern.compile("(:\\*)+$"); // "blah:*", "blah:*:*", etc. + + String digestPolicyIp(final String policyIp) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerIpMatcher.digestPolicyIp(" + policyIp + ")"); + } + + String result; + Matcher matcher = allWildcards.matcher(policyIp); + if (matcher.matches()) { + if (LOG.isDebugEnabled()) { + LOG.debug("digestPolicyIp: policyIP[" + policyIp +"] all wildcards."); + } + result = ""; + } else if (policyIp.contains(".")) { + matcher = trailingWildcardsIp4.matcher(policyIp); + result = matcher.replaceFirst("."); + } else { + matcher = trailingWildcardsIp6.matcher(policyIp); + // also lower cases the ipv6 items + result = matcher.replaceFirst(":").toLowerCase(); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerIpMatcher.digestPolicyIp(" + policyIp + "): " + policyIp); + } + return result; + } + + boolean isWildcardMatched(final List ips, final String requestIp) { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerIpMatcher.isWildcardMatched(" + ips+ ", " + requestIp + ")"); + } + + boolean matchFound = false; + Iterator iterator = ips.iterator(); + while (iterator.hasNext() && !matchFound) { + String ip = iterator.next(); + if (requestIp.contains(".") && requestIp.startsWith(ip)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Wildcard Policy IP[" + ip + "] matches request IPv4[" + requestIp + "]."); + } + matchFound = true; + } else if (requestIp.toLowerCase().startsWith(ip)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Wildcard Policy IP[" + ip + "] matches request IPv6[" + requestIp + "]."); + } + matchFound = true; + } else { + LOG.debug("Wildcard policy IP[" + ip + "] did not match request IP[" + requestIp + "]."); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerIpMatcher.isWildcardMatched(" + ips+ ", " + requestIp + "): " + matchFound); + } + return matchFound; + } + + boolean isExactlyMatched(final List ips, final String requestIp) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerIpMatcher.isExactlyMatched(" + ips+ ", " + requestIp + ")"); + } + + boolean matchFound = false; + if (requestIp.contains(".")) { + matchFound = ips.contains(requestIp); + } else { + matchFound = ips.contains(requestIp.toLowerCase()); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerIpMatcher.isExactlyMatched(" + ips+ ", " + requestIp + "): " + matchFound); + } + return matchFound; + } + + /** + * Extracts and returns the ip address from the request. Returns null if one can't be obtained out of the request. + * @param request + * @return + */ + String extractIp(final RangerAccessRequest request) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerIpMatcher.extractIp(" + request+ ")"); + } + + String ip = null; + if (request == null) { + LOG.debug("isMatched: Unexpected: null request object!"); + } else { + ip = request.getClientIPAddress(); + if (ip == null) { + LOG.debug("isMatched: Unexpected: Client ip in request object is null!"); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerIpMatcher.extractIp(" + request+ "): " + ip); + } + return ip; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerNoneOfExpectedTagsPresentConditionEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerNoneOfExpectedTagsPresentConditionEvaluator.java new file mode 100644 index 00000000000..8ab50d84a2e --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerNoneOfExpectedTagsPresentConditionEvaluator.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +//PolicyCondition to check if resource Tags does not contain any of the tags in the policy condition + +public class RangerNoneOfExpectedTagsPresentConditionEvaluator extends RangerAbstractConditionEvaluator { + + private static final Log LOG = LogFactory.getLog(RangerNoneOfExpectedTagsPresentConditionEvaluator.class); + + private final Set policyConditionTags = new HashSet<>(); + + @Override + public void init() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerNoneOfExpectedTagsPresentConditionEvaluator.init(" + condition + ")"); + } + + super.init(); + + if (condition != null ) { + for (String value : condition.getValues()) { + policyConditionTags.add(value.trim()); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerNoneOfExpectedTagsPresentConditionEvaluator.init(" + condition + "): Tags[" + policyConditionTags + "]"); + } + } + + @Override + public boolean isMatched(RangerAccessRequest request) { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerNoneOfExpectedTagsPresentConditionEvaluator.isMatched(" + request + ")"); + } + + boolean matched = true; + + RangerAccessRequest readOnlyRequest = request.getReadOnlyCopy(); + RangerScriptExecutionContext context = new RangerScriptExecutionContext(readOnlyRequest); + Set resourceTags = context.getAllTagTypes(); + + if (resourceTags != null) { + // check if resource Tags does not contain any tags in the policy condition + matched = (Collections.disjoint(resourceTags, policyConditionTags)); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerNoneOfExpectedTagsPresentConditionEvaluator.isMatched(" + request+ "): " + matched); + } + + return matched; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerScriptConditionEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerScriptConditionEvaluator.java new file mode 100644 index 00000000000..f1413733f71 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerScriptConditionEvaluator.java @@ -0,0 +1,232 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.classloader.RangerPluginClassLoader; +import org.apache.atlas.plugin.contextenricher.RangerTagForEval; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.atlas.plugin.util.RangerPerfTracer; + +import javax.script.Bindings; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineFactory; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_OPTION_ENABLE_JSON_CTX; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_VAR_CONTEXT; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_VAR_CONTEXT_JSON; + +public class RangerScriptConditionEvaluator extends RangerAbstractConditionEvaluator { + private static final Log LOG = LogFactory.getLog(RangerScriptConditionEvaluator.class); + + private static final Log PERF_POLICY_CONDITION_SCRIPT_EVAL = RangerPerfTracer.getPerfLogger("policy.condition.script.eval"); + + private static final String SCRIPT_PREEXEC = SCRIPT_VAR_CONTEXT + "=JSON.parse(" + SCRIPT_VAR_CONTEXT_JSON + ");"; + + private ScriptEngine scriptEngine; + private boolean enableJsonCtx = false; + + @Override + public void init() { + + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerScriptConditionEvaluator.init(" + condition + ")"); + } + + super.init(); + + String engineName = "JavaScript"; + + Map evalOptions = conditionDef. getEvaluatorOptions(); + + if (MapUtils.isNotEmpty(evalOptions)) { + engineName = evalOptions.get("engineName"); + + enableJsonCtx = Boolean.parseBoolean(evalOptions.getOrDefault(SCRIPT_OPTION_ENABLE_JSON_CTX, Boolean.toString(enableJsonCtx))); + } + + if (StringUtils.isBlank(engineName)) { + engineName = "JavaScript"; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("RangerScriptConditionEvaluator.init() - engineName=" + engineName); + } + + String conditionType = condition != null ? condition.getType() : null; + + try { + ScriptEngineManager manager = new ScriptEngineManager(); + + if (LOG.isDebugEnabled()) { + List factories = manager.getEngineFactories(); + + if (CollectionUtils.isEmpty(factories)) { + LOG.debug("List of scriptEngineFactories is empty!!"); + } else { + for (ScriptEngineFactory factory : factories) { + LOG.debug("engineName=" + factory.getEngineName() + ", language=" + factory.getLanguageName()); + } + } + } + + scriptEngine = manager.getEngineByName(engineName); + } catch (Exception exp) { + LOG.error("RangerScriptConditionEvaluator.init() failed with exception=" + exp); + } + + if (scriptEngine == null) { + LOG.warn("failed to initialize condition '" + conditionType + "': script engine '" + engineName + "' was not created in a default manner"); + LOG.info("Will try to get script-engine from plugin-class-loader"); + + + RangerPluginClassLoader pluginClassLoader; + + try { + + pluginClassLoader = RangerPluginClassLoader.getInstance(serviceDef.getName(), null); + + if (pluginClassLoader != null) { + scriptEngine = pluginClassLoader.getScriptEngine(engineName); + } else { + LOG.error("Cannot get script-engine from null pluginClassLoader"); + } + + } catch (Throwable exp) { + LOG.error("RangerScriptConditionEvaluator.init() failed with exception=", exp); + } + } + + if (scriptEngine == null) { + LOG.error("failed to initialize condition '" + conditionType + "': script engine '" + engineName + "' was not created"); + } else { + LOG.info("ScriptEngine for engineName=[" + engineName + "] is successfully created"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerScriptConditionEvaluator.init(" + condition + ")"); + } + } + + @Override + public boolean isMatched(RangerAccessRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerScriptConditionEvaluator.isMatched()"); + } + boolean result = true; + + if (scriptEngine != null) { + + String script = getScript(); + + if (StringUtils.isNotBlank(script)) { + + RangerAccessRequest readOnlyRequest = request.getReadOnlyCopy(); + + RangerScriptExecutionContext context = new RangerScriptExecutionContext(readOnlyRequest); + RangerTagForEval currentTag = context.getCurrentTag(); + Map tagAttribs = currentTag != null ? currentTag.getAttributes() : Collections.emptyMap(); + + Bindings bindings = scriptEngine.createBindings(); + + bindings.put("ctx", context); + bindings.put("tag", currentTag); + bindings.put("tagAttr", tagAttribs); + + if (enableJsonCtx) { + bindings.put(SCRIPT_VAR_CONTEXT_JSON, context.toJson()); + + script = SCRIPT_PREEXEC + script; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("RangerScriptConditionEvaluator.isMatched(): script={" + script + "}"); + } + + RangerPerfTracer perf = null; + + try { + long requestHash = request.hashCode(); + + if (RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_CONDITION_SCRIPT_EVAL)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_CONDITION_SCRIPT_EVAL, "RangerScriptConditionEvaluator.isMatched(requestHash=" + requestHash + ")"); + } + + Object ret = scriptEngine.eval(script, bindings); + + if (ret == null) { + ret = context.getResult(); + } + if (ret instanceof Boolean) { + result = (Boolean) ret; + } + + } catch (NullPointerException nullp) { + LOG.error("RangerScriptConditionEvaluator.isMatched(): eval called with NULL argument(s)", nullp); + + } catch (ScriptException exception) { + LOG.error("RangerScriptConditionEvaluator.isMatched(): failed to evaluate script," + + " exception=" + exception); + } finally { + RangerPerfTracer.log(perf); + } + } else { + String conditionType = condition != null ? condition.getType() : null; + LOG.error("failed to evaluate condition '" + conditionType + "': script is empty"); + } + + } else { + String conditionType = condition != null ? condition.getType() : null; + LOG.error("failed to evaluate condition '" + conditionType + "': script engine not found"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerScriptConditionEvaluator.isMatched(), result=" + result); + } + + return result; + + } + + protected String getScript() { + String ret = null; + + List values = condition.getValues(); + + if (CollectionUtils.isNotEmpty(values)) { + + String value = values.get(0); + if (StringUtils.isNotBlank(value)) { + ret = value.trim(); + } + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerScriptExecutionContext.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerScriptExecutionContext.java new file mode 100644 index 00000000000..3fb1f4bafd9 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerScriptExecutionContext.java @@ -0,0 +1,567 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.atlas.authorization.utils.RangerUtil; +import org.apache.atlas.plugin.contextenricher.RangerTagForEval; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.atlas.plugin.policyengine.RangerAccessResource; +import org.apache.atlas.plugin.util.RangerAccessRequestUtil; +import org.apache.atlas.plugin.util.RangerPerfTracer; +import org.apache.atlas.plugin.util.RangerUserStore; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; + +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_ACCESS_TIME; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_ACCESS_TYPE; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_ACTION; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_CLIENT_IP_ADDRESS; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_CLIENT_TYPE; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_CLUSTER_NAME; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_CLUSTER_TYPE; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_FORWARDED_ADDRESSES; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_REMOTE_IP_ADDRESS; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_REQUEST; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_REQUEST_DATA; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_RESOURCE; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_RESOURCE_MATCHING_SCOPE; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_RESOURCE_OWNER_USER; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_TAG; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_TAGS; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_USER; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_USER_ATTRIBUTES; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_USER_GROUPS; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_USER_GROUP_ATTRIBUTES; +import static org.apache.atlas.plugin.util.RangerCommonConstants.SCRIPT_FIELD_USER_ROLES; + + +public final class RangerScriptExecutionContext { + private static final Log LOG = LogFactory.getLog(RangerScriptExecutionContext.class); + + private static final Log PERF_POLICY_CONDITION_SCRIPT_TOJSON = RangerPerfTracer.getPerfLogger("policy.condition.script.tojson"); + private static final String TAG_ATTR_DATE_FORMAT_PROP = "ranger.plugin.tag.attr.additional.date.formats"; + private static final String TAG_ATTR_DATE_FORMAT_SEPARATOR = "||"; + private static final String TAG_ATTR_DATE_FORMAT_SEPARATOR_REGEX = "\\|\\|"; + private static final String DEFAULT_RANGER_TAG_ATTRIBUTE_DATE_FORMAT = "yyyy/MM/dd"; + private static final String DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT_NAME = "ATLAS_DATE_FORMAT"; + private static final String DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; + + private final RangerAccessRequest accessRequest; + private Boolean result = false; + + private static String[] dateFormatStrings = null; + + static { + init(null); + } + + private static final ThreadLocal> THREADLOCAL_DATE_FORMATS = + new ThreadLocal>() { + @Override protected List initialValue() { + List ret = new ArrayList<>(); + + for (String dateFormatString : dateFormatStrings) { + try { + if (StringUtils.isNotBlank(dateFormatString)) { + if (StringUtils.equalsIgnoreCase(dateFormatString, DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT_NAME)) { + dateFormatString = DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT; + } + SimpleDateFormat df = new SimpleDateFormat(dateFormatString); + df.setLenient(false); + ret.add(df); + } + } catch (Exception exception) { + // Ignore + } + } + + return ret; + } + }; + + RangerScriptExecutionContext(final RangerAccessRequest accessRequest) { + this.accessRequest = accessRequest; + } + + public String toJson() { + RangerPerfTracer perf = null; + + long requestHash = accessRequest.hashCode(); + + if (RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_CONDITION_SCRIPT_TOJSON)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_CONDITION_SCRIPT_TOJSON, "RangerScriptExecutionContext.toJson(requestHash=" + requestHash + ")"); + } + + Map ret = new HashMap<>(); + Map request = new HashMap<>(); + RangerUserStore userStore = RangerAccessRequestUtil.getRequestUserStoreFromContext(accessRequest.getContext()); + + if (accessRequest.getAccessTime() != null) { + request.put(SCRIPT_FIELD_ACCESS_TIME, accessRequest.getAccessTime().getTime()); + } + + request.put(SCRIPT_FIELD_ACCESS_TYPE, accessRequest.getAccessType()); + request.put(SCRIPT_FIELD_ACTION, accessRequest.getAction()); + request.put(SCRIPT_FIELD_CLIENT_IP_ADDRESS, accessRequest.getClientIPAddress()); + request.put(SCRIPT_FIELD_CLIENT_TYPE, accessRequest.getClientType()); + request.put(SCRIPT_FIELD_CLUSTER_NAME, accessRequest.getClusterName()); + request.put(SCRIPT_FIELD_CLUSTER_TYPE, accessRequest.getClusterType()); + request.put(SCRIPT_FIELD_FORWARDED_ADDRESSES, accessRequest.getForwardedAddresses()); + request.put(SCRIPT_FIELD_REMOTE_IP_ADDRESS, accessRequest.getRemoteIPAddress()); + request.put(SCRIPT_FIELD_REQUEST_DATA, accessRequest.getRequestData()); + + if (accessRequest.getResource() != null) { + request.put(SCRIPT_FIELD_RESOURCE, accessRequest.getResource().getAsMap()); + request.put(SCRIPT_FIELD_RESOURCE_OWNER_USER, accessRequest.getResource().getOwnerUser()); + } + + request.put(SCRIPT_FIELD_RESOURCE_MATCHING_SCOPE, accessRequest.getResourceMatchingScope()); + + request.put(SCRIPT_FIELD_USER, accessRequest.getUser()); + request.put(SCRIPT_FIELD_USER_GROUPS, accessRequest.getUserGroups()); + request.put(SCRIPT_FIELD_USER_ROLES, accessRequest.getUserRoles()); + + if (userStore != null) { + Map> userAttrMapping = userStore.getUserAttrMapping(); + Map> groupAttrMapping = userStore.getGroupAttrMapping(); + + if (userAttrMapping != null) { + request.put(SCRIPT_FIELD_USER_ATTRIBUTES, userAttrMapping.get(accessRequest.getUser())); + } + + if (groupAttrMapping != null && accessRequest.getUserGroups() != null) { + Map> groupAttrs = new HashMap<>(); + + for (String groupName : accessRequest.getUserGroups()) { + groupAttrs.put(groupName, groupAttrMapping.get(groupName)); + } + + request.put(SCRIPT_FIELD_USER_GROUP_ATTRIBUTES, groupAttrs); + } + } + + ret.put(SCRIPT_FIELD_REQUEST, request); + + Set requestTags = RangerAccessRequestUtil.getRequestTagsFromContext(getRequestContext()); + + if (CollectionUtils.isNotEmpty(requestTags)) { + Set> tags = new HashSet<>(); + + for (RangerTagForEval tag : requestTags) { + tags.add(toMap(tag)); + } + + ret.put(SCRIPT_FIELD_TAGS, tags); + + RangerTagForEval currentTag = RangerAccessRequestUtil.getCurrentTagFromContext(getRequestContext()); + + if (currentTag != null) { + ret.put(SCRIPT_FIELD_TAG, toMap(currentTag)); + } + } + + RangerAccessResource resource = RangerAccessRequestUtil.getCurrentResourceFromContext(getRequestContext()); + + if (resource != null) { + ret.put(SCRIPT_FIELD_RESOURCE, resource.getAsMap()); + + if (resource.getOwnerUser() != null) { + ret.put(SCRIPT_FIELD_RESOURCE_OWNER_USER, resource.getOwnerUser()); + } + } + + String strRet = RangerUtil.objectToJson(ret); + + RangerPerfTracer.log(perf); + + return strRet; + } + + public static void init(Configuration config) { + StringBuilder sb = new StringBuilder(DEFAULT_RANGER_TAG_ATTRIBUTE_DATE_FORMAT); + + sb.append(TAG_ATTR_DATE_FORMAT_SEPARATOR).append(DEFAULT_ATLAS_TAG_ATTRIBUTE_DATE_FORMAT_NAME); + + String additionalDateFormatsValue = config != null ? config.get(TAG_ATTR_DATE_FORMAT_PROP) : null; + + if (StringUtils.isNotBlank(additionalDateFormatsValue)) { + sb.append(TAG_ATTR_DATE_FORMAT_SEPARATOR).append(additionalDateFormatsValue); + } + + String[] formatStrings = sb.toString().split(TAG_ATTR_DATE_FORMAT_SEPARATOR_REGEX); + + Arrays.sort(formatStrings, new Comparator() { + @Override + public int compare(String first, String second) { + return Integer.compare(second.length(), first.length()); + } + }); + + RangerScriptExecutionContext.dateFormatStrings = formatStrings; + } + + public String getResource() { + String ret = null; + RangerAccessResource val = RangerAccessRequestUtil.getCurrentResourceFromContext(getRequestContext()); + + if(val != null) { + ret = val.getAsString(); + } + + return ret; + } + + public Map getRequestContext() { + return accessRequest.getContext(); + } + + public String getRequestContextAttribute(String attributeName) { + String ret = null; + + if (StringUtils.isNotBlank(attributeName)) { + Object val = getRequestContext().get(attributeName); + + if(val != null) { + ret = val.toString(); + } + } + + return ret; + } + + public boolean isAccessTypeAny() { return accessRequest.isAccessTypeAny(); } + + public boolean isAccessTypeDelegatedAdmin() { return accessRequest.isAccessTypeDelegatedAdmin(); } + + public String getUser() { return accessRequest.getUser(); } + + public Set getUserGroups() { return accessRequest.getUserGroups(); } + + public Date getAccessTime() { return accessRequest.getAccessTime() != null ? accessRequest.getAccessTime() : new Date(); } + + public String getClientIPAddress() { return accessRequest.getClientIPAddress(); } + + public String getClientType() { return accessRequest.getClientType(); } + + public String getAction() { return accessRequest.getAction(); } + + public String getRequestData() { return accessRequest.getRequestData(); } + + public String getSessionId() { return accessRequest.getSessionId(); } + + public RangerTagForEval getCurrentTag() { + RangerTagForEval ret = RangerAccessRequestUtil.getCurrentTagFromContext(getRequestContext()); + + if(ret == null ) { + if (LOG.isDebugEnabled()) { + logDebug("RangerScriptExecutionContext.getCurrentTag() - No current TAG object. Script execution must be for resource-based policy."); + } + } + return ret; + } + + public String getCurrentTagType() { + RangerTagForEval tagObject = getCurrentTag(); + return (tagObject != null) ? tagObject.getType() : null; + } + + public Set getAllTagTypes() { + Set allTagTypes = null; + Set tagObjectList = getAllTags(); + + if (CollectionUtils.isNotEmpty(tagObjectList)) { + for (RangerTagForEval tag : tagObjectList) { + String tagType = tag.getType(); + if (allTagTypes == null) { + allTagTypes = new HashSet<>(); + } + allTagTypes.add(tagType); + } + } + + return allTagTypes; + } + + public Map getTagAttributes(final String tagType) { + Map ret = null; + + if (StringUtils.isNotBlank(tagType)) { + Set tagObjectList = getAllTags(); + + // Assumption: There is exactly one tag with given tagType in the list of tags - may not be true ***TODO*** + // This will get attributes of the first tagType that matches + if (CollectionUtils.isNotEmpty(tagObjectList)) { + for (RangerTagForEval tag : tagObjectList) { + if (tag.getType().equals(tagType)) { + ret = tag.getAttributes(); + break; + } + } + } + } + + return ret; + } + + public List> getTagAttributesForAllMatchingTags(final String tagType) { + List> ret = null; + + if (StringUtils.isNotBlank(tagType)) { + Set tagObjectList = getAllTags(); + + // Assumption: There is exactly one tag with given tagType in the list of tags - may not be true ***TODO*** + // This will get attributes of the first tagType that matches + if (CollectionUtils.isNotEmpty(tagObjectList)) { + for (RangerTagForEval tag : tagObjectList) { + if (tag.getType().equals(tagType)) { + Map tagAttributes = tag.getAttributes(); + if (tagAttributes != null) { + if (ret == null) { + ret = new ArrayList<>(); + } + ret.add(tagAttributes); + } + break; + } + } + } + } + + return ret; + } + + public Set getAttributeNames(final String tagType) { + Set ret = null; + Map attributes = getTagAttributes(tagType); + + if (attributes != null) { + ret = attributes.keySet(); + } + + return ret; + } + + public String getAttributeValue(final String tagType, final String attributeName) { + String ret = null; + + if (StringUtils.isNotBlank(tagType) || StringUtils.isNotBlank(attributeName)) { + Map attributes = getTagAttributes(tagType); + + if (attributes != null) { + ret = attributes.get(attributeName); + } + } + return ret; + } + + public List getAttributeValueForAllMatchingTags(final String tagType, final String attributeName) { + List ret = null; + + if (StringUtils.isNotBlank(tagType) || StringUtils.isNotBlank(attributeName)) { + Map attributes = getTagAttributes(tagType); + + if (attributes != null && attributes.get(attributeName) != null) { + if (ret == null) { + ret = new ArrayList<>(); + } + ret.add(attributes.get(attributeName)); + } + } + return ret; + } + + public String getAttributeValue(final String attributeName) { + String ret = null; + + if (StringUtils.isNotBlank(attributeName)) { + RangerTagForEval tag = getCurrentTag(); + Map attributes = null; + if (tag != null) { + attributes = tag.getAttributes(); + } + if (attributes != null) { + ret = attributes.get(attributeName); + } + } + + return ret; + } + + public boolean getResult() { + return result; + + } + + public void setResult(final boolean result) { + this.result = result; + } + + private Date getAsDate(String value, SimpleDateFormat df) { + Date ret = null; + + TimeZone savedTimeZone = df.getTimeZone(); + try { + ret = df.parse(value); + } catch (ParseException exception) { + // Ignore + } finally { + df.setTimeZone(savedTimeZone); + } + + return ret; + } + + public Date getAsDate(String value) { + Date ret = null; + + if (StringUtils.isNotBlank(value)) { + for (SimpleDateFormat simpleDateFormat : THREADLOCAL_DATE_FORMATS.get()) { + ret = getAsDate(value, simpleDateFormat); + if (ret != null) { + if (LOG.isDebugEnabled()) { + logDebug("RangerScriptExecutionContext.getAsDate() -The best match found for Format-String:[" + simpleDateFormat.toPattern() + "], date:[" + ret +"]"); + } + break; + } + } + } + + if (ret == null) { + logError("RangerScriptExecutionContext.getAsDate() - Could not convert [" + value + "] to Date using any of the Format-Strings: " + Arrays.toString(dateFormatStrings)); + } else { + ret = RangerUtil.getUTCDateForLocalDate(ret); + } + + return ret; + } + + public Date getTagAttributeAsDate(String tagType, String attributeName) { + String attrValue = getAttributeValue(tagType, attributeName); + + return getAsDate(attrValue); + } + + public boolean isAccessedAfter(String tagType, String attributeName) { + boolean ret = false; + Date accessDate = getAccessTime(); + Date expiryDate = getTagAttributeAsDate(tagType, attributeName); + + if (expiryDate == null || accessDate.after(expiryDate) || accessDate.equals(expiryDate)) { + ret = true; + } + + return ret; + } + + public boolean isAccessedAfter(String attributeName) { + boolean ret = false; + Date accessDate = getAccessTime(); + Date expiryDate = getAsDate(getAttributeValue(attributeName)); + + if (expiryDate == null || accessDate.after(expiryDate) || accessDate.equals(expiryDate)) { + ret = true; + } + + return ret; + } + + public boolean isAccessedBefore(String tagType, String attributeName) { + boolean ret = true; + Date accessDate = getAccessTime(); + Date expiryDate = getTagAttributeAsDate(tagType, attributeName); + + if (expiryDate == null || accessDate.after(expiryDate)) { + ret = false; + } + + return ret; + } + + public boolean isAccessedBefore(String attributeName) { + boolean ret = true; + Date accessDate = getAccessTime(); + Date expiryDate = getAsDate(getAttributeValue(attributeName)); + + if (expiryDate == null || accessDate.after(expiryDate)) { + ret = false; + } + + return ret; + } + + private Set getAllTags() { + Set ret = RangerAccessRequestUtil.getRequestTagsFromContext(accessRequest.getContext()); + if(ret == null) { + if (LOG.isDebugEnabled()) { + String resource = accessRequest.getResource().getAsString(); + + logDebug("RangerScriptExecutionContext.getAllTags() - No TAGS. No TAGS for the RangerAccessResource=" + resource); + } + } + + return ret; + } + + private static Map toMap(RangerTagForEval tag) { + Map ret = new HashMap<>(); + + ret.put("type", tag.getType()); + ret.put("attributes", tag.getAttributes()); + ret.put("matchType", tag.getMatchType()); + + return ret; + } + + public void logDebug(Object msg) { + LOG.debug(msg); + } + + public void logInfo(Object msg) { + LOG.info(msg); + } + + public void logWarn(Object msg) { + LOG.warn(msg); + } + + public void logError(Object msg) { + LOG.error(msg); + } + + public void logFatal(Object msg) { + LOG.fatal(msg); + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerScriptTemplateConditionEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerScriptTemplateConditionEvaluator.java new file mode 100644 index 00000000000..dc397c28959 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerScriptTemplateConditionEvaluator.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; + +public class RangerScriptTemplateConditionEvaluator extends RangerScriptConditionEvaluator { + private static final Log LOG = LogFactory.getLog(RangerScriptTemplateConditionEvaluator.class); + + protected String script; + private boolean reverseResult; + + @Override + public void init() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerScriptTemplateConditionEvaluator.init(" + condition + ")"); + } + + super.init(); + + if(CollectionUtils.isNotEmpty(condition.getValues())) { + String expectedScriptReturn = condition.getValues().get(0); + + if(StringUtils.isNotBlank(expectedScriptReturn)) { + if(StringUtils.equalsIgnoreCase(expectedScriptReturn, "false") || StringUtils.equalsIgnoreCase(expectedScriptReturn, "no")) { + reverseResult = true; + } + + script = MapUtils.getString(conditionDef.getEvaluatorOptions(), "scriptTemplate"); + + if(script != null) { + script = script.trim(); + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerScriptTemplateConditionEvaluator.init(" + condition + "): script=" + script + "; reverseResult=" + reverseResult); + } + } + + @Override + public boolean isMatched(RangerAccessRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerScriptTemplateConditionEvaluator.isMatched()"); + } + + boolean ret = super.isMatched(request); + + if(reverseResult) { + ret = !ret; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerScriptTemplateConditionEvaluator.isMatched(): ret=" + ret); + } + + return ret; + } + + @Override + protected String getScript() { + return script; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerTagsAllPresentConditionEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerTagsAllPresentConditionEvaluator.java new file mode 100644 index 00000000000..42de615de5e --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerTagsAllPresentConditionEvaluator.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; + +import java.util.HashSet; +import java.util.Set; + + +public class RangerTagsAllPresentConditionEvaluator extends RangerAbstractConditionEvaluator { + + private static final Log LOG = LogFactory.getLog(RangerTagsAllPresentConditionEvaluator.class); + + private final Set policyConditionTags = new HashSet<>(); + + @Override + public void init() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagsAllPresentConditionEvaluator.init(" + condition + ")"); + } + + super.init(); + + if (condition != null ) { + for (String value : condition.getValues()) { + policyConditionTags.add(value.trim()); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagsAllPresentConditionEvaluator.init(" + condition + "): Tags[" + policyConditionTags + "]"); + } + } + + @Override + public boolean isMatched(RangerAccessRequest request) { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagsAllPresentConditionEvaluator.isMatched(" + request + ")"); + } + + boolean matched = true; + + if (CollectionUtils.isNotEmpty(policyConditionTags)) { + RangerAccessRequest readOnlyRequest = request.getReadOnlyCopy(); + RangerScriptExecutionContext context = new RangerScriptExecutionContext(readOnlyRequest); + Set resourceTags = context.getAllTagTypes(); + + // check if resource Tags atleast have to have all the tags in policy Condition + matched = resourceTags != null && resourceTags.containsAll(policyConditionTags); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagsAllPresentConditionEvaluator.isMatched(" + request+ "): " + matched); + } + + return matched; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerTimeOfDayMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerTimeOfDayMatcher.java new file mode 100644 index 00000000000..d265c68670c --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/conditionevaluator/RangerTimeOfDayMatcher.java @@ -0,0 +1,203 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.conditionevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RangerTimeOfDayMatcher extends RangerAbstractConditionEvaluator { + private static final Log LOG = LogFactory.getLog(RangerTimeOfDayMatcher.class); + boolean _allowAny; + List _durations = new ArrayList<>(); + + @Override + public void init() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerTimeOfDayMatcher.init(" + condition + ")"); + } + + super.init(); + + if (condition == null) { + LOG.debug("init: null policy condition! Will match always!"); + _allowAny = true; + } else if (CollectionUtils.isEmpty(condition.getValues())) { + LOG.debug("init: empty conditions collection on policy condition! Will match always!"); + _allowAny = true; + } else { + for (String value : condition.getValues()) { + if (StringUtils.isEmpty(value)) { + LOG.warn("init: Unexpected: one of the value in condition is null or empty!"); + } else { + int[] aDuration = extractDuration(value); + if (aDuration != null) { + _durations.add(aDuration); + } + } + } + } + + if (_durations.isEmpty()) { + LOG.debug("No valid durations found. Will always match!"); + _allowAny = true; + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerTimeOfDayMatcher.init(" + condition + "): durations[" + toString() + "]"); + } + } + + // match "9am-5pm", "9 Am - 5 PM", "9 am.- 5 P.M", "9:30 AM - 4:00p.m." etc. spaces around - and after digits are allowed and dots in am/pm string in mixed cases is allowed + static final Pattern _Pattern = Pattern.compile(" *(\\d{1,2})(:(\\d{1,2}))? *([aApP])\\.?[mM]\\.? *- *(\\d{1,2})(:(\\d{1,2}))? *([aApP])\\.?[mM]\\.? *"); + + int[] extractDuration(String value) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerTimeOfDayMatcher.extractDuration(" + value + ")"); + } + + int[] result = null; + if (value == null) { + LOG.warn("extractDuration: null input value!"); + } else { + Matcher m = _Pattern.matcher(value); + if (!m.matches()) { + LOG.warn("extractDuration: input[" + value + "] did not match pattern!"); + } else { + int startHour = Integer.parseInt(m.group(1)); + int startMin = 0; + if (m.group(3) != null) { + startMin = Integer.parseInt(m.group(3)); + } + String startType = m.group(4).toUpperCase(); + + int endHour = Integer.parseInt(m.group(5)); + int endMinute = 0; + if (m.group(7) != null) { + endMinute = Integer.parseInt(m.group(7)); + } + String endType = m.group(8).toUpperCase(); + if(startHour == 12) { + if("A".equals(startType)) { + startHour = 0; + } + } else if ("P".equals(startType)) { + startHour += 12; + } + + if(endHour == 12) { + if("A".equals(endType)) { + endHour = 0; + } + } else if ("P".equals(endType)) { + endHour += 12; + } + + result = new int[] { (startHour*60)+startMin, (endHour*60)+endMinute }; + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerTimeOfDayMatcher.extractDuration(" + value + "): duration:" + Arrays.toString(result)); + } + return result; + } + + @Override + public boolean isMatched(RangerAccessRequest request) { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerTimeOfDayMatcher.isMatched(" + request + ")"); + } + + boolean matched = true; + if (_allowAny) { + LOG.debug("isMatched: allowAny flag is true. Matched!"); + } else if (request == null) { + LOG.warn("isMatched: Unexpected: Request is null! Implicitly matched!"); + } else if (request.getAccessTime() == null) { + LOG.warn("isMatched: Unexpected: Accesstime on the request is null! Implicitly matched!"); + } else { + Date date = request.getAccessTime(); + Calendar calendar = GregorianCalendar.getInstance(); + calendar.setTime(date); + int hourOfDay = calendar.get(Calendar.HOUR_OF_DAY); + int minutes = calendar.get(Calendar.MINUTE); + if (! durationMatched(_durations, hourOfDay, minutes)) { + matched = false; + + if (LOG.isDebugEnabled()) { + LOG.debug("isMatched: None of the durations contains this hour of day[" + hourOfDay + "] and minutes[" + minutes + "]"); + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerTimeOfDayMatcher.isMatched(" + request+ "): " + matched); + } + + return matched; + } + + boolean durationMatched(List durations, int hourOfDay, int minutes) { + for (int[] aDuration : durations) { + int start = aDuration[0]; + int end = aDuration[1]; + int minutesOfDay = hourOfDay*60 + minutes; + if(start < end) { + if (start <= minutesOfDay && minutesOfDay <= end) { + return true; + } + } else { + if(start <= minutesOfDay || minutesOfDay <= end) { + return true; + } + } + } + return false; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("RangerTimeOfDayMatcher {"); + sb.append("_allowAny=").append(_allowAny).append(" "); + sb.append("_durations=["); + for(int[] duration : _durations) { + sb.append("{start=").append(duration[0]).append("; end=").append(duration[1]).append("} "); + } + sb.append("]"); + sb.append("}"); + + return sb.toString(); + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerAbstractContextEnricher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerAbstractContextEnricher.java new file mode 100644 index 00000000000..4e39cf57354 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerAbstractContextEnricher.java @@ -0,0 +1,342 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.contextenricher; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.atlas.authorization.config.RangerPluginConfig; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerContextEnricherDef; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.atlas.plugin.policyengine.RangerPluginContext; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngineOptions; +import org.apache.atlas.plugin.service.RangerAuthContext; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Map; +import java.util.Properties; + + +public abstract class RangerAbstractContextEnricher implements RangerContextEnricher { + private static final Log LOG = LogFactory.getLog(RangerAbstractContextEnricher.class); + + protected RangerContextEnricherDef enricherDef; + protected String serviceName; + protected String appId; + protected RangerServiceDef serviceDef; + private RangerPluginContext pluginContext; + protected RangerPolicyEngineOptions options = new RangerPolicyEngineOptions(); + + @Override + public void setEnricherDef(RangerContextEnricherDef enricherDef) { + this.enricherDef = enricherDef; + } + + @Override + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + @Override + public void setServiceDef(RangerServiceDef serviceDef) { + this.serviceDef = serviceDef; + } + + @Override + public void setAppId(String appId) { + this.appId = appId; + } + + @Override + public void init() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerAbstractContextEnricher.init(" + enricherDef + ")"); + } + + RangerAuthContext authContext = getAuthContext(); + + if (authContext != null) { + authContext.addOrReplaceRequestContextEnricher(this, null); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("authContext is null. This context-enricher is not added to authContext"); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerAbstractContextEnricher.init(" + enricherDef + ")"); + } + } + + @Override + public void enrich(RangerAccessRequest request, Object dataStore) { + enrich(request); + } + + @Override + public boolean preCleanup() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerAbstractContextEnricher.preCleanup(" + enricherDef + ")"); + } + + RangerAuthContext authContext = getAuthContext(); + + if (authContext != null) { + authContext.cleanupRequestContextEnricher(this); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("authContext is null. AuthContext need not be cleaned."); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerAbstractContextEnricher.preCleanup(" + enricherDef + ")"); + } + + return true; + } + + @Override + public void cleanup() { + preCleanup(); + } + + @Override + protected void finalize() throws Throwable { + try { + cleanup(); + } + finally { + super.finalize(); + } + } + + @Override + public String getName() { + return enricherDef == null ? null : enricherDef.getName(); + } + + public RangerContextEnricherDef getEnricherDef() { + return enricherDef; + } + + public String getServiceName() { + return serviceName; + } + + public RangerServiceDef getServiceDef() { + return serviceDef; + } + + public String getAppId() { + return appId; + } + + public String getOption(String name) { + String ret = null; + + Map options = enricherDef != null ? enricherDef.getEnricherOptions() : null; + + if(options != null && name != null) { + ret = options.get(name); + } + + return ret; + } + + public RangerAuthContext getAuthContext() { + RangerPluginContext pluginContext = this.pluginContext; + + return pluginContext != null ? pluginContext.getAuthContext() : null; + } + + final public void setPluginContext(RangerPluginContext pluginContext) { + this.pluginContext = pluginContext; + } + + public RangerPluginContext getPluginContext() { + return this.pluginContext; + } + + final public void setPolicyEngineOptions(RangerPolicyEngineOptions options) { + this.options = options; + } + + public RangerPluginConfig getPluginConfig() { + RangerPluginContext pluginContext = this.pluginContext; + + return pluginContext != null ? pluginContext.getConfig() : null; + } + + public RangerPolicyEngineOptions getPolicyEngineOptions() { + return options; + } + + public void notifyAuthContextChanged() { + RangerPluginContext pluginContext = this.pluginContext; + + if (pluginContext != null) { + pluginContext.notifyAuthContextChanged(); + } + } + + public String getConfig(String configName, String defaultValue) { + RangerPluginContext pluginContext = this.pluginContext; + String ret = defaultValue; + Configuration config = pluginContext != null ? pluginContext.getConfig() : null; + + if (config != null) { + ret = config.get(configName, defaultValue); + } + + return ret; + } + + public int getIntConfig(String configName, int defaultValue) { + RangerPluginContext pluginContext = this.pluginContext; + int ret = defaultValue; + Configuration config = pluginContext != null ? pluginContext.getConfig() : null; + + if (config != null) { + ret = config.getInt(configName, defaultValue); + } + + return ret; + } + + public boolean getBooleanConfig(String configName, boolean defaultValue) { + RangerPluginContext pluginContext = this.pluginContext; + boolean ret = defaultValue; + Configuration config = pluginContext != null ? pluginContext.getConfig() : null; + + if (config != null) { + ret = config.getBoolean(configName, defaultValue); + } + + return ret; + } + + public String getOption(String name, String defaultValue) { + String ret = defaultValue; + String val = getOption(name); + + if(val != null) { + ret = val; + } + + return ret; + } + + public boolean getBooleanOption(String name, boolean defaultValue) { + boolean ret = defaultValue; + String val = getOption(name); + + if(val != null) { + ret = Boolean.parseBoolean(val); + } + + return ret; + } + + public char getCharOption(String name, char defaultValue) { + char ret = defaultValue; + String val = getOption(name); + + if(! StringUtils.isEmpty(val)) { + ret = val.charAt(0); + } + + return ret; + } + + public long getLongOption(String name, long defaultValue) { + long ret = defaultValue; + String val = getOption(name); + + if(val != null) { + ret = Long.parseLong(val); + } + + return ret; + } + + public Properties readProperties(String fileName) { + Properties ret = null; + InputStream inStr = null; + URL fileURL = null; + File f = new File(fileName); + + if (f.exists() && f.isFile() && f.canRead()) { + try { + inStr = new FileInputStream(f); + fileURL = f.toURI().toURL(); + } catch (FileNotFoundException exception) { + LOG.error("Error processing input file:" + fileName + " or no privilege for reading file " + fileName, exception); + } catch (MalformedURLException malformedException) { + LOG.error("Error processing input file:" + fileName + " cannot be converted to URL " + fileName, malformedException); + } + } else { + fileURL = getClass().getResource(fileName); + + if (fileURL == null && !fileName.startsWith("/")) { + fileURL = getClass().getResource("/" + fileName); + } + + if (fileURL == null) { + fileURL = ClassLoader.getSystemClassLoader().getResource(fileName); + + if (fileURL == null && !fileName.startsWith("/")) { + fileURL = ClassLoader.getSystemClassLoader().getResource("/" + fileName); + } + } + } + + if (fileURL != null) { + try { + inStr = fileURL.openStream(); + + Properties prop = new Properties(); + + prop.load(inStr); + + ret = prop; + } catch (Exception excp) { + LOG.error("failed to load properties from file '" + fileName + "'", excp); + } finally { + if (inStr != null) { + try { + inStr.close(); + } catch (Exception excp) { + // ignore + } + } + } + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerContextEnricher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerContextEnricher.java new file mode 100644 index 00000000000..a427eb5e8bd --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerContextEnricher.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.contextenricher; + + +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerContextEnricherDef; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; + +public interface RangerContextEnricher { + void setEnricherDef(RangerContextEnricherDef enricherDef); + + void setServiceName(String serviceName); + + void setServiceDef(RangerServiceDef serviceDef); + + void setAppId(String appId); + + void init(); + + void enrich(RangerAccessRequest request); + + void enrich(RangerAccessRequest request, Object dataStore); + + boolean preCleanup(); + + void cleanup(); + + String getName(); + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerServiceResourceMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerServiceResourceMatcher.java new file mode 100644 index 00000000000..c7fb07bc6a2 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerServiceResourceMatcher.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.contextenricher; + +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerServiceResource; +import org.apache.atlas.plugin.policyengine.RangerAccessResource; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceEvaluator; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; +import org.apache.atlas.plugin.resourcematcher.RangerResourceMatcher; +import org.apache.atlas.plugin.util.ServiceDefUtil; + +import java.io.Serializable; +import java.util.Comparator; +import java.util.Map; + +public class RangerServiceResourceMatcher implements RangerPolicyResourceEvaluator { + public static final Comparator ID_COMPARATOR = new IdComparator(); + + private final RangerServiceResource serviceResource; + private final RangerPolicyResourceMatcher policyResourceMatcher; + private RangerServiceDef.RangerResourceDef leafResourceDef; + + public RangerServiceResourceMatcher(final RangerServiceResource serviceResource, RangerPolicyResourceMatcher policyResourceMatcher) { + this.serviceResource = serviceResource; + this.policyResourceMatcher = policyResourceMatcher; + this.leafResourceDef = ServiceDefUtil.getLeafResourceDef(policyResourceMatcher.getServiceDef(), getPolicyResource()); + } + + public RangerServiceResource getServiceResource() { return serviceResource; } + + @Override + public long getId() { + return serviceResource != null ? serviceResource.getId() :-1; + } + + @Override + public String getGuid() { + return serviceResource != null ? serviceResource.getGuid() : "-1"; + } + + @Override + public RangerPolicyResourceMatcher getPolicyResourceMatcher() { return policyResourceMatcher; } + + @Override + public Map getPolicyResource() { + return serviceResource != null ? serviceResource.getResourceElements() : null; + } + + @Override + public RangerResourceMatcher getResourceMatcher(String resourceName) { + return policyResourceMatcher != null ? policyResourceMatcher.getResourceMatcher(resourceName) : null; + } + + @Override + public boolean isAncestorOf(RangerServiceDef.RangerResourceDef resourceDef) { + return ServiceDefUtil.isAncestorOf(policyResourceMatcher.getServiceDef(), leafResourceDef, resourceDef); + } + + public RangerPolicyResourceMatcher.MatchType getMatchType(RangerAccessResource requestedResource, Map evalContext) { + return policyResourceMatcher != null ? policyResourceMatcher.getMatchType(requestedResource, evalContext) : RangerPolicyResourceMatcher.MatchType.NONE; + } + + static class IdComparator implements Comparator, Serializable { + @Override + public int compare(RangerServiceResourceMatcher me, RangerServiceResourceMatcher other) { + return Long.compare(me.getId(), other.getId()); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerTagEnricher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerTagEnricher.java new file mode 100644 index 00000000000..488fd3461e8 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerTagEnricher.java @@ -0,0 +1,1190 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.contextenricher; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.authorization.config.RangerPluginConfig; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerServiceResource; +import org.apache.atlas.plugin.model.RangerTag; +import org.apache.atlas.plugin.model.validation.RangerServiceDefHelper; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.atlas.plugin.policyengine.RangerAccessRequestImpl; +import org.apache.atlas.plugin.policyengine.RangerAccessResource; +import org.apache.atlas.plugin.policyengine.RangerAccessResourceImpl; +import org.apache.atlas.plugin.policyengine.RangerResourceTrie; +import org.apache.atlas.plugin.policyresourcematcher.RangerDefaultPolicyResourceMatcher; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; +import org.apache.atlas.plugin.service.RangerAuthContext; +import org.apache.atlas.plugin.util.DownloadTrigger; +import org.apache.atlas.plugin.util.DownloaderTask; +import org.apache.atlas.plugin.util.RangerAccessRequestUtil; +import org.apache.atlas.plugin.util.RangerCommonConstants; +import org.apache.atlas.plugin.util.RangerPerfTracer; +import org.apache.atlas.plugin.util.RangerReadWriteLock; +import org.apache.atlas.plugin.util.RangerServiceNotFoundException; +import org.apache.atlas.plugin.util.RangerServiceTagsDeltaUtil; +import org.apache.atlas.plugin.util.ServiceTags; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Timer; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +public class RangerTagEnricher extends RangerAbstractContextEnricher { + private static final Log LOG = LogFactory.getLog(RangerTagEnricher.class); + + private static final Log PERF_CONTEXTENRICHER_INIT_LOG = RangerPerfTracer.getPerfLogger("contextenricher.init"); + private static final Log PERF_TRIE_OP_LOG = RangerPerfTracer.getPerfLogger("resourcetrie.retrieval"); + private static final Log PERF_SET_SERVICETAGS_LOG = RangerPerfTracer.getPerfLogger("tagenricher.setservicetags"); + + + private static final String TAG_REFRESHER_POLLINGINTERVAL_OPTION = "tagRefresherPollingInterval"; + public static final String TAG_RETRIEVER_CLASSNAME_OPTION = "tagRetrieverClassName"; + private static final String TAG_DISABLE_TRIE_PREFILTER_OPTION = "disableTrieLookupPrefilter"; + + private RangerTagRefresher tagRefresher; + private RangerTagRetriever tagRetriever; + private boolean disableTrieLookupPrefilter; + private EnrichedServiceTags enrichedServiceTags; + private boolean disableCacheIfServiceNotFound = true; + + private final BlockingQueue tagDownloadQueue = new LinkedBlockingQueue<>(); + private Timer tagDownloadTimer; + + private RangerServiceDefHelper serviceDefHelper; + private RangerReadWriteLock lock = new RangerReadWriteLock(false); + + @Override + public void init() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagEnricher.init()"); + } + + super.init(); + + String tagRetrieverClassName = getOption(TAG_RETRIEVER_CLASSNAME_OPTION); + + long pollingIntervalMs = getLongOption(TAG_REFRESHER_POLLINGINTERVAL_OPTION, 60 * 1000); + + disableTrieLookupPrefilter = getBooleanOption(TAG_DISABLE_TRIE_PREFILTER_OPTION, false); + + serviceDefHelper = new RangerServiceDefHelper(serviceDef, false); + + if (StringUtils.isNotBlank(tagRetrieverClassName)) { + + try { + @SuppressWarnings("unchecked") + Class tagRetriverClass = (Class) Class.forName(tagRetrieverClassName); + + tagRetriever = tagRetriverClass.newInstance(); + + } catch (ClassNotFoundException exception) { + LOG.error("Class " + tagRetrieverClassName + " not found, exception=" + exception); + } catch (ClassCastException exception) { + LOG.error("Class " + tagRetrieverClassName + " is not a type of RangerTagRetriever, exception=" + exception); + } catch (IllegalAccessException exception) { + LOG.error("Class " + tagRetrieverClassName + " illegally accessed, exception=" + exception); + } catch (InstantiationException exception) { + LOG.error("Class " + tagRetrieverClassName + " could not be instantiated, exception=" + exception); + } + + if (tagRetriever != null) { + String propertyPrefix = "ranger.plugin." + serviceDef.getName(); + disableCacheIfServiceNotFound = getBooleanConfig(propertyPrefix + ".disable.cache.if.servicenotfound", true); + String cacheDir = getConfig(propertyPrefix + ".policy.cache.dir", null); + String cacheFilename = String.format("%s_%s_tag.json", appId, serviceName); + + cacheFilename = cacheFilename.replace(File.separatorChar, '_'); + cacheFilename = cacheFilename.replace(File.pathSeparatorChar, '_'); + + String cacheFile = cacheDir == null ? null : (cacheDir + File.separator + cacheFilename); + + createLock(); + + tagRetriever.setServiceName(serviceName); + tagRetriever.setServiceDef(serviceDef); + tagRetriever.setAppId(appId); + tagRetriever.setPluginConfig(getPluginConfig()); + tagRetriever.setPluginContext(getPluginContext()); + tagRetriever.init(enricherDef.getEnricherOptions()); + + tagRefresher = new RangerTagRefresher(tagRetriever, this, -1L, tagDownloadQueue, cacheFile); + LOG.info("Created RangerTagRefresher Thread(" + tagRefresher.getName() + ")"); + + try { + tagRefresher.populateTags(); + } catch (Throwable exception) { + LOG.error("Exception when retrieving tag for the first time for this enricher", exception); + } + tagRefresher.setDaemon(true); + tagRefresher.startRefresher(); + + tagDownloadTimer = new Timer("policyDownloadTimer", true); + + try { + tagDownloadTimer.schedule(new DownloaderTask(tagDownloadQueue), pollingIntervalMs, pollingIntervalMs); + if (LOG.isDebugEnabled()) { + LOG.debug("Scheduled tagDownloadRefresher to download tags every " + pollingIntervalMs + " milliseconds"); + } + } catch (IllegalStateException exception) { + LOG.error("Error scheduling tagDownloadTimer:", exception); + LOG.error("*** Tags will NOT be downloaded every " + pollingIntervalMs + " milliseconds ***"); + tagDownloadTimer = null; + } + } + } else { + LOG.warn("No value specified for " + TAG_RETRIEVER_CLASSNAME_OPTION + " in the RangerTagEnricher options"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagEnricher.init()"); + } + } + + @Override + public void enrich(RangerAccessRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagEnricher.enrich(" + request + ")"); + } + + enrich(request, null); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagEnricher.enrich(" + request + ")"); + } + } + + @Override + public void enrich(RangerAccessRequest request, Object dataStore) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagEnricher.enrich(" + request + ") with dataStore:[" + dataStore + "]"); + } + + Set atlasClassificationSet = getMatchingAtlasClassificationsToAsset(request); + + final Set matchedTags; + + try (RangerReadWriteLock.RangerLock readLock = this.lock.getReadLock()) { + + if (LOG.isDebugEnabled()) { + if (readLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + readLock); + } + } + + final EnrichedServiceTags enrichedServiceTags; + + if (dataStore instanceof EnrichedServiceTags) { + enrichedServiceTags = (EnrichedServiceTags) dataStore; + } else { + enrichedServiceTags = this.enrichedServiceTags; + + if (dataStore != null) { + LOG.warn("Incorrect type of dataStore :[" + dataStore.getClass().getName() + "], falling back to original enrich"); + } + } + + if(atlasClassificationSet!=null && atlasClassificationSet.size() > 0) { + matchedTags = atlasClassificationSet; + } else { + matchedTags = enrichedServiceTags == null ? null : findMatchingTags(request, enrichedServiceTags); + } + + RangerAccessRequestUtil.setRequestTagsInContext(request.getContext(), matchedTags); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagEnricher.enrich(" + request + ") with dataStore:[" + dataStore + "]): tags count=" + (matchedTags == null ? 0 : matchedTags.size())); + } + } + + private Set getMatchingAtlasClassificationsToAsset(RangerAccessRequest request) { + + Map requestContext = request.getContext(); + + Set atlasClassificationSet = new HashSet<>(); + + if (requestContext != null && requestContext.get("CLASSIFICATIONS") != null) { + atlasClassificationSet = (Set) requestContext.get("CLASSIFICATIONS"); + } + return atlasClassificationSet; + } + + /* + * This class implements a cache of result of look-up of keyset of policy-resources for each of the collections of hierarchies + * for policy types: access, datamask and rowfilter. If a keyset is examined for validity in a hierarchy of a policy-type, + * then that record is maintained in this cache for later look-up. + * + * The basic idea is that with a large number of tagged service-resources, this cache will speed up performance as well as put + * a cap on the upper bound because it is expected that the cardinality of set of all possible keysets for all resource-def + * combinations in a service-def will be much smaller than the number of service-resources. + */ + + static public class ResourceHierarchies { + private final Map, Boolean> accessHierarchies = new HashMap<>(); + private final Map, Boolean> dataMaskHierarchies = new HashMap<>(); + private final Map, Boolean> rowFilterHierarchies = new HashMap<>(); + + Boolean isValidHierarchy(String policyType, Collection resourceKeys) { + switch (policyType) { + case RangerPolicy.POLICY_TYPE_ACCESS: + return accessHierarchies.get(resourceKeys); + case RangerPolicy.POLICY_TYPE_DATAMASK: + return dataMaskHierarchies.get(resourceKeys); + case RangerPolicy.POLICY_TYPE_ROWFILTER: + return rowFilterHierarchies.get(resourceKeys); + default: + return null; + } + } + + void addHierarchy(String policyType, Collection resourceKeys, Boolean isValid) { + switch (policyType) { + case RangerPolicy.POLICY_TYPE_ACCESS: + accessHierarchies.put(resourceKeys, isValid); + break; + case RangerPolicy.POLICY_TYPE_DATAMASK: + dataMaskHierarchies.put(resourceKeys, isValid); + break; + case RangerPolicy.POLICY_TYPE_ROWFILTER: + rowFilterHierarchies.put(resourceKeys, isValid); + break; + default: + LOG.error("unknown policy-type " + policyType); + break; + } + } + } + + public void setServiceTags(final ServiceTags serviceTags) { + boolean rebuildOnlyIndex = false; + setServiceTags(serviceTags, rebuildOnlyIndex); + } + + protected void setServiceTags(final ServiceTags serviceTags, final boolean rebuildOnlyIndex) { + + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagEnricher.setServiceTags(serviceTags=" + serviceTags + ", rebuildOnlyIndex=" + rebuildOnlyIndex + ")"); + } + + try (RangerReadWriteLock.RangerLock writeLock = this.lock.getWriteLock()) { + + if (LOG.isDebugEnabled()) { + if (writeLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + writeLock); + } + } + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_SET_SERVICETAGS_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_SET_SERVICETAGS_LOG, "RangerTagEnricher.setServiceTags(newTagVersion=" + serviceTags.getTagVersion() + ",isDelta=" + serviceTags.getIsDelta() + ")"); + } + + if (serviceTags == null) { + LOG.info("ServiceTags is null for service " + serviceName); + enrichedServiceTags = null; + } else { + if (!serviceTags.getIsDelta()) { + processServiceTags(serviceTags); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Received service-tag deltas:" + serviceTags); + } + ServiceTags oldServiceTags = enrichedServiceTags != null ? enrichedServiceTags.getServiceTags() : new ServiceTags(); + ServiceTags allServiceTags = rebuildOnlyIndex ? oldServiceTags : RangerServiceTagsDeltaUtil.applyDelta(oldServiceTags, serviceTags); + + if (serviceTags.getTagsChangeExtent() == ServiceTags.TagsChangeExtent.NONE) { + if (LOG.isDebugEnabled()) { + LOG.debug("No change to service-tags other than version change"); + } + } else { + if (serviceTags.getTagsChangeExtent() != ServiceTags.TagsChangeExtent.TAGS) { + Map> trieMap; + + if (enrichedServiceTags == null) { + trieMap = new HashMap<>(); + } else { + trieMap = writeLock.isLockingEnabled() ? enrichedServiceTags.getServiceResourceTrie() : copyServiceResourceTrie(); + } + + processServiceTagDeltas(serviceTags, allServiceTags, trieMap); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Delta contains only tag attribute changes"); + } + List resourceMatchers = enrichedServiceTags != null ? enrichedServiceTags.getServiceResourceMatchers() : new ArrayList<>(); + Map> serviceResourceTrie = enrichedServiceTags != null ? enrichedServiceTags.getServiceResourceTrie() : new HashMap<>(); + enrichedServiceTags = new EnrichedServiceTags(allServiceTags, resourceMatchers, serviceResourceTrie); + } + } + } + + } + setEnrichedServiceTagsInPlugin(); + + RangerPerfTracer.logAlways(perf); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagEnricher.setServiceTags(serviceTags=" + serviceTags + ", rebuildOnlyIndex=" + rebuildOnlyIndex + ")"); + } + + } + + public Long getServiceTagsVersion() { + EnrichedServiceTags localEnrichedServiceTags = enrichedServiceTags; + return localEnrichedServiceTags != null ? localEnrichedServiceTags.getServiceTags().getTagVersion() : -1L; + } + + protected Long getResourceTrieVersion() { + EnrichedServiceTags localEnrichedServiceTags = enrichedServiceTags; + return localEnrichedServiceTags != null ? localEnrichedServiceTags.getResourceTrieVersion() : -1L; + } + + @Override + public boolean preCleanup() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagEnricher.preCleanup()"); + } + + super.preCleanup(); + + Timer tagDownloadTimer = this.tagDownloadTimer; + this.tagDownloadTimer = null; + + if (tagDownloadTimer != null) { + tagDownloadTimer.cancel(); + } + + RangerTagRefresher tagRefresher = this.tagRefresher; + this.tagRefresher = null; + + if (tagRefresher != null) { + tagRefresher.cleanup(); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagEnricher.preCleanup() : result=" + true); + } + return true; + } + + public void syncTagsWithAdmin(final DownloadTrigger token) throws InterruptedException { + tagDownloadQueue.put(token); + token.waitForCompletion(); + } + + public EnrichedServiceTags getEnrichedServiceTags() { + return enrichedServiceTags; + } + + protected RangerReadWriteLock createLock() { + String propertyPrefix = "ranger.plugin." + serviceDef.getName(); + RangerPluginConfig config = getPluginConfig(); + boolean deltasEnabled = config != null && config.getBoolean(propertyPrefix + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_TAG_DELTA, RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_TAG_DELTA_DEFAULT); + boolean inPlaceUpdatesEnabled = config != null && config.getBoolean(propertyPrefix + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_IN_PLACE_TAG_UPDATES, RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_IN_PLACE_TAG_UPDATES_DEFAULT); + boolean useReadWriteLock = deltasEnabled && inPlaceUpdatesEnabled; + + LOG.info("Policy-Engine will" + (useReadWriteLock ? " " : " not ") + "use read-write locking to update tags in place when tag-deltas are provided"); + + return new RangerReadWriteLock(useReadWriteLock); + + } + private void processServiceTags(ServiceTags serviceTags) { + if (LOG.isDebugEnabled()) { + LOG.debug("Processing all service-tags"); + } + + boolean isInError = false; + + if (CollectionUtils.isEmpty(serviceTags.getServiceResources())) { + LOG.info("There are no tagged resources for service " + serviceName); + enrichedServiceTags = null; + } else { + + ResourceHierarchies hierarchies = new ResourceHierarchies(); + + List resourceMatchers = new ArrayList<>(); + List serviceResources = serviceTags.getServiceResources(); + + for (RangerServiceResource serviceResource : serviceResources) { + RangerServiceResourceMatcher serviceResourceMatcher = createRangerServiceResourceMatcher(serviceResource, serviceDefHelper, hierarchies); + if (serviceResourceMatcher != null) { + resourceMatchers.add(serviceResourceMatcher); + } else { + LOG.error("Could not create service-resource-matcher for service-resource:[" + serviceResource + "]"); + isInError = true; + break; + } + } + + if (isInError) { + serviceTags.setTagVersion(-1L); + LOG.error("Error in processing tag-deltas. Will continue to use old tags"); + } else { + Map> serviceResourceTrie = null; + + if (!disableTrieLookupPrefilter) { + serviceResourceTrie = new HashMap<>(); + + for (RangerServiceDef.RangerResourceDef resourceDef : serviceDef.getResources()) { + serviceResourceTrie.put(resourceDef.getName(), new RangerResourceTrie(resourceDef, resourceMatchers, getPolicyEngineOptions().optimizeTrieForRetrieval, null)); + } + } + enrichedServiceTags = new EnrichedServiceTags(serviceTags, resourceMatchers, serviceResourceTrie); + } + } + } + + private void processServiceTagDeltas(ServiceTags deltas, ServiceTags allServiceTags, Map> serviceResourceTrie) { + if (LOG.isDebugEnabled()) { + LOG.debug("Delta contains changes other than tag attribute changes, [" + deltas.getTagsChangeExtent() + "]"); + } + + boolean isInError = false; + + ResourceHierarchies hierarchies = new ResourceHierarchies(); + List resourceMatchers = new ArrayList<>(); + + if (enrichedServiceTags != null) { + resourceMatchers.addAll(enrichedServiceTags.getServiceResourceMatchers()); + } + + List changedServiceResources = deltas.getServiceResources(); + + for (RangerServiceResource serviceResource : changedServiceResources) { + + final boolean removedOldServiceResource = MapUtils.isEmpty(serviceResource.getResourceElements()) || removeOldServiceResource(serviceResource, resourceMatchers, serviceResourceTrie); + if (removedOldServiceResource) { + + if (!StringUtils.isEmpty(serviceResource.getResourceSignature())) { + + RangerServiceResourceMatcher resourceMatcher = createRangerServiceResourceMatcher(serviceResource, serviceDefHelper, hierarchies); + + if (resourceMatcher != null) { + for (RangerServiceDef.RangerResourceDef resourceDef : serviceDef.getResources()) { + + RangerResourceTrie trie = serviceResourceTrie.get(resourceDef.getName()); + + if (trie != null) { + trie.add(serviceResource.getResourceElements().get(resourceDef.getName()), resourceMatcher); + if (LOG.isDebugEnabled()) { + LOG.debug("Added resource-matcher for service-resource:[" + serviceResource + "]"); + } + } else { + trie = new RangerResourceTrie<>(resourceDef, Collections.singletonList(resourceMatcher)); + serviceResourceTrie.put(resourceDef.getName(), trie); + } + } + resourceMatchers.add(resourceMatcher); + } else { + LOG.error("Could not create resource-matcher for resource: [" + serviceResource + "]. Should NOT happen!!"); + LOG.error("Setting tagVersion to -1 to ensure that in the next download all tags are downloaded"); + isInError = true; + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Service-resource:[id=" + serviceResource.getId() + "] is deleted as its resource-signature is empty. No need to create it!"); + } + } + } else { + isInError = true; + } + if (isInError) { + break; + } + } + if (isInError) { + LOG.error("Error in processing tag-deltas. Will continue to use old tags"); + deltas.setTagVersion(-1L); + } else { + for (Map.Entry> entry : serviceResourceTrie.entrySet()) { + entry.getValue().wrapUpUpdate(); + } + enrichedServiceTags = new EnrichedServiceTags(allServiceTags, resourceMatchers, serviceResourceTrie); + } + + } + + private boolean removeOldServiceResource(RangerServiceResource serviceResource, List resourceMatchers, Map> resourceTries) { + boolean ret = true; + + if (enrichedServiceTags != null) { + + if (LOG.isDebugEnabled()) { + LOG.debug("Removing service-resource:[" + serviceResource + "] from trie-map"); + } + + // Remove existing serviceResource from the copy + + RangerAccessResourceImpl accessResource = new RangerAccessResourceImpl(); + + for (Map.Entry entry : serviceResource.getResourceElements().entrySet()) { + accessResource.setValue(entry.getKey(), entry.getValue()); + } + if (LOG.isDebugEnabled()) { + LOG.debug("RangerAccessResource:[" + accessResource + "] created to represent service-resource[" + serviceResource + "] to find evaluators from trie-map"); + } + + RangerAccessRequestImpl request = new RangerAccessRequestImpl(); + request.setResource(accessResource); + + List oldMatchers = getEvaluators(request, enrichedServiceTags); + + if (LOG.isDebugEnabled()) { + LOG.debug("Found [" + oldMatchers.size() + "] matchers for service-resource[" + serviceResource + "]"); + } + + for (RangerServiceResourceMatcher matcher : oldMatchers) { + + for (RangerServiceDef.RangerResourceDef resourceDef : serviceDef.getResources()) { + String resourceDefName = resourceDef.getName(); + + RangerResourceTrie trie = resourceTries.get(resourceDefName); + + if (trie != null) { + trie.delete(serviceResource.getResourceElements().get(resourceDefName), matcher); + } else { + LOG.error("Cannot find resourceDef with name:[" + resourceDefName + "]. Should NOT happen!!"); + LOG.error("Setting tagVersion to -1 to ensure that in the next download all tags are downloaded"); + ret = false; + break; + } + } + } + + // Remove old resource matchers + if (ret) { + resourceMatchers.removeAll(oldMatchers); + + if (LOG.isDebugEnabled()) { + LOG.debug("Found and removed [" + oldMatchers.size() + "] matchers for service-resource[" + serviceResource + "] from trie-map"); + } + } + } + return ret; + } + + static public RangerServiceResourceMatcher createRangerServiceResourceMatcher(RangerServiceResource serviceResource, RangerServiceDefHelper serviceDefHelper, ResourceHierarchies hierarchies) { + + if (LOG.isDebugEnabled()) { + LOG.debug("==> createRangerServiceResourceMatcher(serviceResource=" + serviceResource + ")"); + } + + RangerServiceResourceMatcher ret = null; + + final Collection resourceKeys = serviceResource.getResourceElements().keySet(); + + for (String policyType : RangerPolicy.POLICY_TYPES) { + Boolean isValidHierarchy = hierarchies.isValidHierarchy(policyType, resourceKeys); + if (isValidHierarchy == null) { // hierarchy not yet validated + isValidHierarchy = Boolean.FALSE; + + for (List hierarchy : serviceDefHelper.getResourceHierarchies(policyType)) { + if (serviceDefHelper.hierarchyHasAllResources(hierarchy, resourceKeys)) { + isValidHierarchy = Boolean.TRUE; + + break; + } + } + + hierarchies.addHierarchy(policyType, resourceKeys, isValidHierarchy); + } + + if (isValidHierarchy) { + RangerDefaultPolicyResourceMatcher matcher = new RangerDefaultPolicyResourceMatcher(); + + matcher.setServiceDef(serviceDefHelper.getServiceDef()); + matcher.setPolicyResources(serviceResource.getResourceElements(), policyType); + + if (LOG.isDebugEnabled()) { + LOG.debug("RangerTagEnricher.setServiceTags() - Initializing matcher with (resource=" + serviceResource + + ", serviceDef=" + serviceDefHelper.getServiceDef() + ")"); + + } + matcher.setServiceDefHelper(serviceDefHelper); + matcher.init(); + + ret = new RangerServiceResourceMatcher(serviceResource, matcher); + break; + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== createRangerServiceResourceMatcher(serviceResource=" + serviceResource + ") : [" + ret + "]"); + } + return ret; + + } + + private void setEnrichedServiceTagsInPlugin() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> setEnrichedServiceTagsInPlugin()"); + } + + RangerAuthContext authContext = getAuthContext(); + + if (authContext != null) { + authContext.addOrReplaceRequestContextEnricher(this, enrichedServiceTags); + + notifyAuthContextChanged(); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== setEnrichedServiceTagsInPlugin()"); + } + } + + private Set findMatchingTags(final RangerAccessRequest request, EnrichedServiceTags dataStore) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagEnricher.findMatchingTags(" + request + ")"); + } + + // To minimize chance for race condition between Tag-Refresher thread and access-evaluation thread + final EnrichedServiceTags enrichedServiceTags = dataStore != null ? dataStore : this.enrichedServiceTags; + + Set ret = null; + + RangerAccessResource resource = request.getResource(); + + if ((resource == null || resource.getKeys() == null || resource.getKeys().isEmpty()) && request.isAccessTypeAny()) { + ret = enrichedServiceTags.getTagsForEmptyResourceAndAnyAccess(); + } else { + + final List serviceResourceMatchers = getEvaluators(request, enrichedServiceTags); + + if (CollectionUtils.isNotEmpty(serviceResourceMatchers)) { + + for (RangerServiceResourceMatcher resourceMatcher : serviceResourceMatchers) { + + final RangerPolicyResourceMatcher.MatchType matchType = resourceMatcher.getMatchType(resource, request.getContext()); + + final boolean isMatched; + + if (request.isAccessTypeAny()) { + isMatched = matchType != RangerPolicyResourceMatcher.MatchType.NONE; + } else if (request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS) { + isMatched = matchType != RangerPolicyResourceMatcher.MatchType.NONE; + } else { + isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.ANCESTOR; + } + + if (isMatched) { + if (ret == null) { + ret = new HashSet<>(); + } + ret.addAll(getTagsForServiceResource(request.getAccessTime(), enrichedServiceTags.getServiceTags(), resourceMatcher.getServiceResource(), matchType)); + } + + } + } + } + + if (CollectionUtils.isEmpty(ret)) { + if (LOG.isDebugEnabled()) { + LOG.debug("RangerTagEnricher.findMatchingTags(" + resource + ") - No tags Found "); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("RangerTagEnricher.findMatchingTags(" + resource + ") - " + ret.size() + " tags Found "); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagEnricher.findMatchingTags(" + request + ")"); + } + + return ret; + } + + private List getEvaluators(RangerAccessRequest request, EnrichedServiceTags enrichedServiceTags) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagEnricher.getEvaluators(request=" + request + ")"); + } + List ret = Collections.EMPTY_LIST; + + RangerAccessResource resource = request.getResource(); + + final Map> serviceResourceTrie = enrichedServiceTags.getServiceResourceTrie(); + + if (resource == null || resource.getKeys() == null || resource.getKeys().isEmpty() || serviceResourceTrie == null) { + ret = enrichedServiceTags.getServiceResourceMatchers(); + } else { + RangerPerfTracer perf = null; + + if (RangerPerfTracer.isPerfTraceEnabled(PERF_TRIE_OP_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_TRIE_OP_LOG, "RangerTagEnricher.getEvaluators(resource=" + resource.getAsString() + ")"); + } + + List resourceKeys = serviceDefHelper.getOrderedResourceNames(resource.getKeys()); + Set smallestList = null; + + if (CollectionUtils.isNotEmpty(resourceKeys)) { + + for (String resourceName : resourceKeys) { + RangerResourceTrie trie = serviceResourceTrie.get(resourceName); + + if (trie == null) { // if no trie exists for this resource level, ignore and continue to next level + continue; + } + + Set serviceResourceMatchersForResource = trie.getEvaluatorsForResource(resource.getValue(resourceName), request.getResourceMatchingScope()); + Set inheritedResourceMatchers = trie.getInheritedEvaluators(); + + if (smallestList != null) { + if (CollectionUtils.isEmpty(inheritedResourceMatchers) && CollectionUtils.isEmpty(serviceResourceMatchersForResource)) { + smallestList = null; + } else if (CollectionUtils.isEmpty(inheritedResourceMatchers)) { + smallestList.retainAll(serviceResourceMatchersForResource); + } else if (CollectionUtils.isEmpty(serviceResourceMatchersForResource)) { + smallestList.retainAll(inheritedResourceMatchers); + } else { + Set smaller, bigger; + if (serviceResourceMatchersForResource.size() < inheritedResourceMatchers.size()) { + smaller = serviceResourceMatchersForResource; + bigger = inheritedResourceMatchers; + } else { + smaller = inheritedResourceMatchers; + bigger = serviceResourceMatchersForResource; + } + Set tmp = new HashSet<>(); + if (smallestList.size() < smaller.size()) { + smallestList.stream().filter(smaller::contains).forEach(tmp::add); + smallestList.stream().filter(bigger::contains).forEach(tmp::add); + } else { + smaller.stream().filter(smallestList::contains).forEach(tmp::add); + if (smallestList.size() < bigger.size()) { + smallestList.stream().filter(bigger::contains).forEach(tmp::add); + } else { + bigger.stream().filter(smallestList::contains).forEach(tmp::add); + } + } + smallestList = tmp; + } + } else { + if (CollectionUtils.isEmpty(inheritedResourceMatchers) || CollectionUtils.isEmpty(serviceResourceMatchersForResource)) { + Set tmp = CollectionUtils.isEmpty(inheritedResourceMatchers) ? serviceResourceMatchersForResource : inheritedResourceMatchers; + smallestList = resourceKeys.size() == 1 || CollectionUtils.isEmpty(tmp) ? tmp : new HashSet<>(tmp); + } else { + smallestList = new HashSet<>(serviceResourceMatchersForResource); + smallestList.addAll(inheritedResourceMatchers); + } + } + + if (CollectionUtils.isEmpty(smallestList)) {// no tags for this resource, bail out + smallestList = null; + break; + } + } + } + + if (smallestList != null) { + ret = new ArrayList<>(smallestList); + } + + RangerPerfTracer.logAlways(perf); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagEnricher.getEvaluators(request=" + request + "): evaluatorCount=" + ret.size()); + } + + return ret; + } + + private static Set getTagsForServiceResource(Date accessTime, final ServiceTags serviceTags, final RangerServiceResource serviceResource, final RangerPolicyResourceMatcher.MatchType matchType) { + Set ret = new HashSet<>(); + + final Long resourceId = serviceResource.getId(); + final Map> resourceToTagIds = serviceTags.getResourceToTagIds(); + final Map tags = serviceTags.getTags(); + + if (LOG.isDebugEnabled()) { + LOG.debug("Looking for tags for resource-id:[" + resourceId + "] in serviceTags:[" + serviceTags + "]"); + } + + if (resourceId != null && MapUtils.isNotEmpty(resourceToTagIds) && MapUtils.isNotEmpty(tags)) { + + List tagIds = resourceToTagIds.get(resourceId); + + if (CollectionUtils.isNotEmpty(tagIds)) { + + accessTime = accessTime == null ? new Date() : accessTime; + + for (Long tagId : tagIds) { + + RangerTag tag = tags.get(tagId); + + if (tag != null) { + RangerTagForEval tagForEval = new RangerTagForEval(tag, matchType); + if (tagForEval.isApplicable(accessTime)) { + ret.add(tagForEval); + } + } + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("No tags mapping found for resource:[" + resourceId + "]"); + } + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("resourceId is null or resourceToTagTds mapping is null or tags mapping is null!"); + } + } + + return ret; + } + + private Map> copyServiceResourceTrie() { + Map> ret = new HashMap<>(); + + if (enrichedServiceTags != null) { + for (Map.Entry> entry : enrichedServiceTags.getServiceResourceTrie().entrySet()) { + RangerResourceTrie resourceTrie = new RangerResourceTrie<>(entry.getValue()); + ret.put(entry.getKey(), resourceTrie); + } + } + return ret; + } + + static public final class EnrichedServiceTags { + final private ServiceTags serviceTags; + final private List serviceResourceMatchers; + final private Map> serviceResourceTrie; + final private Set tagsForEmptyResourceAndAnyAccess; // Used only when accessed resource is empty and access type is 'any' + final private Long resourceTrieVersion; + + EnrichedServiceTags(ServiceTags serviceTags, List serviceResourceMatchers, Map> serviceResourceTrie) { + this.serviceTags = serviceTags; + this.serviceResourceMatchers = serviceResourceMatchers; + this.serviceResourceTrie = serviceResourceTrie; + this.tagsForEmptyResourceAndAnyAccess = createTagsForEmptyResourceAndAnyAccess(); + this.resourceTrieVersion = serviceTags.getTagVersion(); + } + public ServiceTags getServiceTags() {return serviceTags;} + public List getServiceResourceMatchers() { return serviceResourceMatchers;} + public Map> getServiceResourceTrie() { return serviceResourceTrie;} + public Long getResourceTrieVersion() { return resourceTrieVersion;} + public Set getTagsForEmptyResourceAndAnyAccess() { return tagsForEmptyResourceAndAnyAccess;} + + private Set createTagsForEmptyResourceAndAnyAccess() { + Set tagsForEmptyResourceAndAnyAccess = new HashSet<>(); + for (Map.Entry entry : serviceTags.getTags().entrySet()) { + tagsForEmptyResourceAndAnyAccess.add(new RangerTagForEval(entry.getValue(), RangerPolicyResourceMatcher.MatchType.DESCENDANT)); + } + return tagsForEmptyResourceAndAnyAccess; + } + } + + static class RangerTagRefresher extends Thread { + private static final Log LOG = LogFactory.getLog(RangerTagRefresher.class); + + private final RangerTagRetriever tagRetriever; + private final RangerTagEnricher tagEnricher; + private long lastKnownVersion; + private final BlockingQueue tagDownloadQueue; + private long lastActivationTimeInMillis; + + private final String cacheFile; + private boolean hasProvidedTagsToReceiver; + private Gson gson; + + RangerTagRefresher(RangerTagRetriever tagRetriever, RangerTagEnricher tagEnricher, long lastKnownVersion, BlockingQueue tagDownloadQueue, String cacheFile) { + this.tagRetriever = tagRetriever; + this.tagEnricher = tagEnricher; + this.lastKnownVersion = lastKnownVersion; + this.tagDownloadQueue = tagDownloadQueue; + this.cacheFile = cacheFile; + try { + gson = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z").create(); + } catch(Throwable excp) { + LOG.fatal("failed to create GsonBuilder object", excp); + } + setName("RangerTagRefresher(serviceName=" + tagRetriever.getServiceName() + ")-" + getId()); + } + + public long getLastActivationTimeInMillis() { + return lastActivationTimeInMillis; + } + + public void setLastActivationTimeInMillis(long lastActivationTimeInMillis) { + this.lastActivationTimeInMillis = lastActivationTimeInMillis; + } + + @Override + public void run() { + + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagRefresher().run()"); + } + + while (true) { + DownloadTrigger trigger = null; + + try { + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_CONTEXTENRICHER_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_CONTEXTENRICHER_INIT_LOG, "RangerTagRefresher(" + getName() + ").populateTags(lastKnownVersion=" + lastKnownVersion + ")"); + } + trigger = tagDownloadQueue.take(); + populateTags(); + + RangerPerfTracer.log(perf); + + } catch (InterruptedException excp) { + LOG.info("RangerTagRefresher(" + getName() + ").run(): Interrupted! Exiting thread", excp); + break; + } finally { + if (trigger != null) { + trigger.signalCompletion(); + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagRefresher().run()"); + } + } + + private void populateTags() throws InterruptedException { + + if (tagEnricher != null) { + ServiceTags serviceTags; + + try { + serviceTags = tagRetriever.retrieveTags(lastKnownVersion, lastActivationTimeInMillis); + + if (serviceTags == null) { + if (!hasProvidedTagsToReceiver) { + serviceTags = loadFromCache(); + } + } else if (!serviceTags.getIsDelta()) { + saveToCache(serviceTags); + } + + if (serviceTags != null) { + tagEnricher.setServiceTags(serviceTags); + if (serviceTags.getIsDelta() && serviceTags.getTagVersion() != -1L) { + saveToCache(tagEnricher.enrichedServiceTags.serviceTags); + } + LOG.info("RangerTagRefresher(serviceName=" + tagRetriever.getServiceName() + ").populateTags() - Updated tags-cache to new version of tags, lastKnownVersion=" + lastKnownVersion + "; newVersion=" + + (serviceTags.getTagVersion() == null ? -1L : serviceTags.getTagVersion())); + hasProvidedTagsToReceiver = true; + lastKnownVersion = serviceTags.getTagVersion() == null ? -1L : serviceTags.getTagVersion(); + setLastActivationTimeInMillis(System.currentTimeMillis()); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("RangerTagRefresher(serviceName=" + tagRetriever.getServiceName() + ").populateTags() - No need to update tags-cache. lastKnownVersion=" + lastKnownVersion); + } + } + } catch (RangerServiceNotFoundException snfe) { + LOG.error("Caught ServiceNotFound exception :", snfe); + + // Need to clean up local tag cache + if (tagEnricher.disableCacheIfServiceNotFound) { + disableCache(); + tagEnricher.setServiceTags(null); + setLastActivationTimeInMillis(System.currentTimeMillis()); + lastKnownVersion = -1L; + } + } catch (InterruptedException interruptedException) { + throw interruptedException; + } catch (Exception e) { + LOG.error("RangerTagRefresher(serviceName=" + tagRetriever.getServiceName() + ").populateTags(): Encountered unexpected exception. Ignoring", e); + } + + } else { + LOG.error("RangerTagRefresher(serviceName=" + tagRetriever.getServiceName() + ".populateTags() - no tag receiver to update tag-cache"); + } + } + + void cleanup() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagRefresher.cleanup()"); + } + + stopRefresher(); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagRefresher.cleanup()"); + } + } + + final void startRefresher() { + try { + super.start(); + } catch (Exception excp) { + LOG.error("RangerTagRefresher(" + getName() + ").startRetriever(): Failed to start, exception=" + excp); + } + } + + private void stopRefresher() { + + if (super.isAlive()) { + super.interrupt(); + + boolean setInterrupted = false; + boolean isJoined = false; + + while (!isJoined) { + try { + super.join(); + isJoined = true; + } catch (InterruptedException excp) { + LOG.warn("RangerTagRefresher(" + getName() + ").stopRefresher(): Error while waiting for thread to exit", excp); + LOG.warn("Retrying Thread.join(). Current thread will be marked as 'interrupted' after Thread.join() returns"); + setInterrupted = true; + } + } + if (setInterrupted) { + Thread.currentThread().interrupt(); + } + } + } + + + final ServiceTags loadFromCache() { + ServiceTags serviceTags = null; + + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagRetriever(serviceName=" + tagEnricher.getServiceName() + ").loadFromCache()"); + } + + File cacheFile = StringUtils.isEmpty(this.cacheFile) ? null : new File(this.cacheFile); + + if (cacheFile != null && cacheFile.isFile() && cacheFile.canRead()) { + Reader reader = null; + + try { + reader = new FileReader(cacheFile); + + serviceTags = gson.fromJson(reader, ServiceTags.class); + + if (serviceTags != null && !StringUtils.equals(tagEnricher.getServiceName(), serviceTags.getServiceName())) { + LOG.warn("ignoring unexpected serviceName '" + serviceTags.getServiceName() + "' in cache file '" + cacheFile.getAbsolutePath() + "'"); + + serviceTags.setServiceName(tagEnricher.getServiceName()); + } + } catch (Exception excp) { + LOG.error("failed to load service-tags from cache file " + cacheFile.getAbsolutePath(), excp); + } finally { + if (reader != null) { + try { + reader.close(); + } catch (Exception excp) { + LOG.error("error while closing opened cache file " + cacheFile.getAbsolutePath(), excp); + } + } + } + } else { + LOG.warn("cache file does not exist or not readable '" + (cacheFile == null ? null : cacheFile.getAbsolutePath()) + "'"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagRetriever(serviceName=" + tagEnricher.getServiceName() + ").loadFromCache()"); + } + + return serviceTags; + } + + final void saveToCache(ServiceTags serviceTags) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagRetriever(serviceName=" + tagEnricher.getServiceName() + ").saveToCache()"); + } + + if (serviceTags != null) { + File cacheFile = StringUtils.isEmpty(this.cacheFile) ? null : new File(this.cacheFile); + + if (cacheFile != null) { + Writer writer = null; + + try { + writer = new FileWriter(cacheFile); + + gson.toJson(serviceTags, writer); + } catch (Exception excp) { + LOG.error("failed to save service-tags to cache file '" + cacheFile.getAbsolutePath() + "'", excp); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (Exception excp) { + LOG.error("error while closing opened cache file '" + cacheFile.getAbsolutePath() + "'", excp); + } + } + } + } + } else { + LOG.info("service-tags is null for service=" + tagRetriever.getServiceName() + ". Nothing to save in cache"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagRetriever(serviceName=" + tagEnricher.getServiceName() + ").saveToCache()"); + } + } + + final void disableCache() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagRetriever.disableCache(serviceName=" + tagEnricher.getServiceName() + ")"); + } + + File cacheFile = StringUtils.isEmpty(this.cacheFile) ? null : new File(this.cacheFile); + if (cacheFile != null && cacheFile.isFile() && cacheFile.canRead()) { + LOG.warn("Cleaning up local tags cache"); + String renamedCacheFile = cacheFile.getAbsolutePath() + "_" + System.currentTimeMillis(); + if (!cacheFile.renameTo(new File(renamedCacheFile))) { + LOG.error("Failed to move " + cacheFile.getAbsolutePath() + " to " + renamedCacheFile); + } else { + LOG.warn("moved " + cacheFile.getAbsolutePath() + " to " + renamedCacheFile); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("No local TAGS cache found. No need to disable it!"); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagRetriever.disableCache(serviceName=" + tagEnricher.getServiceName() + ")"); + } + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerTagForEval.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerTagForEval.java new file mode 100644 index 00000000000..3cec7dd8bc2 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerTagForEval.java @@ -0,0 +1,239 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.contextenricher; + +import org.apache.atlas.authorization.utils.RangerUtil; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.model.RangerTag; +import org.apache.atlas.plugin.model.RangerValiditySchedule; +import org.apache.atlas.plugin.policyevaluator.RangerValidityScheduleEvaluator; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; + +@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY) +@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown=true) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) + +// This class needs above annotations for policy-engine unit tests involving RangerTagForEval objects that are initialized +// from JSON specification + +public class RangerTagForEval implements Serializable { + private static final Log LOG = LogFactory.getLog(RangerTagForEval.class); + + private String type; + private Map attributes; + private Map options; + private RangerPolicyResourceMatcher.MatchType matchType = RangerPolicyResourceMatcher.MatchType.SELF; + @JsonIgnore + private List validityPeriods; + @JsonIgnore + private transient List validityPeriodEvaluators; + + + private RangerTagForEval() {} + + public RangerTagForEval(RangerTag tag, RangerPolicyResourceMatcher.MatchType matchType) { + this.type = tag.getType(); + this.attributes = tag.getAttributes(); + this.options = tag.getOptions(); + this.matchType = matchType; + this.validityPeriods = tag.getValidityPeriods(); + + this.validityPeriodEvaluators = createValidityPeriodEvaluators(); + } + + public String getType() { return type;} + + public Map getAttributes() { return attributes; } + + public Map getOptions() { return options; } + + public RangerPolicyResourceMatcher.MatchType getMatchType() { return matchType; } + + public List getValidityPeriods() { return validityPeriods; } + + public boolean isApplicable(Date accessTime) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerTagForEval.isApplicable(type=" + type + ", " + accessTime + ")"); + } + + boolean ret = false; + + List validityPeriodEvaluators = this.validityPeriodEvaluators; + + // Specifically for unit-testing using TestPolicyEngine + if (MapUtils.isNotEmpty(options) && CollectionUtils.isEmpty(validityPeriodEvaluators)) { + Object value = getOption(RangerTag.OPTION_TAG_VALIDITY_PERIODS); + + if (value != null && value instanceof String) { + this.validityPeriods = RangerUtil.jsonToRangerValiditySchedule((String) value); + + validityPeriodEvaluators = createValidityPeriodEvaluators(); + } else { + validityPeriodEvaluators = Collections.emptyList(); + } + + this.validityPeriodEvaluators = validityPeriodEvaluators; + } + + if (accessTime != null && CollectionUtils.isNotEmpty(validityPeriodEvaluators)) { + for (RangerValidityScheduleEvaluator evaluator : validityPeriodEvaluators) { + if (evaluator.isApplicable(accessTime.getTime())) { + ret = true; + break; + } + } + } else { + ret = true; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerTagForEval.isApplicable(type=" + type + ", " + accessTime + ") : " + ret); + } + + return ret; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerTagForEval={ "); + sb.append("type=" ).append(type); + sb.append(", attributes={ "); + if (attributes != null) { + for (Map.Entry entry : attributes.entrySet()) { + sb.append('"').append(entry.getKey()).append("\":\"").append(entry.getValue()).append("\", "); + } + } + sb.append(" }"); + sb.append(", matchType=").append(matchType); + + if (options != null) { + sb.append(", options={").append(options).append("}"); + } + + if (validityPeriods != null) { + sb.append(", validityPeriods=").append(validityPeriods); + } + sb.append(" }"); + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((type == null) ? 0 : type.hashCode()); + result = prime * result + + ((attributes == null) ? 0 : attributes.hashCode()); + result = prime * result + + ((matchType == null) ? 0 : matchType.hashCode()); + result = prime * result + + ((validityPeriods == null) ? 0 : validityPeriods.hashCode()); + result = prime * result + + ((options == null) ? 0 : options.hashCode()); + + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerTagForEval other = (RangerTagForEval) obj; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + if (attributes == null) { + if (other.attributes != null) + return false; + } else if (!attributes.equals(other.attributes)) + return false; + if (matchType == null) { + if (other.matchType != null) + return false; + } else if (!matchType.equals(other.matchType)) + return false; + if (options == null) { + if (other.options != null) + return false; + } else if (!options.equals(other.options)) + return false; + if (validityPeriods == null) { + if (other.validityPeriods != null) + return false; + } else if (!validityPeriods.equals(other.validityPeriods)) + return false; + + return true; + } + + private Object getOption(String name) { + return options != null ? options.get(name) : null; + } + + private List createValidityPeriodEvaluators() { + final List ret; + + if (CollectionUtils.isNotEmpty(validityPeriods)) { + ret = new ArrayList<>(); + + for (RangerValiditySchedule schedule : validityPeriods) { + ret.add(new RangerValidityScheduleEvaluator(schedule)); + } + } else { + ret = Collections.emptyList(); + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerTagRetriever.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerTagRetriever.java new file mode 100644 index 00000000000..7f549ffcadc --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/contextenricher/RangerTagRetriever.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.contextenricher; + +import org.apache.atlas.authorization.config.RangerPluginConfig; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.policyengine.RangerPluginContext; +import org.apache.atlas.plugin.util.ServiceTags; + +import java.util.Map; + +public abstract class RangerTagRetriever { + + protected String serviceName; + protected RangerServiceDef serviceDef; + protected String appId; + protected RangerPluginConfig pluginConfig; + protected RangerPluginContext pluginContext; + + public abstract void init(Map options); + + public abstract ServiceTags retrieveTags(long lastKnownVersion, long lastActivationTimeInMillis) throws Exception; + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public RangerServiceDef getServiceDef() { + return serviceDef; + } + + public void setServiceDef(RangerServiceDef serviceDef) { + this.serviceDef = serviceDef; + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public void setPluginConfig(RangerPluginConfig pluginConfig) { this.pluginConfig = pluginConfig; } + + public RangerPluginContext getPluginContext() { + return pluginContext; + } + + public void setPluginContext(RangerPluginContext pluginContext) { + this.pluginContext = pluginContext; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/errors/ValidationErrorCode.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/errors/ValidationErrorCode.java new file mode 100644 index 00000000000..3bcaf7332d4 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/errors/ValidationErrorCode.java @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.errors; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.text.MessageFormat; +import java.util.Arrays; + +public enum ValidationErrorCode { + // SERVICE VALIDATION + SERVICE_VALIDATION_ERR_UNSUPPORTED_ACTION(1001, "Internal error: unsupported action[{0}]; isValid(Long) is only supported for DELETE"), + SERVICE_VALIDATION_ERR_MISSING_FIELD(1002, "Internal error: missing field[{0}]"), + SERVICE_VALIDATION_ERR_NULL_SERVICE_OBJECT(1003, "Internal error: service object passed in was null"), + SERVICE_VALIDATION_ERR_EMPTY_SERVICE_ID(1004, "Internal error: service id was null/empty/blank"), + SERVICE_VALIDATION_ERR_INVALID_SERVICE_ID(1005, "No service found for id [{0}]"), + SERVICE_VALIDATION_ERR_INVALID_SERVICE_NAME(1006, "Missing service name"), + SERVICE_VALIDATION_ERR_SERVICE_NAME_CONFICT(1007, "Duplicate service name: name=[{0}]"), + SERVICE_VALIDATION_ERR_SERVICE_DISPLAY_NAME_CONFICT(3051,"Display name [{0}] is already used by service [{1}]"), + SERVICE_VALIDATION_ERR_SPECIAL_CHARACTERS_SERVICE_NAME(3031, "Invalid service name=[{0}]. It should not be longer than 256 characters and special characters are not allowed (except underscore and hyphen)"), + SERVICE_VALIDATION_ERR_SPECIAL_CHARACTERS_SERVICE_DISPLAY_NAME(3050, "Invalid service display name [{0}]. It should not be longer than 256 characters, should not start with space, and should not include special characters (except underscore, hyphen and space)"), + SERVICE_VALIDATION_ERR_ID_NAME_CONFLICT(1008, "Duplicate service name: name=[{0}], id=[{1}]"), + SERVICE_VALIDATION_ERR_MISSING_SERVICE_DEF(1009, "Missing service def"), + SERVICE_VALIDATION_ERR_INVALID_SERVICE_DEF(1010, "Service def not found: service-def-name=[{0}]"), + SERVICE_VALIDATION_ERR_REQUIRED_PARM_MISSING(1011, "Missing required configuration parameter(s): missing parameters={0}"), + + // SERVICE-DEF VALIDATION + SERVICE_DEF_VALIDATION_ERR_UNSUPPORTED_ACTION(2001, "Internal error: unsupported action[{0}]; isValid(Long) is only supported for DELETE"), + SERVICE_DEF_VALIDATION_ERR_MISSING_FIELD(2002, "Internal error: missing field[{0}]"), + SERVICE_DEF_VALIDATION_ERR_NULL_SERVICE_DEF_OBJECT(2003, "Internal error: service def object passed in was null"), + SERVICE_DEF_VALIDATION_ERR_EMPTY_SERVICE_DEF_ID(2004, "Internal error: service def id was null/empty/blank"), + SERVICE_DEF_VALIDATION_ERR_INVALID_SERVICE_DEF_ID(2005, "No service def found for id [{0}]"), + SERVICE_DEF_VALIDATION_ERR_INVALID_SERVICE_DEF_NAME(2006, "Service def name[{0}] was null/empty/blank"), + SERVICE_DEF_VALIDATION_ERR_INVALID_SERVICE_DEF_DISPLAY_NAME(2024, "Service def display name[{0}] was null/empty/blank"), + SERVICE_DEF_VALIDATION_ERR_SERVICE_DEF_NAME_CONFICT(2007, "service def with the name[{0}] already exists"), + SERVICE_DEF_VALIDATION_ERR_SERVICE_DEF__DISPLAY_NAME_CONFICT(2025, "Display name [{0}] is already used by service def [{1}]"), + SERVICE_DEF_VALIDATION_ERR_ID_NAME_CONFLICT(2008, "id/name conflict: another service def already exists with name[{0}], its id is [{1}]"), + SERVICE_DEF_VALIDATION_ERR_IMPLIED_GRANT_UNKNOWN_ACCESS_TYPE(2009, "implied grant[{0}] contains an unknown access types[{1}]"), + SERVICE_DEF_VALIDATION_ERR_IMPLIED_GRANT_IMPLIES_ITSELF(2010, "implied grants list [{0}] for access type[{1}] contains itself"), + SERVICE_DEF_VALIDATION_ERR_POLICY_CONDITION_NULL_EVALUATOR(2011, "evaluator on policy condition definition[{0}] was null/empty!"), + SERVICE_DEF_VALIDATION_ERR_CONFIG_DEF_UNKNOWN_ENUM(2012, "subtype[{0}] of service def config[{1}] was not among defined enums[{2}]"), + SERVICE_DEF_VALIDATION_ERR_CONFIG_DEF_UNKNOWN_ENUM_VALUE(2013, "default value[{0}] of service def config[{1}] was not among the valid values[{2}] of enums[{3}]"), + SERVICE_DEF_VALIDATION_ERR_CONFIG_DEF_MISSING_TYPE(2014, "type of service def config[{0}] was null/empty"), + SERVICE_DEF_VALIDATION_ERR_CONFIG_DEF_INVALID_TYPE(2015, "type[{0}] of service def config[{1}] is not among valid types: {2}"), + SERVICE_DEF_VALIDATION_ERR_RESOURCE_GRAPH_INVALID(2016, "Resource graph implied by various resources, e.g. parent value is invalid. Valid graph must forest (union of disjoint trees)."), + SERVICE_DEF_VALIDATION_ERR_ENUM_DEF_NULL_OBJECT(2017, "Internal error: An enum def in enums collection is null"), + SERVICE_DEF_VALIDATION_ERR_ENUM_DEF_NO_VALUES(2018, "enum [{0}] does not have any elements"), + SERVICE_DEF_VALIDATION_ERR_ENUM_DEF_INVALID_DEFAULT_INDEX(2019, "default index[{0}] for enum [{1}] is invalid"), + SERVICE_DEF_VALIDATION_ERR_ENUM_DEF_NULL_ENUM_ELEMENT(2020, "An enum element in enum element collection of enum [{0}] is null"), + SERVICE_DEF_VALIDATION_ERR_INVALID_SERVICE_RESOURCE_LEVELS(2021, "Resource-def levels are not in increasing order in an hierarchy"), + SERVICE_DEF_VALIDATION_ERR_NOT_LOWERCASE_NAME(2022, "{0}:[{1}] Invalid resource name. Resource name should consist of only lowercase, hyphen or underscore characters"), + SERVICE_DEF_VALIDATION_ERR_INVALID_MANADORY_VALUE_FOR_SERVICE_RESOURCE(2023, "{0} cannot be mandatory because {1}(parent) is not mandatory"), + + // POLICY VALIDATION + POLICY_VALIDATION_ERR_UNSUPPORTED_ACTION(3001, "Internal error: method signature isValid(Long) is only supported for DELETE"), + POLICY_VALIDATION_ERR_MISSING_FIELD(3002, "Internal error: missing field[{0}]"), + POLICY_VALIDATION_ERR_NULL_POLICY_OBJECT(3003, "Internal error: policy object passed in was null"), + POLICY_VALIDATION_ERR_INVALID_POLICY_ID(3004, "No policy found for id[{0}]"), + POLICY_VALIDATION_ERR_POLICY_NAME_MULTIPLE_POLICIES_WITH_SAME_NAME(3005, "Internal error: multiple policies found with the name[{0}]"), + POLICY_VALIDATION_ERR_POLICY_NAME_CONFLICT(3006, "Another policy already exists for this name: policy-id=[{0}], service=[{1}]"), + POLICY_VALIDATION_ERR_INVALID_SERVICE_NAME(3007, "no service found with name[{0}]"), + POLICY_VALIDATION_ERR_MISSING_POLICY_ITEMS(3008, "at least one policy item must be specified if audit isn't enabled"), + POLICY_VALIDATION_ERR_MISSING_SERVICE_DEF(3009, "Internal error: Service def[{0}] of policy's service[{1}] does not exist!"), + POLICY_VALIDATION_ERR_DUPLICATE_POLICY_RESOURCE(3010, "Another policy already exists for matching resource: policy-name=[{0}], service=[{1}]"), + POLICY_VALIDATION_ERR_INVALID_RESOURCE_NO_COMPATIBLE_HIERARCHY(3011, "Invalid resources specified. {0} policy can specify values for one of the following resource sets: {1}"), + POLICY_VALIDATION_ERR_INVALID_RESOURCE_MISSING_MANDATORY(3012, "Invalid resources specified. {0} policy must specify values for one of the following resource sets: {1}"), + POLICY_VALIDATION_ERR_NULL_RESOURCE_DEF(3013, "Internal error: a resource-def on resource def collection of service-def[{0}] was null"), + POLICY_VALIDATION_ERR_MISSING_RESOURCE_DEF_NAME(3014, "Internal error: name of a resource-def on resource def collection of service-def[{0}] was null"), + POLICY_VALIDATION_ERR_EXCLUDES_NOT_SUPPORTED(3015, "Excludes option not supported: resource-name=[{0}]"), + POLICY_VALIDATION_ERR_EXCLUDES_REQUIRES_ADMIN(3016, "Insufficient permissions to create excludes policy"), + POLICY_VALIDATION_ERR_RECURSIVE_NOT_SUPPORTED(3017, "Recursive option not supported: resource-name=[{0}]."), + POLICY_VALIDATION_ERR_INVALID_RESOURCE_VALUE_REGEX(3018, "Invalid resource specified. A value of [{0}] is not valid for resource [{1}]"), + POLICY_VALIDATION_ERR_NULL_POLICY_ITEM(3019, "policy items object was null"), + POLICY_VALIDATION_ERR_MISSING_USER_AND_GROUPS(3020, "All of users, user-groups and roles collections on the policy item were null/empty"), + POLICY_VALIDATION_ERR_NULL_POLICY_ITEM_ACCESS(3021, "policy items access object was null"), + POLICY_VALIDATION_ERR_POLICY_ITEM_ACCESS_TYPE_INVALID(3022, "Invalid access type: access type=[{0}], valid access types=[{1}]"), + POLICY_VALIDATION_ERR_POLICY_ITEM_ACCESS_TYPE_DENY(3023, "Currently deny access types are not supported. Access type is set to deny."), + POLICY_VALIDATION_ERR_INVALID_RESOURCE_NO_COMPATIBLE_HIERARCHY_SINGLE(3024, "Invalid resources specified. {0} policy can specify values for the following resources: {1}"), + POLICY_VALIDATION_ERR_INVALID_RESOURCE_MISSING_MANDATORY_SINGLE(3025, "Invalid resources specified. {0} policy must specify values for the following resources: {1}"), + POLICY_VALIDATION_ERR_MISSING_RESOURCE_LIST(3026, "Resource list was empty or contains null. At least one resource must be specified"), + POLICY_VALIDATION_ERR_POLICY_UPDATE_MOVE_SERVICE_NOT_ALLOWED(3027, "attempt to move policy id={0} from service={1} to service={2} is not allowed"), + POLICY_VALIDATION_ERR_POLICY_TYPE_CHANGE_NOT_ALLOWED(3028, "attempt to change type of policy id={0} from type={1} to type={2} is not allowed"), + POLICY_VALIDATION_ERR_POLICY_INVALID_VALIDITY_SCHEDULE(3029, "Invalid validity schedule specification"), + POLICY_VALIDATION_ERR_POLICY_INVALID_PRIORITY(3030, "Invalid priority value"), + POLICY_VALIDATION_ERR_UPDATE_ZONE_NAME_NOT_ALLOWED(3032, "Update of Zone name from={0} to={1} in policy is not supported"), + POLICY_VALIDATION_ERR_NONEXISTANT_ZONE_NAME(3033, "Non-existent Zone name={0} in policy create"), + POLICY_VALIDATION_ERR_SERVICE_NOT_ASSOCIATED_TO_ZONE(3048, "Service name = {0} is not associated to Zone name = {1}"), + POLICY_VALIDATION_ERR_UNSUPPORTED_POLICY_ITEM_TYPE(3049, "Deny or deny-exceptions are not supported if policy has isDenyAllElse flag set to true"), + POLICY_VALIDATION_ERR_INVALID_SERVICE_TYPE(4009," Invalid service type [{0}] provided for service [{1}]"), + + // SECURITY_ZONE Validations + SECURITY_ZONE_VALIDATION_ERR_UNSUPPORTED_ACTION(3034, "Internal error: unsupported action[{0}]; isValid() is only supported for DELETE"), + SECURITY_ZONE_VALIDATION_ERR_MISSING_FIELD(3035, "Internal error: missing field[{0}]"), + SECURITY_ZONE_VALIDATION_ERR_ZONE_NAME_CONFLICT(3036, "Another security zone already exists for this name: zone-id=[{0}]]"), + SECURITY_ZONE_VALIDATION_ERR_INVALID_ZONE_ID(3037, "No security zone found for [{0}]"), + SECURITY_ZONE_VALIDATION_ERR_MISSING_USER_AND_GROUPS(3038, "both users and user-groups collections for the security zone were null/empty"), + SECURITY_ZONE_VALIDATION_ERR_MISSING_RESOURCES(3039, "No resources specified for service [{0}]"), + SECURITY_ZONE_VALIDATION_ERR_INVALID_SERVICE_NAME(3040, "Invalid service [{0}]"), + SECURITY_ZONE_VALIDATION_ERR_INVALID_SERVICE_TYPE(3041, "Invalid service-type [{0}]"), + SECURITY_ZONE_VALIDATION_ERR_INVALID_RESOURCE_HIERARCHY(3042, "Invalid resource hierarchy specified for service:[{0}], resource-hierarchy:[{1}]"), + SECURITY_ZONE_VALIDATION_ERR_ALL_WILDCARD_RESOURCE_VALUES(3043, "All wildcard values specified for resources for service:[{0}]"), + SECURITY_ZONE_VALIDATION_ERR_MISSING_SERVICES(3044, "No services specified for security-zone:[{0}]"), + SECURITY_ZONE_VALIDATION_ERR_INTERNAL_ERROR(3045, "Internal Error:[{0}]"), + SECURITY_ZONE_VALIDATION_ERR_ZONE_RESOURCE_CONFLICT(3046, "Multiple zones:[{0}] match resource:[{1}]"), + SECURITY_ZONE_VALIDATION_ERR_UNEXPECTED_RESOURCES(3047, "Tag service [{0}], with non-empty resources, is associated with security zone"), + + //RANGER ROLE Validations + ROLE_VALIDATION_ERR_NULL_RANGER_ROLE_OBJECT(4001, "Internal error: RangerRole object passed in was null"), + ROLE_VALIDATION_ERR_MISSING_FIELD(4002, "Internal error: missing field[{0}]"), + ROLE_VALIDATION_ERR_NULL_RANGER_ROLE_NAME(4003, "Internal error: RangerRole name passed in was null/empty"), + ROLE_VALIDATION_ERR_MISSING_USER_OR_GROUPS_OR_ROLES(4004, "RangerRole should contain atleast one user or group or role"), + ROLE_VALIDATION_ERR_ROLE_NAME_CONFLICT(4005, "Another RangerRole already exists for this name: Role =[{0}]]"), + ROLE_VALIDATION_ERR_INVALID_ROLE_ID(4006, "No RangerRole found for id[{0}]"), + ROLE_VALIDATION_ERR_INVALID_ROLE_NAME(4007, "No RangerRole found for name[{0}]"), + ROLE_VALIDATION_ERR_UNSUPPORTED_ACTION(4008, "Internal error: method signature isValid(Long) is only supported for DELETE"), + + + ; + + + private static final Log LOG = LogFactory.getLog(ValidationErrorCode.class); + + final int _errorCode; + final String _template; + + ValidationErrorCode(int errorCode, String template) { + _errorCode = errorCode; + _template = template; + } + + public String getMessage(Object... items) { + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("<== ValidationErrorCode.getMessage(%s)", Arrays.toString(items))); + } + + MessageFormat mf = new MessageFormat(_template); + String result = mf.format(items); + + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("<== ValidationErrorCode.getMessage(%s): %s", Arrays.toString(items), result)); + } + return result; + } + + public int getErrorCode() { + return _errorCode; + } + + @Override + public String toString() { + return String.format("Code: %d, template: %s", _errorCode, _template); + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/BinarySearchTree.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/BinarySearchTree.java new file mode 100644 index 00000000000..bfd49526c9d --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/BinarySearchTree.java @@ -0,0 +1,222 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.geo; + +public class BinarySearchTree & RangeChecker, V> { + private Node root; + private int size; + + public BinarySearchTree() { + root = null; + } + + public void insert(final T value) { + Node node = new Node(value); + + if (root == null) { + root = node; + return; + } + + Node focusNode = root; + Node parent; + + while (true) { + parent = focusNode; + + int comparison = focusNode.getValue().compareTo(value); + if (comparison == 0) { + return; + } + if (comparison < 0) { + focusNode = focusNode.getRight(); + if (focusNode == null) { + parent.setRight(node); + return; + } + } else { + focusNode = focusNode.getLeft(); + if (focusNode == null) { + parent.setLeft(node); + return; + } + } + } + } + + public T find(final V value) { + Node focusNode = root; + + int rangeCheck; + + while (focusNode != null) { + rangeCheck = focusNode.getValue().compareToRange(value); + if (rangeCheck == 0) { + break; + } else if (rangeCheck < 0) { + focusNode = focusNode.getRight(); + } else { + focusNode = focusNode.getLeft(); + } + } + + return focusNode == null ? null : focusNode.getValue(); + } + + final public void preOrderTraverseTree(final ValueProcessor processor) { + preOrderTraverseTree(getRoot(), processor); + } + + final public void inOrderTraverseTree(final ValueProcessor processor) { + inOrderTraverseTree(getRoot(), processor); + } + + Node getRoot() { + return root; + } + + void setRoot(final Node newRoot) { + root = newRoot; + } + + void rebalance() { + Node dummy = new Node(null); + dummy.setRight(root); + + setRoot(dummy); + + degenerate(); + reconstruct(); + + setRoot(getRoot().getRight()); + } + + final void inOrderTraverseTree(final Node focusNode, final ValueProcessor processor) { + if (focusNode != null) { + inOrderTraverseTree(focusNode.getLeft(), processor); + processor.process(focusNode.getValue()); + inOrderTraverseTree(focusNode.getRight(), processor); + } + } + + final void preOrderTraverseTree(final Node focusNode, final ValueProcessor processor) { + if (focusNode != null) { + processor.process(focusNode.getValue()); + + preOrderTraverseTree(focusNode.getLeft(), processor); + preOrderTraverseTree(focusNode.getRight(), processor); + } + } + + private void degenerate() { + + Node remainder, temp, sentinel; + + sentinel = getRoot(); + remainder = sentinel.getRight(); + + size = 0; + + while (remainder != null) { + if (remainder.getLeft() == null) { + sentinel = remainder; + remainder = remainder.getRight(); + size++; + } else { + temp = remainder.getLeft(); + remainder.setLeft(temp.getRight()); + temp.setRight(remainder); + remainder = temp; + sentinel.setRight(temp); + } + } + } + + private void reconstruct() { + + int sz = size; + Node node = getRoot(); + + int fullCount = fullSize(sz); + rotateLeft(node, sz - fullCount); + + for (sz = fullCount; sz > 1; sz /= 2) { + rotateLeft(node, sz / 2); + } + } + + private void rotateLeft(Node root, final int count) { + if (root == null) return; + + Node scanner = root; + + for (int i = 0; i < count; i++) { + //Leftward rotation + Node child = scanner.getRight(); + scanner.setRight(child.getRight()); + scanner = child.getRight(); + child.setRight(scanner.getLeft()); + scanner.setLeft(child); + } + } + + private int fullSize(final int size) { + // Full portion of a complete tree + int ret = 1; + while (ret <= size) { + ret = 2*ret + 1; + } + return ret / 2; + } + + static class Node { + private T value; + private Node left; + private Node right; + + public Node(final T value) { + this.value = value; + } + + public T getValue() { + return value; + } + + public void setValue(final T value) { + this.value = value; + } + + public Node getLeft() { + return left; + } + + public void setLeft(final Node left) { + this.left = left; + } + + public Node getRight() { + return right; + } + + public void setRight(final Node right) { + this.right = right; + } + } +} \ No newline at end of file diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/GeolocationMetadata.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/GeolocationMetadata.java new file mode 100644 index 00000000000..e8d64495ff7 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/GeolocationMetadata.java @@ -0,0 +1,91 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.geo; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class GeolocationMetadata { + private static final Log LOG = LogFactory.getLog(GeolocationMetadata.class); + + private String[] locationDataItemNames = new String[0]; + + public static GeolocationMetadata create(String fields[], int index) { + GeolocationMetadata ret = null; + + if (fields.length > 2) { + String[] metadataNames = new String[fields.length-2]; + + for (int i = 2; i < fields.length; i++) { + metadataNames[i-2] = fields[i]; + } + ret = new GeolocationMetadata(metadataNames); + } else { + LOG.error("GeolocationMetadata.createMetadata() - Not enough fields specified, need {start, end, location} at " + index); + } + + return ret; + } + + GeolocationMetadata() {} + + GeolocationMetadata(final String[] locationDataItemNames) { + this.locationDataItemNames = locationDataItemNames; + } + + public int getDataItemNameIndex(final String dataItemName) { + int ret = -1; + + if (!StringUtils.isBlank(dataItemName)) { + for (int i = 0; i < locationDataItemNames.length; i++) { + if (locationDataItemNames[i].equals(dataItemName)) { + ret = i; + break; + } + } + } + + return ret; + } + + public String[] getLocationDataItemNames() { + return locationDataItemNames; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toStringDump(sb); + + return sb.toString(); + } + + private StringBuilder toStringDump(StringBuilder sb) { + sb.append("FROM_IP,TO_IP,"); + + for (String locationDataItemName : locationDataItemNames) { + sb.append(locationDataItemName).append(", "); + } + + return sb; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/RangeChecker.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/RangeChecker.java new file mode 100644 index 00000000000..0cf9cb16e52 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/RangeChecker.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.geo; + +public interface RangeChecker { + int compareToRange(V value); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/RangerGeolocationData.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/RangerGeolocationData.java new file mode 100644 index 00000000000..db600a1768b --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/RangerGeolocationData.java @@ -0,0 +1,222 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.geo; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Objects; + +public class RangerGeolocationData implements Comparable, RangeChecker { + private static final Log LOG = LogFactory.getLog(RangerGeolocationData.class); + + private static final Character IPSegmentsSeparator = '.'; + + private final long fromIPAddress; + private final long toIPAddress; + private final String[] locationData; + private int hash; + + public static RangerGeolocationData create(String fields[], int index, boolean useDotFormat) { + + RangerGeolocationData data = null; + + if (fields.length > 2) { + String startAddress = fields[0]; + String endAddress = fields[1]; + + if (RangerGeolocationData.validateAsIP(startAddress, useDotFormat) && RangerGeolocationData.validateAsIP(endAddress, useDotFormat)) { + + long startIP, endIP; + if (!useDotFormat) { + startAddress = RangerGeolocationData.unsignedIntToIPAddress(Long.valueOf(startAddress)); + endAddress = RangerGeolocationData.unsignedIntToIPAddress(Long.valueOf(endAddress)); + } + startIP = RangerGeolocationData.ipAddressToLong(startAddress); + endIP = RangerGeolocationData.ipAddressToLong(endAddress); + + if ((endIP - startIP) >= 0) { + + String[] locationData = new String[fields.length-2]; + for (int i = 2; i < fields.length; i++) { + locationData[i-2] = fields[i]; + } + data = new RangerGeolocationData(startIP, endIP, locationData); + } + } + + } else { + LOG.error("GeolocationMetadata.createMetadata() - Not enough fields specified, need {start, end, location} at " + index); + } + return data; + } + + private RangerGeolocationData(final long fromIPAddress, final long toIPAddress, final String[] locationData) { + this.fromIPAddress = fromIPAddress; + this.toIPAddress = toIPAddress; + this.locationData = locationData; + } + + public String[] getLocationData() { + return locationData; + } + + @Override + public int compareTo(final RangerGeolocationData other) { + int ret = (other == null) ? 1 : 0; + if (ret == 0) { + ret = Long.compare(fromIPAddress, other.fromIPAddress); + if (ret == 0) { + ret = Long.compare(toIPAddress, other.toIPAddress); + if (ret == 0) { + ret = Integer.compare(locationData.length, other.locationData.length); + for (int i = 0; ret == 0 && i < locationData.length; i++) { + ret = stringCompareTo(locationData[i], other.locationData[i]); + } + } + } + } + return ret; + } + + @Override + public boolean equals(Object other) { + boolean ret = false; + if (other != null && (other instanceof RangerGeolocationData)) { + ret = this == other || compareTo((RangerGeolocationData) other) == 0; + } + return ret; + } + + @Override + public int hashCode() { + if (hash == 0) { + hash = Objects.hash(fromIPAddress, toIPAddress, locationData); + } + return hash; + } + + @Override + public int compareToRange(final Long ip) { + int ret = Long.compare(fromIPAddress, ip.longValue()); + + if (ret < 0) { + ret = Long.compare(toIPAddress, ip.longValue()); + if (ret > 0) { + ret = 0; + } + } + + return ret; + } + + public static long ipAddressToLong(final String ipAddress) { + + long ret = 0L; + + try { + byte[] bytes = InetAddress.getByName(ipAddress).getAddress(); + + if (bytes != null && bytes.length <= 4) { + for (int i = 0; i < bytes.length; i++) { + int val = bytes[i] < 0 ? (256 + bytes[i]) : bytes[i]; + ret += (val << (8 * (3 - i))); + } + } + } + catch (UnknownHostException exception) { + LOG.error("RangerGeolocationData.ipAddressToLong() - Invalid IP address " + ipAddress); + } + + return ret; + } + + public static String unsignedIntToIPAddress(final long val) { + if (val <= 0) { + return ""; + } + long remaining = val; + String segments[] = new String[4]; + for (int i = 3; i >= 0; i--) { + long segment = remaining % 0x100; + remaining = remaining / 0x100; + segments[i] = String.valueOf(segment); + } + return StringUtils.join(segments, IPSegmentsSeparator); + } + + public static boolean validateAsIP(String ipAddress, boolean ipInDotNotation) { + if (!ipInDotNotation) { + return StringUtils.isNumeric(ipAddress); + } + + boolean ret = false; + + try { + // Only to validate to see if ipAddress is in correct format + InetAddress.getByName(ipAddress).getAddress(); + ret = true; + } + catch(UnknownHostException exception) { + LOG.error("RangerGeolocationData.validateAsIP() - Invalid address " + ipAddress); + } + + return ret; + } + + private static int stringCompareTo(String str1, String str2) { + if(str1 == str2) { + return 0; + } else if(str1 == null) { + return -1; + } else if(str2 == null) { + return 1; + } else { + return str1.compareTo(str2); + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + private StringBuilder toString(StringBuilder sb) { + sb.append("{") + .append("from=") + .append(RangerGeolocationData.unsignedIntToIPAddress(fromIPAddress)) + .append(", to=") + .append(RangerGeolocationData.unsignedIntToIPAddress(toIPAddress)) + .append(", location={"); + for (String data : locationData) { + sb.append(data).append(", "); + } + sb.append("}"); + sb.append("}"); + return sb; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/RangerGeolocationDatabase.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/RangerGeolocationDatabase.java new file mode 100644 index 00000000000..c792397c311 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/RangerGeolocationDatabase.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.geo; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class RangerGeolocationDatabase { + private static final Log LOG = LogFactory.getLog(RangerGeolocationDatabase.class); + + private BinarySearchTree data = new BinarySearchTree<>(); + + private GeolocationMetadata metadata = new GeolocationMetadata(); + + public String getValue(final RangerGeolocationData geolocationData, final String attributeName) { + String value = null; + int index = -1; + + if (geolocationData != null && StringUtils.isNotBlank(attributeName)) { + if ((index = getMetadata().getDataItemNameIndex(attributeName)) != -1) { + String[] attrValues = geolocationData.getLocationData(); + if (index < attrValues.length) { + value = attrValues[index]; + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("RangerGeolocationDatabase.getValue() - No value specified attribute-name:" + attributeName); + } + } + } else { + LOG.error("RangerGeolocationDatabase.getValue() - RangerGeolocationDatabase not initialized or Invalid attribute-name:" + attributeName); + } + } + + return value; + } + + public RangerGeolocationData find(final String ipAddressStr) { + RangerGeolocationData ret = null; + + if (StringUtils.isNotBlank(ipAddressStr) && RangerGeolocationData.validateAsIP(ipAddressStr, true)) { + ret = data.find(RangerGeolocationData.ipAddressToLong(ipAddressStr)); + } + return ret; + } + + public void optimize() { + long start = 0L, end = 0L; + + start = System.currentTimeMillis(); + data.rebalance(); + end = System.currentTimeMillis(); + + if (LOG.isDebugEnabled()) { + LOG.debug("RangerGeolocationDatabase.optimize() - Time taken for optimizing database = " + (end - start) + " milliseconds"); + } + } + + public void setData(final BinarySearchTree dataArg) { data = dataArg != null ? dataArg : new BinarySearchTree();} + + public void setMetadata(final GeolocationMetadata metadataArg) { metadata = metadataArg != null ? metadataArg : new GeolocationMetadata();} + + public GeolocationMetadata getMetadata() { return metadata; } + + public BinarySearchTree getData() { return data; } + + public void dump(ValuePrinter processor) { + + BinarySearchTree geoDatabase = getData(); + GeolocationMetadata metadata = getMetadata(); + processor.build(); + + processor.print("#================== Geolocation metadata =================="); + processor.print(metadata.toString()); + + processor.print("#================== Dump of geoDatabase - START =================="); + geoDatabase.preOrderTraverseTree(processor); + processor.print("#================== Dump of geoDatabase - END =================="); + + processor.close(); + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/ValuePrinter.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/ValuePrinter.java new file mode 100644 index 00000000000..fe23f53bb65 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/ValuePrinter.java @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.geo; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.BufferedWriter; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; + +class ValuePrinter implements ValueProcessor { + private static final Log LOG = LogFactory.getLog(ValuePrinter.class); + + private Writer writer; + private String fileName; + + ValuePrinter(String fileName) { + this.fileName = fileName; + } + + public T process(T value) { + + if (value != null) { + if (writer == null) { + LOG.error("ValuePrinter.process() -" + value); + } else { + try { + writer.write(value.toString()); + writer.write('\n'); + } catch (IOException exception) { + LOG.error("ValuePrinter.process() - Cannot write '" + value + "' to " + fileName); + } + } + } + return value; + } + + public void print(String str) { + if (writer == null) { + LOG.error("ValuePrinter.print() -" + str); + } else { + try { + writer.write(str); + writer.write('\n'); + } catch (IOException exception) { + LOG.error("ValuePrinter.print() - Cannot write '" + str + "' to " + fileName ); + } + } + } + + void build() { + try { + if (StringUtils.isNotBlank(fileName)) { + writer = new BufferedWriter(new OutputStreamWriter( + new FileOutputStream(fileName))); + } + } catch(IOException exception) { + LOG.error("ValuePrinter.build() - Cannot open " + fileName + " for writing"); + } + } + + void close() { + try { + if (writer != null) { + writer.close(); + } + } catch (IOException exception) { + LOG.error("ValuePrinter.close() - Cannot close " + fileName); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/ValueProcessor.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/ValueProcessor.java new file mode 100644 index 00000000000..713ffb3e25d --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/geo/ValueProcessor.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.geo; + +public interface ValueProcessor { + T process(T value); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/AuditFilter.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/AuditFilter.java new file mode 100644 index 00000000000..97281e1c51e --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/AuditFilter.java @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyResource; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class AuditFilter { + public enum AccessResult { DENIED, ALLOWED, NOT_DETERMINED } + + private AccessResult accessResult; + private Map resources; + private List accessTypes; + private List actions; + private List users; + private List groups; + private List roles; + private Boolean isAudited; + + public AuditFilter() { } + + public AccessResult getAccessResult() { + return accessResult; + } + + public void setAccessResult(AccessResult accessResult) { + this.accessResult = accessResult; + } + + public Map getResources() { + return resources; + } + + public void setResources(Map resources) { + this.resources = resources; + } + + public List getAccessTypes() { + return accessTypes; + } + + public void setAccessTypes(List accessTypes) { + this.accessTypes = accessTypes; + } + + public List getActions() { + return actions; + } + + public void setActions(List actions) { + this.actions = actions; + } + + public List getUsers() { + return users; + } + + public void setUsers(List users) { + this.users = users; + } + + public List getGroups() { + return groups; + } + + public void setGroups(List groups) { + this.groups = groups; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + public Boolean getIsAudited() { + return isAudited; + } + + public void setAction(Boolean isAudited) { + this.isAudited = isAudited; + } + + @Override + public String toString() { + return "{accessResult=" + accessResult + + ", resources=" + resources + + ", accessTypes=" + accessTypes + + ", actions=" + actions + + ", users=" + users + + ", groups=" + groups + + ", roles=" + roles + + ", isAudited=" + isAudited + + "}"; + } +} \ No newline at end of file diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerMetrics.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerMetrics.java new file mode 100644 index 00000000000..d9ac642fc4a --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerMetrics.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + + +import com.fasterxml.jackson.annotation.JsonInclude; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerMetrics { + + private Map data; + + public RangerMetrics() { + setData(null); + } + public RangerMetrics(Map data) { + setData(data); + } + + public Map getData() { + return data; + } + + public void setData(Map data) { + this.data = data; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerPolicyDelta.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerPolicyDelta.java new file mode 100644 index 00000000000..a8af41cd8cf --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerPolicyDelta.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerPolicyDelta implements java.io.Serializable { + + public static final int CHANGE_TYPE_POLICY_CREATE = 0; + public static final int CHANGE_TYPE_POLICY_UPDATE = 1; + public static final int CHANGE_TYPE_POLICY_DELETE = 2; + + private static String[] changeTypeNames = { "POLICY_CREATE", "POLICY_UPDATE", "POLICY_DELETE", "SERVICE_CHANGE", "SERVICE_DEF_CHANGE", "RANGER_ADMIN_START", "LOG_ERROR", "INVALIDATE_POLICY_DELTAS", "ROLE_UPDATE" }; + + private Long id; + private Integer changeType; + private Long policiesVersion; + private RangerPolicy policy; + + public RangerPolicyDelta() { + this(null, null, null, null); + } + + public RangerPolicyDelta(final Long id, final Integer changeType, final Long policiesVersion, final RangerPolicy policy) { + setId(id); + setChangeType(changeType); + setPoliciesVersion(policiesVersion); + setPolicy(policy); + } + public Long getId() { return id; } + + public Integer getChangeType() { return changeType; } + + public Long getPoliciesVersion() { return policiesVersion; } + + @JsonIgnore + public String getServiceType() { return policy != null ? policy.getServiceType() : null; } + + @JsonIgnore + public String getPolicyType() { return policy != null ? policy.getPolicyType() : null; } + + @JsonIgnore + public Long getPolicyId() { return policy != null ? policy.getId() : null; } + + @JsonIgnore + public String getPolicyGuid() { return policy != null ? policy.getGuid() : null; } + + @JsonIgnore + public String getPolicyAtlasGuid() { return policy != null ? policy.getAtlasGuid() : null; } + + @JsonIgnore + public String getZoneName() { return policy != null ? policy.getZoneName() : null; } + + public RangerPolicy getPolicy() { return policy; } + + public void setId(Long id) { this.id = id;} + + private void setChangeType(Integer changeType) { this.changeType = changeType; } + + private void setPoliciesVersion(Long policiesVersion) { this.policiesVersion = policiesVersion; } + + public void setPolicy(RangerPolicy policy) { this.policy = policy; } + + @Override + public String toString() { + return "id:" + id + + ", changeType:" + changeTypeNames[changeType] + + ", policiesVersion:" + getPoliciesVersion() + + ", serviceType:" + getServiceType() + + ", policyType:" + getPolicyType() + + ", policyId:[" + getPolicyId() + "]" + + ", policyGuid:[" + getPolicyGuid() + "]" + + ", policy:[" + policy +"]"; + } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerPolicyResourceSignature.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerPolicyResourceSignature.java new file mode 100644 index 00000000000..10f220e43f1 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerPolicyResourceSignature.java @@ -0,0 +1,225 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.authorization.config.RangerAdminConfig; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemCondition; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyResource; +import org.apache.commons.lang.StringUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; + +public class RangerPolicyResourceSignature { + + static final int _SignatureVersion = 1; + private static final Log LOG = LogFactory.getLog(RangerPolicyResourceSignature.class); + static final RangerPolicyResourceSignature _EmptyResourceSignature = new RangerPolicyResourceSignature((RangerPolicy)null); + + private final String _string; + private final String _hash; + private final RangerPolicy _policy; + + public RangerPolicyResourceSignature(RangerPolicy policy) { + _policy = policy; + PolicySerializer serializer = new PolicySerializer(_policy); + _string = serializer.toString(); + if (RangerAdminConfig.getInstance().isFipsEnabled()) { + _hash = DigestUtils.sha512Hex(_string); + } else { + _hash = DigestUtils.sha256Hex(_string); + } + } + + String asString() { + return _string; + } + + public String getSignature() { + return _hash; + } + + @Override + public int hashCode() { + // we assume no collision + return Objects.hashCode(_hash); + } + + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof RangerPolicyResourceSignature)) { + return false; + } + RangerPolicyResourceSignature that = (RangerPolicyResourceSignature)object; + return Objects.equals(this._hash, that._hash); + } + + @Override + public String toString() { + return String.format("%s: %s", _hash, _string); + } + + static class PolicySerializer { + final RangerPolicy _policy; + PolicySerializer(RangerPolicy policy) { + _policy = policy; + } + + boolean isPolicyValidForResourceSignatureComputation() { + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("==> RangerPolicyResourceSignature.isPolicyValidForResourceSignatureComputation(%s)", _policy)); + } + + boolean valid = false; + if (_policy == null) { + LOG.debug("isPolicyValidForResourceSignatureComputation: policy was null!"); + } else if (_policy.getResources() == null) { + LOG.debug("isPolicyValidForResourceSignatureComputation: resources collection on policy was null!"); + } else if (_policy.getResources().containsKey(null)) { + LOG.debug("isPolicyValidForResourceSignatureComputation: resources collection has resource with null name!"); + } else { + valid = true; + } + + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("<== RangerPolicyResourceSignature.isPolicyValidForResourceSignatureComputation(%s): %s", _policy, valid)); + } + return valid; + } + + @Override + public String toString() { + // invalid/empty policy gets a deterministic signature as if it had an + // empty resource string + if (!isPolicyValidForResourceSignatureComputation()) { + return ""; + } + String type = RangerPolicy.POLICY_TYPE_ACCESS; + if (StringUtils.isEmpty(_policy.getPolicyType())) { + type = _policy.getPolicyType(); + } + Map resources = new TreeMap<>(); + for (Map.Entry entry : _policy.getResources().entrySet()) { + String resourceName = entry.getKey(); + ResourceSerializer resourceView = new ResourceSerializer(entry.getValue()); + resources.put(resourceName, resourceView); + } + String resource = resources.toString(); + if (CollectionUtils.isNotEmpty(_policy.getValiditySchedules())) { + resource += _policy.getValiditySchedules().toString(); + } + if (_policy.getPolicyPriority() != null && _policy.getPolicyPriority() != RangerPolicy.POLICY_PRIORITY_NORMAL) { + resource += _policy.getPolicyPriority(); + } + if (!StringUtils.isEmpty(_policy.getZoneName())) { + resource += _policy.getZoneName(); + } + + if (_policy.getConditions() != null) { + CustomConditionSerialiser customConditionSerialiser = new CustomConditionSerialiser(_policy.getConditions()); + resource += customConditionSerialiser.toString(); + } + + String result = String.format("{version=%d,type=%d,resource=%s}", _SignatureVersion, type, resource); + return result; + } + + } + + static class ResourceSerializer { + final RangerPolicyResource _policyResource; + + ResourceSerializer(RangerPolicyResource policyResource) { + _policyResource = policyResource; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("{"); + if (_policyResource != null) { + builder.append("values="); + if (_policyResource.getValues() != null) { + List values = new ArrayList(_policyResource.getValues()); + Collections.sort(values); + builder.append(values); + } + builder.append(",excludes="); + if (_policyResource.getIsExcludes() == null) { // null is same as false + builder.append(Boolean.FALSE); + } else { + builder.append(_policyResource.getIsExcludes()); + } + builder.append(",recursive="); + if (_policyResource.getIsRecursive() == null) { // null is the same as false + builder.append(Boolean.FALSE); + } else { + builder.append(_policyResource.getIsRecursive()); + } + } + builder.append("}"); + return builder.toString(); + } + } + + static class CustomConditionSerialiser { + final List rangerPolicyConditions; + + CustomConditionSerialiser(List rangerPolicyConditions) { + this.rangerPolicyConditions = rangerPolicyConditions; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + Map> conditionMap = new TreeMap<>(); + + for(RangerPolicyItemCondition rangerPolicyCondition : rangerPolicyConditions) { + if (rangerPolicyCondition.getType() != null) { + String type = rangerPolicyCondition.getType(); + List values = new ArrayList<>(); + if (rangerPolicyCondition.getValues() != null) { + values.addAll(rangerPolicyCondition.getValues()); + Collections.sort(values); + } + conditionMap.put(type, values); + } + } + + if (MapUtils.isNotEmpty(conditionMap)) { + builder.append("{"); + builder.append("RangerPolicyConditions="); + builder.append(conditionMap); + builder.append("}"); + } + + return builder.toString(); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerSecurityZone.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerSecurityZone.java new file mode 100644 index 00000000000..336ba3d906d --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerSecurityZone.java @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY) +@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown=true) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerSecurityZone extends RangerBaseModelObject implements java.io.Serializable { + public static final long RANGER_UNZONED_SECURITY_ZONE_ID = 1L; + private static final long serialVersionUID = 1L; + private String name; + private Map services; + private List tagServices; + private List adminUsers; + private List adminUserGroups; + private List auditUsers; + private List auditUserGroups; + private String description; + + public RangerSecurityZone() { + this(null, null, null, null, null, null, null,null); + } + + public RangerSecurityZone(String name, Map services,List tagServices, List adminUsers, List adminUserGroups, List auditUsers, List auditUserGroups, String description) { + setName(name); + setServices(services); + setAdminUsers(adminUsers); + setAdminUserGroups(adminUserGroups); + setAuditUsers(auditUsers); + setAuditUserGroups(auditUserGroups); + setDescription(description); + setTagServices(tagServices); + } + public String getName() { return name; } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { return description; } + + public void setDescription(String description) { + this.description = description; + } + + public Map getServices() { return services; } + + public void setServices(Map services) { + this.services = services == null ? new HashMap<>() : services; + } + + public List getAdminUsers() { return adminUsers; } + + public void setAdminUsers(List adminUsers) { + this.adminUsers = adminUsers == null ? new ArrayList<>() : adminUsers; + } + + public List getAdminUserGroups() { return adminUserGroups; } + + public void setAdminUserGroups(List adminUserGroups) { + this.adminUserGroups = adminUserGroups == null ? new ArrayList<>() : adminUserGroups; + } + + public List getAuditUsers() { return auditUsers; } + + public void setAuditUsers(List auditUsers) { + this.auditUsers = auditUsers == null ? new ArrayList<>() : auditUsers; + } + + public List getAuditUserGroups() { return auditUserGroups; } + + public void setAuditUserGroups(List auditUserGroups) { + this.auditUserGroups = auditUserGroups == null ? new ArrayList<>() : auditUserGroups; + } + + public List getTagServices() { + return tagServices; + } + + public void setTagServices(List tagServices) { + this.tagServices = (tagServices != null) ? tagServices : new ArrayList(); + } + + @Override + public String toString() { + return "{name=" + name + + ", services=" + services + + ", tagServices=" + tagServices + + ", adminUsers=" + adminUsers + + ", adminUserGroups=" + adminUserGroups + + ", auditUsers=" + auditUsers + + ", auditUserGroups=" + auditUserGroups + + ", description="+ description + +"}"; + } + + @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY) + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @JsonIgnoreProperties(ignoreUnknown=true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerSecurityZoneService implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private List>> resources; + + public RangerSecurityZoneService() { + this(null); + } + + public RangerSecurityZoneService(List>> resources) { + setResources(resources); + } + + public List>> getResources() { return resources; } + + public void setResources(List>> resources) { + this.resources = resources == null ? new ArrayList<>() : resources; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{resources={"); + for (Map> resource : resources) { + sb.append("[ "); + for (Map.Entry> entry : resource.entrySet()) { + sb.append("{resource-def-name=").append(entry.getKey()).append(", values=").append(entry.getValue()).append("},"); + } + sb.append(" ],"); + } + sb.append("}}"); + + return sb.toString(); + } + + } +} + diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerService.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerService.java new file mode 100644 index 00000000000..ed64ed5686d --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerService.java @@ -0,0 +1,278 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerService extends RangerBaseModelObject implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String type; + private String name; + private String displayName; + private String description; + private String tagService; + private Map configs; + private Long policyVersion; + private Date policyUpdateTime; + private Long tagVersion; + private Date tagUpdateTime; + + + /** + * @param + */ + public RangerService() { + this(null, null, null, null, null); + } + + /** + * @param type + * @param name + * @param description + * @param configs + * @param tagService + */ + public RangerService(String type, String name, String description, String tagService, Map configs) { + super(); + + setType(type); + setName(name); + setDescription(description); + setTagService(tagService); + setConfigs(configs); + } + + /** + * @param other + */ + public void updateFrom(RangerService other) { + super.updateFrom(other); + + setType(other.getType()); + setName(other.getName()); + setDisplayName(other.getDisplayName()); + setDescription(other.getDescription()); + setTagService(other.getTagService()); + setConfigs(other.getConfigs()); + setPolicyVersion(other.getPolicyVersion()); + setPolicyUpdateTime(other.getPolicyUpdateTime()); + setTagVersion(other.getTagVersion()); + setTagUpdateTime(other.getTagUpdateTime()); + } + + /** + * @return the type + */ + public String getType() { + return type; + } + + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + /** + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * @param description the description to set + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * @return the tagService + */ + public String getTagService() { + return tagService; + } + + /** + * @param tagService the tagServiceName to set + */ + public void setTagService(String tagService) { + this.tagService = tagService; + } + + /** + * @return the configs + */ + public Map getConfigs() { + return configs; + } + + /** + * @param configs the configs to set + */ + public void setConfigs(Map configs) { + if(this.configs == null) { + this.configs = new HashMap<>(); + } + + if(this.configs == configs) { + return; + } + + this.configs.clear(); + + if(configs != null) { + for(Map.Entry e : configs.entrySet()) { + this.configs.put(e.getKey(), e.getValue()); + } + } + } + + /** + * @return the policyVersion + */ + public Long getPolicyVersion() { + return policyVersion; + } + + /** + * @param policyVersion the policyVersion to set + */ + public void setPolicyVersion(Long policyVersion) { + this.policyVersion = policyVersion; + } + + /** + * @return the policyUpdateTime + */ + public Date getPolicyUpdateTime() { + return policyUpdateTime; + } + + /** + * @param policyUpdateTime the policyUpdateTime to set + */ + public void setPolicyUpdateTime(Date policyUpdateTime) { + this.policyUpdateTime = policyUpdateTime; + } + + /** + * @return the tagVersion + */ + public Long getTagVersion() { + return tagVersion; + } + + /** + * @param tagVersion the tagVersion to set + */ + public void setTagVersion(Long tagVersion) { + this.tagVersion = tagVersion; + } + + + /** + * @return the tagUpdateTime + */ + public Date getTagUpdateTime() { + return tagUpdateTime; + } + + /** + * @param tagUpdateTime the policyUpdateTime to set + */ + public void setTagUpdateTime(Date tagUpdateTime) { + this.tagUpdateTime = tagUpdateTime; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerService={"); + + super.toString(sb); + sb.append("name={").append(name).append("} "); + sb.append("displayName={").append(displayName).append("} "); + sb.append("type={").append(type).append("} "); + sb.append("description={").append(description).append("} "); + sb.append("tagService={").append(tagService).append("} "); + + sb.append("configs={"); + if(configs != null) { + for(Map.Entry e : configs.entrySet()) { + sb.append(e.getKey()).append("={").append(e.getValue()).append("} "); + } + } + sb.append("} "); + + sb.append("policyVersion={").append(policyVersion).append("} "); + sb.append("policyUpdateTime={").append(policyUpdateTime).append("} "); + + sb.append("tagVersion={").append(tagVersion).append("} "); + sb.append("tagUpdateTime={").append(tagUpdateTime).append("} "); + + sb.append("}"); + + return sb; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerServiceResource.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerServiceResource.java new file mode 100644 index 00000000000..80886ff6149 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerServiceResource.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.HashMap; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerServiceResource extends RangerBaseModelObject { + private static final long serialVersionUID = 1L; + + private String serviceName; + private Map resourceElements; + private String ownerUser; + private String resourceSignature; + private Map additionalInfo; + + public RangerServiceResource(String guid, String serviceName, Map resourceElements, String resourceSignature, String ownerUser, Map additionalInfo) { + super(); + setGuid(guid); + setServiceName(serviceName); + setResourceElements(resourceElements); + setResourceSignature(resourceSignature); + setOwnerUser(ownerUser); + setAdditionalInfo(additionalInfo); + } + public RangerServiceResource(String guid, String serviceName, Map resourceElements, String resourceSignature, String ownerUser) { + this(guid, serviceName, resourceElements, resourceSignature,ownerUser, null); + } + public RangerServiceResource(String guid, String serviceName, Map resourceElements, String resourceSignature) { + this(guid, serviceName, resourceElements, resourceSignature, null); + + } + + public RangerServiceResource(String guid, String serviceName, Map resourceElements) { + this(guid, serviceName, resourceElements, null, null); + } + public RangerServiceResource(String serviceName, Map resourceElements) { + this(null, serviceName, resourceElements, null, null); + } + + public RangerServiceResource() { + this(null, null, null, null, null); + } + + public String getServiceName() { return serviceName; } + + public Map getResourceElements() { return resourceElements; } + + public String getResourceSignature() { + return resourceSignature; + } + + public String getOwnerUser() { + return ownerUser; + } + + public Map getAdditionalInfo() { + return additionalInfo; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public void setResourceElements(Map resource) { + this.resourceElements = resource == null ? new HashMap() : resource; + } + + public void setResourceSignature(String resourceSignature) { + this.resourceSignature = resourceSignature; + } + + public void setOwnerUser(String ownerUser) { + this.ownerUser = ownerUser; + } + + public void setAdditionalInfo(Map additionalInfo) { + this.additionalInfo = additionalInfo; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + + sb.append("RangerServiceResource={ "); + + super.toString(sb); + + sb.append("guid={").append(getGuid()).append("} "); + sb.append("serviceName={").append(serviceName).append("} "); + + sb.append("resourceElements={"); + if(resourceElements != null) { + for(Map.Entry e : resourceElements.entrySet()) { + sb.append(e.getKey()).append("={"); + e.getValue().toString(sb); + sb.append("} "); + } + } + sb.append("} "); + + sb.append("ownerUser={").append(ownerUser).append("} "); + + sb.append("additionalInfo={"); + if(additionalInfo != null) { + for(Map.Entry e : additionalInfo.entrySet()) { + sb.append(e.getKey()).append("={").append(e.getValue()).append("} "); + } + } + sb.append("} "); + + sb.append("resourceSignature={").append(resourceSignature).append("} "); + + sb.append(" }"); + + return sb; + } +} + diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerTag.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerTag.java new file mode 100644 index 00000000000..2acd4f0e298 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerTag.java @@ -0,0 +1,221 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerTag extends RangerBaseModelObject { + private static final long serialVersionUID = 1L; + + public static final short OWNER_SERVICERESOURCE = 0; + public static final short OWNER_GLOBAL = 1; + + public static final String OPTION_TAG_VALIDITY_PERIODS = "TAG_VALIDITY_PERIODS"; + + private String type; + private Short owner = OWNER_SERVICERESOURCE; + private Map attributes; + private Map options; + private List validityPeriods; + + public RangerTag(String guid, String type, Map attributes, Short owner, Map options, List validityPeriods) { + super(); + + setGuid(guid); + setType(type); + setOwner(owner); + setAttributes(attributes); + setOwner(owner); + setOptions(options); + setValidityPeriods(validityPeriods); + } + + public RangerTag(String guid, String type, Map attributes, Short owner) { + this(guid, type, attributes, owner, null, null); + } + + public RangerTag(String type, Map attributes) { + this(null, type, attributes, OWNER_SERVICERESOURCE, null, null); + } + + public RangerTag() { + this(null, null, null, OWNER_SERVICERESOURCE, null, null); + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Map getAttributes() { + return attributes; + } + + public void setAttributes(Map attributes) { + this.attributes = attributes == null ? new HashMap() : attributes; + } + + public Short getOwner() { + return this.owner; + } + + public void setOwner(Short owner) { + this.owner = owner; + } + + public Map getOptions() { return options; } + + public void setOptions(Map options) { + if (this.options == null) { + this.options = new HashMap<>(); + } + if (this.options == options) { + return; + } + this.options.clear(); + + if(options != null) { + for(Map.Entry e : options.entrySet()) { + this.options.put(e.getKey(), e.getValue()); + } + } + } + + public List getValidityPeriods() { return validityPeriods; } + + public void setValidityPeriods(List validityPeriods) { + if (this.validityPeriods == null) { + this.validityPeriods = new ArrayList<>(); + } + if (this.validityPeriods == validityPeriods) { + return; + } + this.validityPeriods.clear(); + + if(validityPeriods != null) { + this.validityPeriods.addAll(validityPeriods); + } + } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerTag={"); + + super.toString(sb); + + sb.append("type={").append(type).append("} "); + sb.append("owner={").append(owner).append("} "); + + sb.append("attributes={"); + if (attributes != null) { + for (Map.Entry e : attributes.entrySet()) { + sb.append(e.getKey()).append("={"); + sb.append(e.getValue()); + sb.append("} "); + } + } + sb.append("} "); + + if (validityPeriods != null) { + sb.append("validityPeriods={").append(validityPeriods).append("} "); + } + sb.append("options={").append(options).append("} "); + + sb.append(" }"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((type == null) ? 0 : type.hashCode()); + result = prime * result + + ((owner == null) ? 0 : owner.hashCode()); + result = prime * result + + ((attributes == null) ? 0 : attributes.hashCode()); + result = prime * result + + ((options == null) ? 0 : options.hashCode()); + result = prime * result + + ((validityPeriods == null) ? 0 : validityPeriods.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerTag other = (RangerTag) obj; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + if (owner == null) { + if (other.owner != null) + return false; + } else if (!owner.equals(other.owner)) + return false; + if (attributes == null) { + if (other.attributes != null) + return false; + } else if (!attributes.equals(other.attributes)) + return false; + if (options == null) { + if (other.options != null) + return false; + } else if (!options.equals(other.options)) + return false; + if (validityPeriods == null) { + if (other.validityPeriods != null) + return false; + } else if (!validityPeriods.equals(other.validityPeriods)) + return false; + return true; + } +} + diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerTagDef.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerTagDef.java new file mode 100644 index 00000000000..f8c587cc2ae --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerTagDef.java @@ -0,0 +1,128 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.List; + + +/** + * Represents a TAG definition known to Ranger. In general, this will be provided + * by some external system identified by 'source'. + * + */ +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerTagDef extends RangerBaseModelObject { + private static final long serialVersionUID = 1L; + + private String name; + private String source; + + private List attributeDefs; + + public RangerTagDef() { + this(null, "Internal"); + } + + public RangerTagDef(String name) { + this(name, "Internal"); + } + + public RangerTagDef(String name, String source) { + super(); + setName(name); + setSource(source); + setAttributeDefs(null); + } + + public String getName() { + return name; + } + + public void setName(String name) { + + this.name = name == null ? "" : name; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source == null ? "" : source; + } + + public List getAttributeDefs() { + return attributeDefs; + } + + public void setAttributeDefs(List attributeDefs) { + this.attributeDefs = attributeDefs == null ? new ArrayList() : attributeDefs; + } + + /** + * Represents one attribute for a TAG. TAG-Attribute consists of a name and type. + * name provides a handle for possible specification of additional information + * associated with the TAG. + * Interpretation of type is up to the policy-engine. + */ + + @JsonInclude(JsonInclude.Include.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + + public static class RangerTagAttributeDef implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String name; + private String type; + + public RangerTagAttributeDef() { + this(null, null); + } + + public RangerTagAttributeDef(String name, String type) { + setName(name); + setType(type); + } + + public String getName() { + return name; + } + + public String getType() { + return type; + } + + public void setName(String name) { + this.name = name == null ? "" : name; + } + public void setType(String type) { + this.type = type == null ? "" : type; + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerTagResourceMap.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerTagResourceMap.java new file mode 100644 index 00000000000..8d2b2f48974 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/RangerTagResourceMap.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerTagResourceMap extends RangerBaseModelObject { + private static final long serialVersionUID = 1L; + + private Long tagId; + private Long resourceId; + + public RangerTagResourceMap() { + } + + public Long getTagId() { + return tagId; + } + + public Long getResourceId() { + return resourceId; + } + + public void setTagId(Long tagId) { + this.tagId = tagId; + } + + public void setResourceId(Long resourceId) { + this.resourceId = resourceId; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + + sb.append("RangerTagResourceMap={ "); + + super.toString(sb); + + sb.append("resourceId=").append(resourceId).append(", "); + + sb.append("tagId=").append(tagId); + + sb.append(" }"); + + return sb; + }} + diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/RangerServiceDefHelper.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/RangerServiceDefHelper.java new file mode 100644 index 00000000000..e7cbb28ddf1 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/RangerServiceDefHelper.java @@ -0,0 +1,677 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model.validation; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerResourceDef; +import org.apache.atlas.plugin.resourcematcher.RangerAbstractResourceMatcher; +import org.apache.atlas.plugin.resourcematcher.RangerPathResourceMatcher; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public class RangerServiceDefHelper { + private static final Log LOG = LogFactory.getLog(RangerServiceDefHelper.class); + + static final Map _Cache = new ConcurrentHashMap<>(); + final Delegate _delegate; + + + public RangerServiceDefHelper(RangerServiceDef serviceDef) { + this(serviceDef, true, false); + } + + public RangerServiceDefHelper(RangerServiceDef serviceDef, boolean useCache) { + this(serviceDef, useCache, false); + } + + /** + * Intended for use when serviceDef object is not-trusted, e.g. when service-def is being created or updated. + * @param serviceDef + * @param useCache + */ + public RangerServiceDefHelper(RangerServiceDef serviceDef, boolean useCache, boolean checkForCycles) { + // NOTE: we assume serviceDef, its name and update time are can never by null. + + if(LOG.isDebugEnabled()) { + LOG.debug(String.format("==> RangerServiceDefHelper(). The RangerServiceDef: %s", serviceDef)); + } + + String serviceName = serviceDef.getName(); + Date serviceDefFreshnessDate = serviceDef.getUpdateTime(); + + Delegate delegate = null; + if (useCache && _Cache.containsKey(serviceName)) { + LOG.debug("RangerServiceDefHelper(): found delegate in cache with matching serviceName. Need to check date"); + Delegate that = _Cache.get(serviceName); + if (Objects.equals(that.getServiceFreshnessDate(), serviceDefFreshnessDate)) { + delegate = that; + LOG.debug("RangerServiceDefHelper(): cached delegate matched in date, too! Will use it now."); + } else { + LOG.debug("RangerServiceDefHelper(): cached delegate date mismatch!"); + } + } + if (delegate == null) { // either not found in cache or date didn't match + delegate = new Delegate(serviceDef, checkForCycles); + if (useCache) { + LOG.debug("RangerServiceDefHelper(): Created new delegate and put in delegate cache!"); + _Cache.put(serviceName, delegate); + } + } + _delegate = delegate; + } + + public RangerServiceDef getServiceDef() { + return _delegate._serviceDef; + } + + /** + * for a resource definition as follows: + * + * /-> E -> F + * A -> B -> C -> D + * \-> G -> H + * + * It would return a set with following ordered entries in it + * { [A B C D], [A E F], [A B G H] } + * + * @return + */ + public Set> getResourceHierarchies(String policyType) { + return _delegate.getResourceHierarchies(policyType); + } + + public Set> getResourceHierarchies(String policyType, Collection keys) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> getResourceHierarchies(policyType=" + policyType + ", keys=" + StringUtils.join(keys, ",") + ")"); + } + + Set> ret = new HashSet>(); + + if (StringUtils.isEmpty(policyType)) { + policyType = RangerPolicy.POLICY_TYPE_ACCESS; + } + + for (List hierarchy : getResourceHierarchies(policyType)) { + if (hierarchyHasAllResources(hierarchy, keys)) { + ret.add(hierarchy); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== getResourceHierarchies(policyType=" + policyType + ", keys=" + StringUtils.join(keys, ",") + ") : " + StringUtils.join(ret, ",")); + } + return ret; + } + + public boolean hierarchyHasAllResources(List hierarchy, Collection resourceNames) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> hierarchyHasAllResources(hierarchy=" + StringUtils.join(hierarchy, ",") + ", resourceNames=" + StringUtils.join(resourceNames, ",") + ")"); + } + boolean foundAllResourceKeys = true; + + for (String resourceKey : resourceNames) { + boolean found = false; + + for (RangerResourceDef resourceDef : hierarchy) { + if (resourceDef.getName().equals(resourceKey)) { + found = true; + break; + } + } + + if (!found) { + foundAllResourceKeys = false; + break; + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== hierarchyHasAllResources(hierarchy=" + StringUtils.join(hierarchy, ",") + ", resourceNames=" + StringUtils.join(resourceNames, ",") + "): " + foundAllResourceKeys); + } + return foundAllResourceKeys; + } + + public boolean isResourceGraphValid() { + return _delegate.isResourceGraphValid(); + } + + public List getOrderedResourceNames(Collection resourceNames) { + final List ret; + if (resourceNames != null) { + ret = new ArrayList<>(); + for (String orderedName : _delegate.getAllOrderedResourceNames()) { + for (String resourceName : resourceNames) { + if (StringUtils.equals(orderedName, resourceName) && !ret.contains(resourceName)) { + ret.add(resourceName); + break; + } + } + } + } else { + ret = Collections.EMPTY_LIST; + } + return ret; + } + + /** + * Not designed for public access. Package level only for testability. + */ + static class Delegate { + final RangerServiceDef _serviceDef; + final Map>> _hierarchies = new HashMap<>(); + final Date _serviceDefFreshnessDate; + final String _serviceName; + final boolean _checkForCycles; + final boolean _valid; + final List _orderedResourceNames; + final static Set> EMPTY_RESOURCE_HIERARCHY = Collections.unmodifiableSet(new HashSet>()); + + + public Delegate(RangerServiceDef serviceDef, boolean checkForCycles) { + // NOTE: we assume serviceDef, its name and update time are can never by null. + _serviceDef = serviceDef; + _serviceName = serviceDef.getName(); + _serviceDefFreshnessDate = serviceDef.getUpdateTime(); + _checkForCycles = checkForCycles; + + boolean isValid = true; + for(String policyType : RangerPolicy.POLICY_TYPES) { + List resources = getResourceDefs(serviceDef, policyType); + DirectedGraph graph = createGraph(resources); + + if(graph != null) { + Map resourceDefMap = getResourcesAsMap(resources); + if (isValid(graph, resourceDefMap)) { + Set> hierarchies = getHierarchies(graph, resourceDefMap); + _hierarchies.put(policyType, Collections.unmodifiableSet(hierarchies)); + } else { + isValid = false; + _hierarchies.put(policyType, EMPTY_RESOURCE_HIERARCHY); + } + } else { + _hierarchies.put(policyType, EMPTY_RESOURCE_HIERARCHY); + } + } + + if (isValid) { + _orderedResourceNames = buildSortedResourceNames(); + } else { + _orderedResourceNames = new ArrayList<>(); + } + + _valid = isValid; + if (LOG.isDebugEnabled()) { + String message = String.format("Found [%d] resource hierarchies for service [%s] update-date[%s]: %s", _hierarchies.size(), _serviceName, + _serviceDefFreshnessDate == null ? null : _serviceDefFreshnessDate.toString(), _hierarchies); + LOG.debug(message); + } + } + + public void patchServiceDefWithDefaultValues() { + for(String policyType : RangerPolicy.POLICY_TYPES) { + Set> resourceHierarchies = getResourceHierarchies(policyType); + for (List resourceHierarchy : resourceHierarchies) { + for (int index = 0; index < resourceHierarchy.size(); index++) { + RangerResourceDef resourceDef = resourceHierarchy.get(index); + if (!Boolean.TRUE.equals(resourceDef.getIsValidLeaf())) { + resourceDef.setIsValidLeaf(index == resourceHierarchy.size()-1); + } + } + } + } + } + + public Set> getResourceHierarchies(String policyType) { + if(StringUtils.isEmpty(policyType)) { + policyType = RangerPolicy.POLICY_TYPE_ACCESS; + } + + Set> ret = _hierarchies.get(policyType); + + if(ret == null) { + ret = EMPTY_RESOURCE_HIERARCHY; + } + + return ret; + } + + public String getServiceName() { + return _serviceName; + } + + public Date getServiceFreshnessDate() { + return _serviceDefFreshnessDate; + } + + public boolean isResourceGraphValid() { + return _valid; + } + /** + * Builds a directed graph where each resource is node and arc goes from parent level to child level + * + * @param resourceDefs + * @return + */ + DirectedGraph createGraph(List resourceDefs) { + DirectedGraph graph = null; + + if(CollectionUtils.isNotEmpty(resourceDefs)) { + graph = new DirectedGraph(); + + for (RangerResourceDef resourceDef : resourceDefs) { + String name = resourceDef.getName(); + + graph.add(name); + String parent = resourceDef.getParent(); + if (StringUtils.isNotEmpty(parent)) { + graph.addArc(parent, name); + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Created graph for resources: " + graph); + } + return graph; + } + + List getResourceDefs(RangerServiceDef serviceDef, String policyType) { + final List resourceDefs; + + if(StringUtils.isEmpty(policyType) || RangerPolicy.POLICY_TYPE_ACCESS.equals(policyType)) { + resourceDefs = serviceDef.getResources(); + } else if(RangerPolicy.POLICY_TYPE_DATAMASK.equals(policyType)) { + if(serviceDef.getDataMaskDef() != null) { + resourceDefs = serviceDef.getDataMaskDef().getResources(); + } else { + resourceDefs = null; + } + } else if(RangerPolicy.POLICY_TYPE_ROWFILTER.equals(policyType)) { + if(serviceDef.getRowFilterDef() != null) { + resourceDefs = serviceDef.getRowFilterDef().getResources(); + } else { + resourceDefs = null; + } + } else { // unknown policyType; use all resources + resourceDefs = serviceDef.getResources(); + } + + return resourceDefs; + } + /** + * A valid resource graph is a forest, i.e. a disjoint union of trees. In our case, given that node can have only one "parent" node, we can detect this validity simply by ensuring that + * the resource graph has: + * - at least one sink AND + * - and least one source. + * + * A more direct method would have been ensure that the resulting graph does not have any cycles. + * + * @param graph + * + * @return + */ + boolean isValid(DirectedGraph graph, Map resourceDefMap) { + boolean ret = true; + Set sources = graph.getSources(); + Set sinks = graph.getSinks(); + + if (CollectionUtils.isEmpty(sources) || CollectionUtils.isEmpty(sinks)) { + ret = false; + } else { + List cycle = _checkForCycles ? graph.getACycle(sources, sinks) : null; + if (cycle == null) { + for (String sink : sinks) { + RangerResourceDef sinkResourceDef = resourceDefMap.get(sink); + if (Boolean.FALSE.equals(sinkResourceDef.getIsValidLeaf())) { + LOG.error("Error in path: sink node:[" + sink + "] is not leaf node"); + ret = false; + break; + } + } + } else { + LOG.error("Graph contains cycle! - " + cycle); + ret = false; + } + } + + return ret; + } + + /** + * Returns all valid resource hierarchies for the configured resource-defs. Behavior is undefined if it is called on and invalid graph. Use isValid to check validation first. + * + * @param graph + * @param resourceMap + * @return + */ + Set> getHierarchies(DirectedGraph graph, Map resourceMap) { + Set> hierarchies = new HashSet<>(); + Set sources = graph.getSources(); + Set sinks = graph.getSinks(); + + for (String source : sources) { + /* + * A disconnected node, i.e. one that does not have any arc coming into or out of it is a hierarchy in itself! + * A source by definition does not have any arcs coming into it. So if it also doesn't have any neighbors then we know + * it is a disconnected node. + */ + if (!graph.hasNeighbors(source)) { + hierarchies.add(Lists.newArrayList(source)); + } else { + for (String sink : sinks) { + List path = graph.getAPath(source, sink, new HashSet()); + + if (!path.isEmpty()) { + hierarchies.add(path); + + List workingPath = new ArrayList(); + + for (int index = 0, pathSize = path.size(); index < pathSize -1; index++) { + String node = path.get(index); + + workingPath.add(node); + + if (Boolean.TRUE.equals(resourceMap.get(node).getIsValidLeaf())) { + hierarchies.add(new ArrayList(workingPath)); + } + } + } + } + } + } + + return convertHierarchies(hierarchies, resourceMap); + } + + Set> convertHierarchies(Set> hierarchies, Map resourceMap) { + Set> result = new HashSet>(hierarchies.size()); + for (List hierarchy : hierarchies) { + List resourceList = new ArrayList(hierarchy.size()); + for (String name : hierarchy) { + RangerResourceDef def = resourceMap.get(name); + resourceList.add(def); + } + result.add(resourceList); + } + return result; + } + + /** + * Converts resource list to resource map for efficient querying + * + * @param resourceList - is guaranteed to be non-null and non-empty + * @return + */ + Map getResourcesAsMap(List resourceList) { + Map map = new HashMap(resourceList.size()); + for (RangerResourceDef resourceDef : resourceList) { + map.put(resourceDef.getName(), resourceDef); + } + return map; + } + + List getAllOrderedResourceNames() { + return this._orderedResourceNames; + } + + private static class ResourceNameLevel implements Comparable { + private String resourceName; + private int level; + + ResourceNameLevel(String resourceName, int level) { + this.resourceName = resourceName; + this.level = level; + } + + @Override + public int compareTo(ResourceNameLevel other) { + return Integer.compare(this.level, other.level); + } + } + + private List buildSortedResourceNames() { + final List ret = new ArrayList<>(); + + boolean isValid = true; + List resourceNameLevels = new ArrayList<>(); + for (RangerResourceDef resourceDef : _serviceDef.getResources()) { + String name = resourceDef.getName(); + Integer level = resourceDef.getLevel(); + if (name != null && level != null) { + ResourceNameLevel resourceNameLevel = new ResourceNameLevel(name, level); + resourceNameLevels.add(resourceNameLevel); + } else { + LOG.error("Incorrect resourceDef:[name=" + name + "]"); + isValid = false; + break; + } + } + + if (isValid) { + Collections.sort(resourceNameLevels); + + for (ResourceNameLevel resourceNameLevel : resourceNameLevels) { + ret.add(resourceNameLevel.resourceName); + } + } + return ret; + } + } + + /** + * Limited DAG implementation to analyze resource graph for a service. Not designed for public access. Package level only for testability. + */ + static class DirectedGraph { + Map> _nodes = new HashMap<>(); + + /** + * Add a node to the graph + * + * @param node + */ + void add(String node) { + if (node == null) { + throw new IllegalArgumentException("Node can't be null!"); + } else if (!_nodes.containsKey(node)) { // don't mess with a node's neighbors if it already exists in the graph + _nodes.put(node, new HashSet()); + } + } + + /** + * Connects node "from" to node "to". Being a directed graph, after this call "to" will be in the list of neighbor's of "from". While the converse need not be true. + * + * @param from + * @param to + */ + void addArc(String from, String to) { + // connecting two nodes, implicitly adds nodes to the graph if they aren't already in it + if (!_nodes.containsKey(from)) { + add(from); + } + if (!_nodes.containsKey(to)) { + add(to); + } + _nodes.get(from).add(to); + } + + /** + * Returns true if "to" is in the list of neighbors of "from" + * + * @param from + * @param to + * @return + */ + boolean hasArc(String from, String to) { + return _nodes.containsKey(from) && _nodes.containsKey(to) && _nodes.get(from).contains(to); + } + + /** + * Returns true if the node "from" has any neighbor. + * @param from + * @return + */ + boolean hasNeighbors(String from) { + return _nodes.containsKey(from) && !_nodes.get(from).isEmpty(); + } + /** + * Return the set of nodes with in degree of 0, i.e. those that are not in any other nodes' list of neighbors + * + * @return + */ + Set getSources() { + Set sources = new HashSet<>(_nodes.keySet()); + for (Map.Entry> entry : _nodes.entrySet()) { + Set nbrs = entry.getValue(); // can never be null + sources.removeAll(nbrs); // A source in a DAG can't be a neighbor of any other node + } + if (LOG.isDebugEnabled()) { + LOG.debug("Returning sources: " + sources); + } + return sources; + } + + /** + * Returns the set of nodes with out-degree of 0, i.e. those nodes whose list of neighbors is empty + * + * @return + */ + Set getSinks() { + Set sinks = new HashSet<>(); + for (Map.Entry> entry : _nodes.entrySet()) { + Set nbrs = entry.getValue(); + if (nbrs.isEmpty()) { // A sink in a DAG doesn't have any neighbor + String node = entry.getKey(); + sinks.add(node); + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("Returning sinks: " + sinks); + } + return sinks; + } + + List getACycle(Set sources, Set sinks) { + List ret = null; + Set nonSourceOrSinkNodes = Sets.difference(_nodes.keySet(), Sets.union(sources, sinks)); + for (String node : nonSourceOrSinkNodes) { + List seenNodes = new ArrayList<>(); + seenNodes.add(node); + ret = findCycle(node, seenNodes); + if (ret != null) { + break; + } + } + return ret; + } + + /** + * Does a depth first traversal of a graph starting from given node. Returns a sequence of nodes that form first cycle or null if no cycle is found. + * + * @param node Start node + * @param seenNodes List of nodes seen thus far + * @return list of nodes comprising first cycle in graph; null if no cycle was found + */ + List findCycle(String node, List seenNodes) { + List ret = null; + Set nbrs = _nodes.get(node); + for (String nbr : nbrs) { + boolean foundCycle = seenNodes.contains(nbr); + seenNodes.add(nbr); + if (foundCycle) { + ret = seenNodes; + break; + } else { + ret = findCycle(nbr, seenNodes); + if (ret != null) { + break; + } + } + } + return ret; + } + /** + * Attempts to do a depth first traversal of a graph and returns the resulting path. Note that there could be several paths that connect node "from" to node "to". + * + * @param from + * @param to + * @return + */ + List getAPath(String from, String to, Set alreadyVisited) { + List path = new ArrayList(_nodes.size()); + if (_nodes.containsKey(from) && _nodes.containsKey(to)) { // one can never reach non-existent nodes + if (hasArc(from, to)) { + path.add(from); + path.add(to); + } else { + alreadyVisited.add(from); + Set nbrs = _nodes.get(from); + for (String nbr : nbrs) { + if (!alreadyVisited.contains(nbr)) { + List subPath = getAPath(nbr, to, alreadyVisited); + if (!subPath.isEmpty()) { + path.add(from); + path.addAll(subPath); + } + } + } + } + } + return path; + } + + @Override + public boolean equals(Object object) { + if (object == this) { + return true; + } + if (object == null || object.getClass() != this.getClass()) { + return false; + } + DirectedGraph that = (DirectedGraph)object; + return Objects.equals(this._nodes, that._nodes); + } + + @Override + public int hashCode() { + return Objects.hashCode(_nodes); + } + + @Override + public String toString() { + return "_nodes=" + Objects.toString(_nodes); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/RangerValidityScheduleValidator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/RangerValidityScheduleValidator.java new file mode 100644 index 00000000000..c2f7adc1677 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/RangerValidityScheduleValidator.java @@ -0,0 +1,482 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model.validation; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.model.RangerValidityRecurrence; +import org.apache.atlas.plugin.model.RangerValidityRecurrence.RecurrenceSchedule; +import org.apache.atlas.plugin.model.RangerValiditySchedule; + +import javax.annotation.Nonnull; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.TimeZone; + +public class RangerValidityScheduleValidator { + private static final Log LOG = LogFactory.getLog(RangerValidityScheduleValidator.class); + + private static final ThreadLocal DATE_FORMATTER = new ThreadLocal() { + @Override + protected DateFormat initialValue() { + return new SimpleDateFormat(RangerValiditySchedule.VALIDITY_SCHEDULE_DATE_STRING_SPECIFICATION); + } + }; + + private static final Set validTimeZoneIds = new HashSet<>(Arrays.asList(TimeZone.getAvailableIDs())); + + private final RangerValiditySchedule validitySchedule; + private Date startTime; + private Date endTime; + private RecurrenceSchedule validityPeriodEstimator; + private RangerValiditySchedule normalizedValiditySchedule; + + public RangerValidityScheduleValidator(@Nonnull RangerValiditySchedule validitySchedule) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerValidityScheduleValidator:: " + validitySchedule); + } + + this.validitySchedule = validitySchedule; + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerValidityScheduleValidator:: " + validitySchedule); + } + } + + public RangerValiditySchedule validate(List validationFailures) { + RangerValiditySchedule ret = null; + + if (StringUtils.isEmpty(validitySchedule.getStartTime()) && StringUtils.isEmpty(validitySchedule.getEndTime()) && CollectionUtils.isEmpty(validitySchedule.getRecurrences())) { + validationFailures.add(new ValidationFailureDetails(0, "startTime,endTime,recurrences", "", true, true, false, "empty values")); + } else { + + if (StringUtils.isNotEmpty(validitySchedule.getStartTime())) { + try { + startTime = DATE_FORMATTER.get().parse(validitySchedule.getStartTime()); + } catch (ParseException exception) { + LOG.error("Error parsing startTime:[" + validitySchedule.getStartTime() + "]", exception); + validationFailures.add(new ValidationFailureDetails(0, "startTime", "", true, true, false, "invalid value")); + } + } else { + startTime = new Date(); + } + + if (StringUtils.isNotEmpty(validitySchedule.getEndTime())) { + try { + endTime = DATE_FORMATTER.get().parse(validitySchedule.getEndTime()); + } catch (ParseException exception) { + LOG.error("Error parsing endTime:[" + validitySchedule.getEndTime() + "]", exception); + validationFailures.add(new ValidationFailureDetails(0, "endTime", "", true, true, false, "invalid value")); + } + } else { + endTime = new Date(Long.MAX_VALUE); + } + + if (startTime != null && endTime != null) { + validityPeriodEstimator = new RangerValidityRecurrence.RecurrenceSchedule(); + normalizedValiditySchedule = new RangerValiditySchedule(); + + boolean isValid = validateTimeRangeSpec(validationFailures); + + if (isValid) { + if (LOG.isDebugEnabled()) { + LOG.debug("validityPeriodEstimator:[" + validityPeriodEstimator + "]"); + } + + normalizedValiditySchedule.setStartTime(validitySchedule.getStartTime()); + normalizedValiditySchedule.setEndTime(validitySchedule.getEndTime()); + normalizedValiditySchedule.setTimeZone(validitySchedule.getTimeZone()); + + ret = normalizedValiditySchedule; + } else { + normalizedValiditySchedule = null; + } + } + } + + return ret; + } + + private boolean validateTimeRangeSpec(List validationFailures) { + boolean ret; + if (startTime.getTime() >= endTime.getTime()) { + validationFailures.add(new ValidationFailureDetails(0, "startTime", "", false, true, false, "endTime is not later than startTime")); + ret = false; + } else { + ret = true; + } + ret = validateTimeZone(validitySchedule.getTimeZone(), validationFailures) && ret; + + for (RangerValidityRecurrence recurrence : validitySchedule.getRecurrences()) { + ret = validateValidityInterval(recurrence, validationFailures) && ret; + + if (ret) { + ret = validateFieldSpec(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute, validationFailures) && ret; + ret = validateFieldSpec(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour, validationFailures) && ret; + ret = validateFieldSpec(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth, validationFailures) && ret; + ret = validateFieldSpec(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek, validationFailures) && ret; + ret = validateFieldSpec(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month, validationFailures) && ret; + ret = validateFieldSpec(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.year, validationFailures) && ret; + ret = ret && validateIntervalDuration(recurrence, validationFailures); + + if (ret) { + RangerValidityRecurrence.RecurrenceSchedule schedule = new RangerValidityRecurrence.RecurrenceSchedule(getNormalizedValue(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute), getNormalizedValue(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour), + getNormalizedValue(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth), getNormalizedValue(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek), + getNormalizedValue(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month), getNormalizedValue(recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.year)); + RangerValidityRecurrence normalizedRecurrence = new RangerValidityRecurrence(schedule, recurrence.getInterval()); + normalizedValiditySchedule.getRecurrences().add(normalizedRecurrence); + } + } + } + + return ret; + } + + private boolean validateTimeZone(String timeZone, List validationFailures) { + validTimeZoneIds.removeAll(Arrays.asList("JST", "IST", "BET", "ACT", "AET", "AGT", "VST", "SystemV/AST4", "CNT", + "NET", "SystemV/MST7", "PLT", "CST", "SST", "SystemV/CST6", "CTT", "PNT", "BST", "SystemV/YST9", "MIT", + "ART", "AST", "PRT", "SystemV/HST10", "PST", "SystemV/EST5", "IET", "SystemV/PST8", "SystemV/CST6CDT", + "NST", "EAT", "ECT", "SystemV/MST7MDT", "SystemV/YST9YDT", "CAT", "SystemV/PST8PDT", "SystemV/AST4ADT", + "SystemV/EST5EDT")); + boolean ret = !StringUtils.isNotBlank(timeZone) || validTimeZoneIds.contains(timeZone); + if (!ret) { + validationFailures.add(new ValidationFailureDetails(0, "timeZone", "", false, true, false, "invalid timeZone")); + } + return ret; + } + + private boolean validateValidityInterval(RangerValidityRecurrence recurrence, List validationFailures) { + boolean ret = recurrence.getInterval() != null && recurrence.getSchedule() != null; + + if (ret) { + RangerValidityRecurrence.ValidityInterval validityInterval = recurrence.getInterval(); + + if (validityInterval.getDays() < 0 + || (validityInterval.getHours() < 0 || validityInterval.getHours() > 23) + || (validityInterval.getMinutes() < 0 || validityInterval.getMinutes() > 59)) { + validationFailures.add(new ValidationFailureDetails(0, "interval", "", false, true, false, "invalid interval")); + ret = false; + } + + if (StringUtils.isBlank(recurrence.getSchedule().getDayOfMonth()) && StringUtils.isBlank(recurrence.getSchedule().getDayOfWeek())) { + validationFailures.add(new ValidationFailureDetails(0, "validitySchedule", "", false, true, false, "empty dayOfMonth and dayOfWeek")); + ret = false; + } + } else { + validationFailures.add(new ValidationFailureDetails(0, "recurrence", "schedule/interval", true, true, false, "empty schedule/interval in recurrence spec")); + } + return ret; + } + + private boolean validateFieldSpec(RangerValidityRecurrence recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec field, List validationFailures) { + boolean ret = true; + + String fieldValue = recurrence.getSchedule().getFieldValue(field); + if (StringUtils.isBlank(fieldValue)) { + if (LOG.isDebugEnabled()) { + LOG.debug("No value provided for [" + field + "]"); + } + if (StringUtils.equals(field.name(), RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek.name()) + || StringUtils.equals(field.name(), RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth.name())) { + if (LOG.isDebugEnabled()) { + LOG.debug("Allow blank value for dayOfWeek or dayOfMonth here. Check for both being null is done elsewhere."); + } + } else { + validationFailures.add(new ValidationFailureDetails(0, field.toString(), "", false, true, false, "No value provided")); + } + } + ret = validateCharacters(fieldValue, field.specialChars); + + if (!ret) { + validationFailures.add(new ValidationFailureDetails(0, field.toString(), "", false, true, false, "invalid character(s)")); + } else { + // Valid month values in java.util.Date are from 1-12, in java.util.Calendar from 0 to 11 + // Internally we use Calendar values for validation and evaluation + int minimum = field == RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month ? field.minimum + 1 : field.minimum; + int maximum = field == RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month ? field.maximum + 1 : field.maximum; + ret = validateRanges(recurrence, field, minimum, maximum, validationFailures); + } + return ret; + } + + private boolean validateCharacters(String str, String permittedCharacters) { + boolean ret = true; + if (StringUtils.isNotBlank(str)) { + char[] chars = str.toCharArray(); + for (char c : chars) { + if (!(Character.isDigit(c) || Character.isWhitespace(c) || StringUtils.contains(permittedCharacters, c))) { + ret = false; + break; + } + } + } + return ret; + } + + private boolean validateIntervalDuration(RangerValidityRecurrence recurrence, List validationFailures) { + boolean ret = true; + + if (!validationFailures.isEmpty() || validityPeriodEstimator == null) { + ret = false; + } else { + int minSchedulingInterval = 1; // In minutes + + String minutes = validityPeriodEstimator.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute); + if (!StringUtils.equals(minutes, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) { + minSchedulingInterval = StringUtils.isBlank(minutes) ? RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute.maximum + 1 : Integer.valueOf(minutes); + + if (minSchedulingInterval == RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute.maximum + 1) { + String hours = validityPeriodEstimator.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour); + if (!StringUtils.equals(hours, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) { + int hour = StringUtils.isBlank(hours) ? RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour.maximum + 1 :Integer.valueOf(hours); + minSchedulingInterval = hour * (RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute.maximum+1); + + if (hour == RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour.maximum + 1) { + String dayOfMonths = validityPeriodEstimator.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth); + String dayOfWeeks = validityPeriodEstimator.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek); + + int dayOfMonth = 1, dayOfWeek = 1; + if (!StringUtils.equals(dayOfMonths, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) { + dayOfMonth = StringUtils.isBlank(dayOfMonths) ? RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth.maximum + 1 : Integer.valueOf(dayOfMonths); + } + if (!StringUtils.equals(dayOfWeeks, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) { + dayOfWeek = StringUtils.isBlank(dayOfWeeks) ? RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek.maximum + 1 : Integer.valueOf(dayOfWeeks); + } + if (!StringUtils.equals(dayOfMonths, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD) || !StringUtils.equals(dayOfWeeks, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) { + int minDays = dayOfMonth > dayOfWeek ? dayOfWeek : dayOfMonth; + minSchedulingInterval = minDays*(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour.maximum+1)*(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute.maximum+1); + + if (dayOfMonth == (RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth.maximum+1) && dayOfWeek == (RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek.maximum+1)) { + String months = validityPeriodEstimator.getFieldValue(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month); + if (!StringUtils.equals(months, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) { + int month = StringUtils.isBlank(months) ? RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month.maximum + 1 :Integer.valueOf(months); + minSchedulingInterval = month * 28 * (RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour.maximum + 1) * (RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute.maximum + 1); + + if (month == RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month.maximum + 1) { + // Maximum interval is 1 year + minSchedulingInterval = 365 * (RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour.maximum + 1) * (RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute.maximum + 1); + } + } + } + } + } + } + } + } + if (RangerValidityRecurrence.ValidityInterval.getValidityIntervalInMinutes(recurrence.getInterval()) > minSchedulingInterval) { + if (LOG.isDebugEnabled()) { + LOG.warn("Specified scheduling interval:" + RangerValidityRecurrence.ValidityInterval.getValidityIntervalInMinutes(recurrence.getInterval()) + " minutes] is more than minimum possible scheduling interval:[" + minSchedulingInterval + " minutes]."); + LOG.warn("This may turn this (expected to be temporary) policy into effectively permanent policy."); + } + } + } + return ret; + } + + private boolean validateRanges(RangerValidityRecurrence recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec field, int minValidValue, int maxValidValue, List validationFailures) { + boolean ret = true; + + String value = null; + String fieldName = field.toString(); + + String noWhiteSpace = StringUtils.deleteWhitespace(recurrence.getSchedule().getFieldValue(field)); + String[] specs = StringUtils.split(noWhiteSpace, ","); + class Range { + private int lower; + private int upper; + private Range(int lower, int upper) { + this.lower = lower; + this.upper = upper; + } + } + class RangeComparator implements Comparator { + @Override + public int compare(Range me, Range other) { + int result; + result = Integer.compare(me.lower, other.lower); + if (result == 0) { + result = Integer.compare(me.upper, other.upper); + } + return result; + } + } + + List rangeOfValues = new ArrayList<>(); + + List values = new ArrayList<>(); + + for (String spec : specs) { + + if (StringUtils.isNotEmpty(spec)) { + // Range + if (spec.startsWith("-") || spec.endsWith("-")) { + validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "incorrect range spec")); + ret = false; + } else { + String[] ranges = StringUtils.split(spec, "-"); + if (ranges.length > 2) { + validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "incorrect range spec")); + ret = false; + } else if (ranges.length == 2) { + int val1 = minValidValue, val2 = maxValidValue; + if (!StringUtils.equals(ranges[0], RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) { + val1 = Integer.valueOf(ranges[0]); + if (val1 < minValidValue || val1 > maxValidValue) { + validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "incorrect lower range value")); + ret = false; + } + } else { + value = RangerValidityRecurrence.RecurrenceSchedule.WILDCARD; + } + if (!StringUtils.equals(ranges[1], RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) { + val2 = Integer.valueOf(ranges[1]); + if (val1 < minValidValue || val2 > maxValidValue) { + validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "incorrect upper range value")); + ret = false; + } + } else { + value = RangerValidityRecurrence.RecurrenceSchedule.WILDCARD; + } + if (ret) { + if (val1 >= val2) { + validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "incorrect range")); + ret = false; + } else { + value = RangerValidityRecurrence.RecurrenceSchedule.WILDCARD; + for (Range range : rangeOfValues) { + if (range.lower == val1 || range.upper == val2) { + validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "duplicate range")); + ret = false; + break; + } + } + if (ret) { + rangeOfValues.add(new Range(val1, val2)); + } + } + } + } else if (ranges.length == 1) { + if (!StringUtils.equals(ranges[0], RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) { + int val = Integer.valueOf(ranges[0]); + if (val < minValidValue || val > maxValidValue) { + validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "incorrect value")); + ret = false; + } else { + if (!StringUtils.equals(value, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) { + values.add(Integer.valueOf(ranges[0])); + } + } + } else { + value = RangerValidityRecurrence.RecurrenceSchedule.WILDCARD; + } + } else { + ret = false; + } + } + } + } + //if (ret) { + if (CollectionUtils.isNotEmpty(rangeOfValues)) { + rangeOfValues.sort( new RangeComparator()); + } + for (int i = 0; i < rangeOfValues.size(); i++) { + Range range = rangeOfValues.get(i); + int upper = range.upper; + for (int j = i+1; j < rangeOfValues.size(); j++) { + Range r = rangeOfValues.get(j); + if (upper < r.upper) { + validationFailures.add(new ValidationFailureDetails(0, fieldName, "", false, true, false, "overlapping range value")); + ret = false; + } + } + } + //} + if (ret) { + if (!StringUtils.equals(value, RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) { + + int minDiff = (values.size() <= 1) ? maxValidValue + 1 : Integer.MAX_VALUE; + + if (values.size() > 1) { + Collections.sort(values); + for (int i = 0; i < values.size() - 1; i++) { + int diff = values.get(i + 1) - values.get(i); + if (diff < minDiff) { + minDiff = diff; + } + int firstLastDiff = values.get(0) + (maxValidValue - minValidValue + 1) - values.get(values.size() - 1); + + if (minDiff > firstLastDiff) { + minDiff = firstLastDiff; + } + } + } + if (values.size() > 0) { + value = Integer.toString(minDiff); + } + } + validityPeriodEstimator.setFieldValue(field, value); + if (LOG.isDebugEnabled()) { + LOG.debug("Set " + field + " to " + value); + } + } + return ret; + } + + private String getNormalizedValue(RangerValidityRecurrence recurrence, RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec field) { + String ret = null; + + if (RangerValidityRecurrence.ValidityInterval.getValidityIntervalInMinutes(recurrence.getInterval()) > 0) { + String noWhiteSpace = StringUtils.deleteWhitespace(recurrence.getSchedule().getFieldValue(field)); + String[] specs = StringUtils.split(noWhiteSpace, ","); + + List values = new ArrayList<>(); + + for (String spec : specs) { + if (StringUtils.isNotBlank(spec)) { + values.add(spec); + } + } + if (values.size() > 0) { + Collections.sort(values); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < values.size(); i++) { + if (i != 0) { + sb.append(","); + } + sb.append(values.get(i)); + } + ret = sb.toString(); + } + } + return ret; + } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/RangerZoneResourceMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/RangerZoneResourceMatcher.java new file mode 100644 index 00000000000..1a56657ae2d --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/RangerZoneResourceMatcher.java @@ -0,0 +1,117 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model.validation; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.policyresourcematcher.RangerDefaultPolicyResourceMatcher; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceEvaluator; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; +import org.apache.atlas.plugin.resourcematcher.RangerResourceMatcher; +import org.apache.atlas.plugin.util.ServiceDefUtil; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +public class RangerZoneResourceMatcher implements RangerPolicyResourceEvaluator { + private static final Log LOG = LogFactory.getLog(RangerZoneResourceMatcher.class); + + private final String securityZoneName; + private final Map policyResource; + private final RangerPolicyResourceMatcher policyResourceMatcher; + private RangerServiceDef.RangerResourceDef leafResourceDef; + + public RangerZoneResourceMatcher(final String securityZoneName, final Map policyResource, final RangerServiceDef serviceDef) { + + RangerServiceDefHelper serviceDefHelper = new RangerServiceDefHelper(serviceDef); + final Collection resourceKeys = policyResource.keySet(); + + RangerDefaultPolicyResourceMatcher matcher = new RangerDefaultPolicyResourceMatcher(); + + matcher.setServiceDef(serviceDef); + matcher.setServiceDefHelper(serviceDefHelper); + + boolean found = false; + + for (String policyType : RangerPolicy.POLICY_TYPES) { + for (List hierarchy : serviceDefHelper.getResourceHierarchies(policyType)) { + if (serviceDefHelper.hierarchyHasAllResources(hierarchy, resourceKeys)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Found hierarchy for resource-keys:[" + resourceKeys + "], policy-type:[" + policyType + "]"); + } + matcher.setPolicyResources(policyResource, policyType); + found = true; + break; + } + } + if (found) { + break; + } + } + if (found) { + matcher.init(); + } else { + LOG.error("Cannot initialize matcher for RangerZoneResourceMatcher"); + } + + this.securityZoneName = securityZoneName; + this.policyResourceMatcher = matcher; + this.policyResource = policyResource; + this.leafResourceDef = ServiceDefUtil.getLeafResourceDef(serviceDef, getPolicyResource()); + } + + public String getSecurityZoneName() { return securityZoneName; } + + @Override + public long getId() { + return securityZoneName.hashCode(); + } + + @Override + public String getGuid() { + return null; + } + + @Override + public RangerPolicyResourceMatcher getPolicyResourceMatcher() { return policyResourceMatcher; } + + @Override + public Map getPolicyResource() { + return policyResource; + } + + @Override + public RangerResourceMatcher getResourceMatcher(String resourceName) { + return policyResourceMatcher != null ? policyResourceMatcher.getResourceMatcher(resourceName) : null; + } + + @Override + public boolean isAncestorOf(RangerServiceDef.RangerResourceDef resourceDef) { + return ServiceDefUtil.isAncestorOf(policyResourceMatcher.getServiceDef(), leafResourceDef, resourceDef); + } + + @Override + public String toString() { + return "{security-zone-name:[" + securityZoneName + "], policyResource=[" + policyResource +"]}"; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/ValidationFailureDetails.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/ValidationFailureDetails.java new file mode 100644 index 00000000000..925925eb0cf --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/ValidationFailureDetails.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model.validation; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.Objects; + +public class ValidationFailureDetails { + + private static final Log LOG = LogFactory.getLog(ValidationFailureDetails.class); + + final String _fieldName; + final String _subFieldName; + final boolean _missing; + final boolean _semanticError; + final boolean _internalError; + final String _reason; + final int _errorCode; + + public ValidationFailureDetails(int errorCode, String fieldName, String subFieldName, boolean missing, boolean semanticError, boolean internalError, String reason) { + _errorCode = errorCode; + _missing = missing; + _semanticError = semanticError; + _internalError = internalError; + _fieldName = fieldName; + _subFieldName = subFieldName; + _reason = reason; + } + + public String getFieldName() { + return _fieldName; + } + + public boolean isMissingRequiredValue() { + return _missing; + } + + public boolean isSemanticallyIncorrect() { + return _semanticError; + } + + String getType() { + if (_missing) return "missing"; + if (_semanticError) return "semantically incorrect"; + if (_internalError) return "internal error"; + return ""; + } + + public String getSubFieldName() { + return _subFieldName; + } + + @Override + public String toString() { + LOG.debug("ValidationFailureDetails.toString()"); + return String.format(" %s: error code[%d], reason[%s], field[%s], subfield[%s], type[%s]", "Validation failure", + _errorCode, _reason, _fieldName, _subFieldName, getType()); + } + + @Override + public int hashCode() { + return Objects.hash(_fieldName, _subFieldName, _missing, _semanticError, _internalError, _reason, _errorCode); + } + + @Override + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof ValidationFailureDetails)) { + return false; + } + ValidationFailureDetails that = (ValidationFailureDetails)obj; + return Objects.equals(_fieldName, that._fieldName) && + Objects.equals(_subFieldName, that._subFieldName) && + Objects.equals(_reason, that._reason) && + _internalError == that._internalError && + _missing == that._missing && + _semanticError == that._semanticError && + _errorCode == that._errorCode; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/ValidationFailureDetailsBuilder.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/ValidationFailureDetailsBuilder.java new file mode 100644 index 00000000000..5f040a1e590 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/model/validation/ValidationFailureDetailsBuilder.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model.validation; + +public class ValidationFailureDetailsBuilder { + protected String _fieldName; + protected boolean _missing; + protected boolean _semanticError; + protected String _reason; + protected String _subFieldName; + protected boolean _internalError; + protected int _errorCode; + + ValidationFailureDetailsBuilder becauseOf(String aReason) { + _reason = aReason; + return this; + } + + ValidationFailureDetailsBuilder isMissing() { + _missing = true; + return this; + } + + ValidationFailureDetailsBuilder isSemanticallyIncorrect() { + _semanticError = true; + return this; + } + + ValidationFailureDetailsBuilder field(String fieldName) { + _fieldName = fieldName; + return this; + } + + ValidationFailureDetails build() { + return new ValidationFailureDetails(_errorCode, _fieldName, _subFieldName, _missing, _semanticError, _internalError, _reason); + } + + ValidationFailureDetailsBuilder subField(String missingParameter) { + _subFieldName = missingParameter; + return this; + } + + ValidationFailureDetailsBuilder isAnInternalError() { + _internalError = true; + return this; + } + + ValidationFailureDetailsBuilder errorCode(int errorCode) { + _errorCode = errorCode; + return this; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/CacheMap.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/CacheMap.java new file mode 100644 index 00000000000..e44bd0fba16 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/CacheMap.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.LinkedHashMap; +import java.util.Map; + +public class CacheMap extends LinkedHashMap { + private static final long serialVersionUID = 1L; + private static final Log LOG = LogFactory.getLog(CacheMap.class); + + + private static final float RANGER_CACHE_DEFAULT_LOAD_FACTOR = 0.75f; + + protected int initialCapacity; + + public CacheMap(int initialCapacity) { + super(initialCapacity, CacheMap.RANGER_CACHE_DEFAULT_LOAD_FACTOR, true); // true for access-order + + this.initialCapacity = initialCapacity; + } + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + boolean result = size() > initialCapacity; + + if (LOG.isDebugEnabled()) { + LOG.debug("CacheMap.removeEldestEntry(), result:"+ result); + } + + return result; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/PolicyEngine.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/PolicyEngine.java new file mode 100644 index 00000000000..e35bac61e42 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/PolicyEngine.java @@ -0,0 +1,930 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.ListUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.contextenricher.RangerContextEnricher; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicyDelta; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.validation.RangerServiceDefHelper; +import org.apache.atlas.plugin.model.validation.RangerZoneResourceMatcher; +import org.apache.atlas.plugin.policyevaluator.RangerPolicyEvaluator; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; +import org.apache.atlas.plugin.resourcematcher.RangerAbstractResourceMatcher; +import org.apache.atlas.plugin.service.RangerAuthContext; +import org.apache.atlas.plugin.store.ServiceDefsUtil; +import org.apache.atlas.plugin.util.RangerPerfTracer; +import org.apache.atlas.plugin.util.RangerPolicyDeltaUtil; +import org.apache.atlas.plugin.util.RangerReadWriteLock; +import org.apache.atlas.plugin.util.RangerRoles; +import org.apache.atlas.plugin.util.ServicePolicies; +import org.apache.atlas.plugin.util.StringTokenReplacer; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class PolicyEngine { + private static final Log LOG = LogFactory.getLog(PolicyEngine.class); + + private static final Log PERF_POLICYENGINE_INIT_LOG = RangerPerfTracer.getPerfLogger("policyengine.init"); + private static final Log PERF_POLICYENGINE_REBALANCE_LOG = RangerPerfTracer.getPerfLogger("policyengine.rebalance"); + + private final RangerPolicyRepository policyRepository; + private final RangerPolicyRepository tagPolicyRepository; + private final List allContextEnrichers; + private final RangerPluginContext pluginContext; + private final Map zonePolicyRepositories = new HashMap<>(); + private final Map resourceZoneTrie = new HashMap<>(); + private final Map zoneTagServiceMap = new HashMap<>(); + private boolean useForwardedIPAddress; + private String[] trustedProxyAddresses; + private final Map tokenReplacers = new HashMap<>(); + + private final RangerReadWriteLock lock; + + public RangerReadWriteLock.RangerLock getReadLock() { + return lock.getReadLock(); + } + + public RangerReadWriteLock.RangerLock getWriteLock() { + return lock.getWriteLock(); + } + + public boolean getUseForwardedIPAddress() { + return useForwardedIPAddress; + } + + public void setUseForwardedIPAddress(boolean useForwardedIPAddress) { + this.useForwardedIPAddress = useForwardedIPAddress; + } + + public String[] getTrustedProxyAddresses() { + return trustedProxyAddresses; + } + + public void setTrustedProxyAddresses(String[] trustedProxyAddresses) { + this.trustedProxyAddresses = trustedProxyAddresses; + } + + public long getRoleVersion() { return this.pluginContext.getAuthContext().getRoleVersion(); } + + public void setRoles(RangerRoles roles) { this.pluginContext.getAuthContext().setRoles(roles); } + + public String getServiceName() { + return policyRepository.getServiceName(); + } + + public RangerServiceDef getServiceDef() { + return policyRepository.getServiceDef(); + } + + public long getPolicyVersion() { + return policyRepository.getPolicyVersion(); + } + + public RangerPolicyRepository getPolicyRepository() { + return policyRepository; + } + + public RangerPolicyRepository getTagPolicyRepository() { + return tagPolicyRepository; + } + + public Map getZonePolicyRepositories() { return zonePolicyRepositories; } + + public List getAllContextEnrichers() { return allContextEnrichers; } + + public RangerPluginContext getPluginContext() { return pluginContext; } + + public StringTokenReplacer getStringTokenReplacer(String resourceName) { + return tokenReplacers.get(resourceName); + } + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + + @Override + protected void finalize() throws Throwable { + try { + cleanup(); + } finally { + super.finalize(); + } + } + + public StringBuilder toString(StringBuilder sb) { + if (sb == null) { + sb = new StringBuilder(); + } + + sb.append("PolicyEngine={"); + + sb.append("serviceName={").append(this.getServiceName()).append("} "); + + sb.append("policyRepository={"); + if (policyRepository != null) { + policyRepository.toString(sb); + } + sb.append("} "); + + sb.append("tagPolicyRepository={"); + if (tagPolicyRepository != null) { + tagPolicyRepository.toString(sb); + } + sb.append("} "); + + sb.append(lock.toString()); + + sb.append("}"); + + return sb; + } + + public List getResourcePolicies(String zoneName) { + RangerPolicyRepository zoneResourceRepository = zonePolicyRepositories.get(zoneName); + + return zoneResourceRepository == null ? ListUtils.EMPTY_LIST : zoneResourceRepository.getPolicies(); + } + + Map getResourceZoneTrie() { + return resourceZoneTrie; + } + + public PolicyEngine(ServicePolicies servicePolicies, RangerPluginContext pluginContext, RangerRoles roles, boolean isUseReadWriteLock) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> PolicyEngine(" + ", " + servicePolicies + ", " + pluginContext + ")"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerPolicyEngine.init(hashCode=" + Integer.toHexString(System.identityHashCode(this)) + ")"); + + long freeMemory = Runtime.getRuntime().freeMemory(); + long totalMemory = Runtime.getRuntime().totalMemory(); + + PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory - freeMemory) + ", Free memory:" + freeMemory); + } + + this.pluginContext = pluginContext; + this.lock = new RangerReadWriteLock(isUseReadWriteLock); + + LOG.info("Policy engine will" + (isUseReadWriteLock ? " " : " not ") + "perform in place update while processing policy-deltas."); + + this.pluginContext.setAuthContext(new RangerAuthContext(null, roles)); + + RangerPolicyEngineOptions options = pluginContext.getConfig().getPolicyEngineOptions(); + + if(StringUtils.isBlank(options.evaluatorType) || StringUtils.equalsIgnoreCase(options.evaluatorType, RangerPolicyEvaluator.EVALUATOR_TYPE_AUTO)) { + options.evaluatorType = RangerPolicyEvaluator.EVALUATOR_TYPE_OPTIMIZED; + } + + policyRepository = new RangerPolicyRepository(servicePolicies, this.pluginContext); + + ServicePolicies.TagPolicies tagPolicies = servicePolicies.getTagPolicies(); + + if (!options.disableTagPolicyEvaluation + && tagPolicies != null + && !StringUtils.isEmpty(tagPolicies.getServiceName()) + && tagPolicies.getServiceDef() != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("PolicyEngine : Building tag-policy-repository for tag-service " + tagPolicies.getServiceName()); + } + + tagPolicyRepository = new RangerPolicyRepository(tagPolicies, this.pluginContext, servicePolicies.getServiceDef(), servicePolicies.getServiceName()); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("PolicyEngine : No tag-policy-repository for service " + servicePolicies.getServiceName()); + } + + tagPolicyRepository = null; + } + + List tmpList; + List tagContextEnrichers = tagPolicyRepository == null ? null :tagPolicyRepository.getContextEnrichers(); + List resourceContextEnrichers = policyRepository.getContextEnrichers(); + + if (CollectionUtils.isEmpty(tagContextEnrichers)) { + tmpList = resourceContextEnrichers; + } else if (CollectionUtils.isEmpty(resourceContextEnrichers)) { + tmpList = tagContextEnrichers; + } else { + tmpList = new ArrayList<>(tagContextEnrichers); + + tmpList.addAll(resourceContextEnrichers); + } + + this.allContextEnrichers = tmpList; + + if (MapUtils.isNotEmpty(servicePolicies.getSecurityZones())) { + buildZoneTrie(servicePolicies); + + for (Map.Entry zone : servicePolicies.getSecurityZones().entrySet()) { + RangerPolicyRepository policyRepository = new RangerPolicyRepository(servicePolicies, this.pluginContext, zone.getKey()); + + zonePolicyRepositories.put(zone.getKey(), policyRepository); + } + } + + for (RangerServiceDef.RangerResourceDef resourceDef : getServiceDef().getResources()) { + Map matchOptions = resourceDef.getMatcherOptions(); + + if (RangerAbstractResourceMatcher.getOptionReplaceTokens(matchOptions)) { + String delimiterPrefix = RangerAbstractResourceMatcher.getOptionDelimiterPrefix(matchOptions); + char delimiterStart = RangerAbstractResourceMatcher.getOptionDelimiterStart(matchOptions); + char delimiterEnd = RangerAbstractResourceMatcher.getOptionDelimiterEnd(matchOptions); + char escapeChar = RangerAbstractResourceMatcher.getOptionDelimiterEscape(matchOptions); + + StringTokenReplacer tokenReplacer = new StringTokenReplacer(delimiterStart, delimiterEnd, escapeChar, delimiterPrefix); + tokenReplacers.put(resourceDef.getName(), tokenReplacer); + } + } + + RangerPerfTracer.log(perf); + + if (PERF_POLICYENGINE_INIT_LOG.isDebugEnabled()) { + long freeMemory = Runtime.getRuntime().freeMemory(); + long totalMemory = Runtime.getRuntime().totalMemory(); + + PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory - freeMemory) + ", Free memory:" + freeMemory); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== PolicyEngine()"); + } + } + + public PolicyEngine cloneWithDelta(ServicePolicies servicePolicies) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> cloneWithDelta(" + Arrays.toString(servicePolicies.getPolicyDeltas().toArray()) + ", " + servicePolicies.getPolicyVersion() + ")"); + } + + final PolicyEngine ret; + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerPolicyEngine.cloneWithDelta()"); + } + + try (RangerReadWriteLock.RangerLock writeLock = getWriteLock()) { + if (LOG.isDebugEnabled()) { + if (writeLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + writeLock); + } + } + + RangerServiceDef serviceDef = this.getServiceDef(); + String serviceType = (serviceDef != null) ? serviceDef.getName() : ""; + boolean isValidDeltas = false; + + if (CollectionUtils.isNotEmpty(servicePolicies.getPolicyDeltas()) || MapUtils.isNotEmpty(servicePolicies.getSecurityZones())) { + isValidDeltas = CollectionUtils.isEmpty(servicePolicies.getPolicyDeltas()) || RangerPolicyDeltaUtil.isValidDeltas(servicePolicies.getPolicyDeltas(), serviceType); + + if (isValidDeltas) { + if (MapUtils.isNotEmpty(servicePolicies.getSecurityZones())) { + for (Map.Entry entry : servicePolicies.getSecurityZones().entrySet()) { + if (!RangerPolicyDeltaUtil.isValidDeltas(entry.getValue().getPolicyDeltas(), serviceType)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Invalid policy-deltas for security zone:[" + entry.getKey() + "]"); + } + + isValidDeltas = false; + break; + } + } + } + } + } + + if (isValidDeltas) { + if (writeLock.isLockingEnabled()) { + updatePolicyEngine(servicePolicies); + ret = this; + } else { + ret = new PolicyEngine(this, servicePolicies); + } + } else { + ret = null; + } + } + + RangerPerfTracer.log(perf); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== cloneWithDelta(" + Arrays.toString(servicePolicies.getPolicyDeltas().toArray()) + ", " + servicePolicies.getPolicyVersion() + ")"); + } + return ret; + } + + public RangerPolicyRepository getRepositoryForMatchedZone(RangerPolicy policy) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> PolicyEngine.getRepositoryForMatchedZone(" + policy + ")"); + } + + String zoneName = policy.getZoneName(); + final RangerPolicyRepository ret = getRepositoryForZone(zoneName); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== PolicyEngine.getRepositoryForMatchedZone(" + policy + ")"); + } + + return ret; + } + + public Set getMatchedZonesForResourceAndChildren(RangerAccessResource accessResource) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> PolicyEngine.getMatchedZonesForResourceAndChildren(" + accessResource + ")"); + } + + Set ret = null; + + if (MapUtils.isNotEmpty(this.resourceZoneTrie)) { + ret = getMatchedZonesForResourceAndChildren(accessResource.getAsMap(), accessResource); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== PolicyEngine.getMatchedZonesForResourceAndChildren(" + accessResource + ") : " + ret); + } + + return ret; + } + + public String getUniquelyMatchedZoneName(Map resourceAsMap) { + String ret = null; + Set matchedZones = getMatchedZonesForResourceAndChildren(resourceAsMap, convertToAccessResource(resourceAsMap)); + if (CollectionUtils.isNotEmpty(matchedZones) && matchedZones.size() == 1) { + String[] matchedZonesArray = new String[1]; + matchedZones.toArray(matchedZonesArray); + ret = matchedZonesArray[0]; + } + return ret; + } + + public RangerPolicyRepository getRepositoryForZone(String zoneName) { + final RangerPolicyRepository ret; + + if (LOG.isDebugEnabled()) { + LOG.debug("zoneName:[" + zoneName + "]"); + } + + if (StringUtils.isNotEmpty(zoneName)) { + ret = getZonePolicyRepositories().get(zoneName); + } else { + ret = getPolicyRepository(); + } + + if (ret == null) { + LOG.error("policyRepository for zoneName:[" + zoneName + "], serviceName:[" + getServiceName() + "], policyVersion:[" + getPolicyVersion() + "] is null!! ERROR!"); + } + + return ret; + } + + public boolean hasTagPolicies(RangerPolicyRepository tagPolicyRepository) { + return tagPolicyRepository != null && CollectionUtils.isNotEmpty(tagPolicyRepository.getPolicies()); + } + + public boolean hasResourcePolicies(RangerPolicyRepository policyRepository) { + return policyRepository != null && CollectionUtils.isNotEmpty(policyRepository.getPolicies()); + } + + public boolean isResourceZoneAssociatedWithTagService(String resourceZoneName) { + final boolean ret; + + if (StringUtils.isNotEmpty(resourceZoneName) && tagPolicyRepository != null && zoneTagServiceMap.get(resourceZoneName) != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Accessed resource is in a zone:[" + resourceZoneName + "] which is associated with the tag-service:[" + tagPolicyRepository.getServiceName() + "]"); + } + + ret = true; + } else { + ret = false; + } + + return ret; + } + + public void preCleanup(boolean isForced) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> PolicyEngine.preCleanup(isForced=" + isForced + ")"); + } + + if (policyRepository != null) { + policyRepository.preCleanup(isForced); + } + + if (tagPolicyRepository != null) { + tagPolicyRepository.preCleanup(isForced); + } + + if (MapUtils.isNotEmpty(this.zonePolicyRepositories)) { + for (Map.Entry entry : this.zonePolicyRepositories.entrySet()) { + entry.getValue().preCleanup(isForced); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== PolicyEngine.preCleanup(isForced=" + isForced + ")"); + } + } + + private Set getMatchedZonesForResourceAndChildren(Map resource, RangerAccessResource accessResource) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> PolicyEngine.getMatchedZonesForResourceAndChildren(" + resource + ", " + accessResource + ")"); + } + + Set ret = null; + + if (MapUtils.isNotEmpty(this.resourceZoneTrie)) { + Set smallestList = null; + RangerServiceDefHelper serviceDefHelper = policyRepository.getOptions().getServiceDefHelper(); + + List resourceKeys = resource == null ? new ArrayList<>() : serviceDefHelper.getOrderedResourceNames(resource.keySet()); + + for (String resourceDefName : resourceKeys) { + RangerResourceTrie trie = resourceZoneTrie.get(resourceDefName); + + if (trie == null) { + continue; + } + + Object resourceValues = resource.get(resourceDefName); + + Set zoneMatchersForResource = trie.getEvaluatorsForResource(resourceValues); + Set inheritedZoneMatchers = trie.getInheritedEvaluators(); + + if (LOG.isDebugEnabled()) { + LOG.debug("ResourceDefName:[" + resourceDefName + "], values:[" + resourceValues + "], matched-zones:[" + zoneMatchersForResource + "], inherited-zones:[" + inheritedZoneMatchers + "]"); + } + + if (smallestList != null) { + if (CollectionUtils.isEmpty(inheritedZoneMatchers) && CollectionUtils.isEmpty(zoneMatchersForResource)) { + smallestList = null; + } else if (CollectionUtils.isEmpty(inheritedZoneMatchers)) { + smallestList.retainAll(zoneMatchersForResource); + } else if (CollectionUtils.isEmpty(zoneMatchersForResource)) { + smallestList.retainAll(inheritedZoneMatchers); + } else { + Set smaller, bigger; + if (zoneMatchersForResource.size() < inheritedZoneMatchers.size()) { + smaller = zoneMatchersForResource; + bigger = inheritedZoneMatchers; + } else { + smaller = inheritedZoneMatchers; + bigger = zoneMatchersForResource; + } + Set tmp = new HashSet<>(); + if (smallestList.size() < smaller.size()) { + smallestList.stream().filter(smaller::contains).forEach(tmp::add); + smallestList.stream().filter(bigger::contains).forEach(tmp::add); + } else { + smaller.stream().filter(smallestList::contains).forEach(tmp::add); + if (smallestList.size() < bigger.size()) { + smallestList.stream().filter(bigger::contains).forEach(tmp::add); + } else { + bigger.stream().filter(smallestList::contains).forEach(tmp::add); + } + } + smallestList = tmp; + } + } else { + if (CollectionUtils.isEmpty(inheritedZoneMatchers) || CollectionUtils.isEmpty(zoneMatchersForResource)) { + Set tmp = CollectionUtils.isEmpty(inheritedZoneMatchers) ? zoneMatchersForResource : inheritedZoneMatchers; + smallestList = resourceKeys.size() == 1 || CollectionUtils.isEmpty(tmp) ? tmp : new HashSet<>(tmp); + } else { + smallestList = new HashSet<>(zoneMatchersForResource); + smallestList.addAll(inheritedZoneMatchers); + } + } + } + + if (CollectionUtils.isNotEmpty(smallestList)) { + final Set intersection = smallestList; + + if (LOG.isDebugEnabled()) { + LOG.debug("Resource:[" + resource + "], matched-zones:[" + intersection + "]"); + } + + if (intersection.size() > 0) { + ret = new HashSet<>(); + + for (RangerZoneResourceMatcher zoneMatcher : intersection) { + if (LOG.isDebugEnabled()) { + LOG.debug("Trying to match resource:[" + accessResource + "] using zoneMatcher:[" + zoneMatcher + "]"); + } + + // These are potential matches. Try to really match them + if (zoneMatcher.getPolicyResourceMatcher().isMatch(accessResource, RangerPolicyResourceMatcher.MatchScope.ANY, null)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Matched resource:[" + accessResource + "] using zoneMatcher:[" + zoneMatcher + "]"); + } + + // Actual match happened + ret.add(zoneMatcher.getSecurityZoneName()); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Did not match resource:[" + accessResource + "] using zoneMatcher:[" + zoneMatcher + "]"); + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("The following zone-names matched resource:[" + accessResource + "]: " + ret); + } + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== PolicyEngine.getMatchedZonesForResourceAndChildren(" + resource + ", " + accessResource + ") : " + ret); + } + + return ret; + } + + private RangerAccessResource convertToAccessResource(Map resource) { + RangerAccessResourceImpl ret = new RangerAccessResourceImpl(); + + ret.setServiceDef(getServiceDef()); + + for (Map.Entry entry : resource.entrySet()) { + ret.setValue(entry.getKey(), entry.getValue()); + } + + return ret; + } + + private PolicyEngine(final PolicyEngine other, ServicePolicies servicePolicies) { + this.useForwardedIPAddress = other.useForwardedIPAddress; + this.trustedProxyAddresses = other.trustedProxyAddresses; + this.pluginContext = other.pluginContext; + this.lock = other.lock; + + long policyVersion = servicePolicies.getPolicyVersion() != null ? servicePolicies.getPolicyVersion() : -1L; + List defaultZoneDeltas = new ArrayList<>(); + List defaultZoneDeltasForTagPolicies = new ArrayList<>(); + + getDeltasSortedByZones(other, servicePolicies, defaultZoneDeltas, defaultZoneDeltasForTagPolicies); + + if (other.policyRepository != null && CollectionUtils.isNotEmpty(defaultZoneDeltas)) { + this.policyRepository = new RangerPolicyRepository(other.policyRepository, defaultZoneDeltas, policyVersion); + } else { + this.policyRepository = shareWith(other.policyRepository); + } + + if (MapUtils.isEmpty(zonePolicyRepositories) && MapUtils.isNotEmpty(other.zonePolicyRepositories)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Existing engine contains some zonePolicyRepositories and new engine contains no zonePolicyRepositories"); + } + for (Map.Entry entry : other.zonePolicyRepositories.entrySet()) { + if (LOG.isDebugEnabled()) { + LOG.debug("Copying over zoneRepository for zone :[" + entry.getKey() + "]"); + } + RangerPolicyRepository otherZonePolicyRepository = entry.getValue(); + RangerPolicyRepository zonePolicyRepository = shareWith(otherZonePolicyRepository); + this.zonePolicyRepositories.put(entry.getKey(), zonePolicyRepository); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Existing engine contains no zonePolicyRepositories or new engine contains some zonePolicyRepositories"); + LOG.debug("Not copying zoneRepositories from existing engine, as they are already copied or modified"); + } + } + + if (servicePolicies.getTagPolicies() != null && CollectionUtils.isNotEmpty(defaultZoneDeltasForTagPolicies)) { + if (other.tagPolicyRepository == null) { + + if (LOG.isDebugEnabled()) { + LOG.debug("Current policy-engine does not have any tagPolicyRepository"); + } + // Only creates are expected + List tagPolicies = new ArrayList<>(); + + for (RangerPolicyDelta delta : defaultZoneDeltasForTagPolicies) { + if (delta.getChangeType() == RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE) { + tagPolicies.add(delta.getPolicy()); + } else { + LOG.warn("Expected changeType:[" + RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE + "], found policy-change-delta:[" + delta + "]"); + } + } + + servicePolicies.getTagPolicies().setPolicies(tagPolicies); + + this.tagPolicyRepository = new RangerPolicyRepository(servicePolicies.getTagPolicies(), this.pluginContext, servicePolicies.getServiceDef(), servicePolicies.getServiceName()); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Current policy-engine has a tagPolicyRepository"); + } + this.tagPolicyRepository = new RangerPolicyRepository(other.tagPolicyRepository, defaultZoneDeltasForTagPolicies, policyVersion); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Either no associated tag repository or no changes to tag policies"); + } + this.tagPolicyRepository = shareWith(other.tagPolicyRepository); + } + + List tmpList; + List tagContextEnrichers = tagPolicyRepository == null ? null :tagPolicyRepository.getContextEnrichers(); + List resourceContextEnrichers = policyRepository == null ? null : policyRepository.getContextEnrichers(); + + if (CollectionUtils.isEmpty(tagContextEnrichers)) { + tmpList = resourceContextEnrichers; + } else if (CollectionUtils.isEmpty(resourceContextEnrichers)) { + tmpList = tagContextEnrichers; + } else { + tmpList = new ArrayList<>(tagContextEnrichers); + + tmpList.addAll(resourceContextEnrichers); + } + + this.allContextEnrichers = tmpList; + + reorderPolicyEvaluators(); + } + + private void buildZoneTrie(ServicePolicies servicePolicies) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> PolicyEngine.buildZoneTrie()"); + } + + Map securityZones = servicePolicies.getSecurityZones(); + + if (MapUtils.isNotEmpty(securityZones)) { + RangerServiceDef serviceDef = servicePolicies.getServiceDef(); + List matchers = new ArrayList<>(); + + for (Map.Entry securityZone : securityZones.entrySet()) { + String zoneName = securityZone.getKey(); + ServicePolicies.SecurityZoneInfo zoneDetails = securityZone.getValue(); + + if (LOG.isDebugEnabled()) { + LOG.debug("Building matchers for zone:[" + zoneName +"]"); + } + + for (Map> resource : zoneDetails.getResources()) { + if (LOG.isDebugEnabled()) { + LOG.debug("Building matcher for resource:[" + resource + "] in zone:[" + zoneName +"]"); + } + + Map policyResources = new HashMap<>(); + + for (Map.Entry> entry : resource.entrySet()) { + String resourceDefName = entry.getKey(); + List resourceValues = entry.getValue(); + RangerPolicy.RangerPolicyResource policyResource = new RangerPolicy.RangerPolicyResource(); + policyResource.setIsExcludes(false); + policyResource.setIsRecursive(ServiceDefsUtil.isRecursiveEnabled(serviceDef, resourceDefName)); + policyResource.setValues(resourceValues); + policyResources.put(resourceDefName, policyResource); + } + + matchers.add(new RangerZoneResourceMatcher(zoneName, policyResources, serviceDef)); + + if (LOG.isDebugEnabled()) { + LOG.debug("Built matcher for resource:[" + resource +"] in zone:[" + zoneName + "]"); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Built all matchers for zone:[" + zoneName +"]"); + } + + if (zoneDetails.getContainsAssociatedTagService()) { + zoneTagServiceMap.put(zoneName, zoneName); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Built matchers for all Zones"); + } + + for (RangerServiceDef.RangerResourceDef resourceDef : serviceDef.getResources()) { + resourceZoneTrie.put(resourceDef.getName(), new RangerResourceTrie<>(resourceDef, matchers)); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== PolicyEngine.buildZoneTrie()"); + } + } + + private RangerPolicyRepository shareWith(RangerPolicyRepository other) { + if (other != null) { + other.setShared(); + } + + return other; + } + private void reorderPolicyEvaluators() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> reorderEvaluators()"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_REBALANCE_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_REBALANCE_LOG, "RangerPolicyEngine.reorderEvaluators()"); + } + + if (tagPolicyRepository != null) { + tagPolicyRepository.reorderPolicyEvaluators(); + } + if (policyRepository != null) { + policyRepository.reorderPolicyEvaluators(); + } + + RangerPerfTracer.log(perf); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== reorderEvaluators()"); + } + } + + private void cleanup() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> PolicyEngine.cleanup()"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerPolicyEngine.cleanUp(hashCode=" + Integer.toHexString(System.identityHashCode(this)) + ")"); + } + + preCleanup(false); + + if (policyRepository != null) { + policyRepository.cleanup(); + } + + if (tagPolicyRepository != null) { + tagPolicyRepository.cleanup(); + } + + if (MapUtils.isNotEmpty(this.zonePolicyRepositories)) { + for (Map.Entry entry : this.zonePolicyRepositories.entrySet()) { + entry.getValue().cleanup(); + } + } + + RangerPerfTracer.log(perf); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== PolicyEngine.cleanup()"); + } + } + + void updatePolicyEngine(ServicePolicies servicePolicies) { + List defaultZoneDeltas = new ArrayList<>(); + List defaultZoneDeltasForTagPolicies = new ArrayList<>(); + + getDeltasSortedByZones(this, servicePolicies, defaultZoneDeltas, defaultZoneDeltasForTagPolicies); + + if (this.policyRepository != null && CollectionUtils.isNotEmpty(defaultZoneDeltas)) { + this.policyRepository.reinit(defaultZoneDeltas); + } + + if (servicePolicies.getTagPolicies() != null && CollectionUtils.isNotEmpty(defaultZoneDeltasForTagPolicies)) { + if (this.tagPolicyRepository != null) { + this.tagPolicyRepository.reinit(defaultZoneDeltasForTagPolicies); + } else { + LOG.error("No previous tagPolicyRepository to update! Should not have come here!!"); + } + } + + reorderPolicyEvaluators(); + } + + private void getDeltasSortedByZones(PolicyEngine current, ServicePolicies servicePolicies, List defaultZoneDeltas, List defaultZoneDeltasForTagPolicies) { + + if (LOG.isDebugEnabled()) { + LOG.debug("==> getDeltasSortedByZones()"); + } + + long policyVersion = servicePolicies.getPolicyVersion() != null ? servicePolicies.getPolicyVersion() : -1L; + + if (CollectionUtils.isNotEmpty(defaultZoneDeltas)) { + LOG.warn("Emptying out defaultZoneDeltas!"); + defaultZoneDeltas.clear(); + } + if (CollectionUtils.isNotEmpty(defaultZoneDeltasForTagPolicies)) { + LOG.warn("Emptying out defaultZoneDeltasForTagPolicies!"); + defaultZoneDeltasForTagPolicies.clear(); + } + + if (MapUtils.isNotEmpty(servicePolicies.getSecurityZones())) { + buildZoneTrie(servicePolicies); + + Map> zoneDeltasMap = new HashMap<>(); + + for (Map.Entry zone : servicePolicies.getSecurityZones().entrySet()) { + String zoneName = zone.getKey(); + List deltas = zone.getValue().getPolicyDeltas(); + List zoneDeltas = new ArrayList<>(); + + if (StringUtils.isNotEmpty(zoneName)) { + zoneDeltasMap.put(zoneName, zoneDeltas); + + for (RangerPolicyDelta delta : deltas) { + zoneDeltas = zoneDeltasMap.get(zoneName); + zoneDeltas.add(delta); + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Security zones found in the service-policies:[" + zoneDeltasMap.keySet() + "]"); + } + + for (Map.Entry> entry : zoneDeltasMap.entrySet()) { + final String zoneName = entry.getKey(); + final List zoneDeltas = entry.getValue(); + final RangerPolicyRepository otherRepository = current.zonePolicyRepositories.get(zoneName); + final RangerPolicyRepository policyRepository; + + if (LOG.isDebugEnabled()) { + LOG.debug("zoneName:[" + zoneName + "], zoneDeltas:[" + Arrays.toString(zoneDeltas.toArray()) + "], doesOtherRepositoryExist:[" + (otherRepository != null) + "]"); + } + + if (CollectionUtils.isNotEmpty(zoneDeltas)) { + if (otherRepository == null) { + List policies = new ArrayList<>(); + + for (RangerPolicyDelta delta : zoneDeltas) { + if (delta.getChangeType() == RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE) { + policies.add(delta.getPolicy()); + } else { + LOG.warn("Expected changeType:[" + RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE + "], found policy-change-delta:[" + delta +"]"); + } + } + + servicePolicies.getSecurityZones().get(zoneName).setPolicies(policies); + + policyRepository = new RangerPolicyRepository(servicePolicies, current.pluginContext, zoneName); + } else { + policyRepository = new RangerPolicyRepository(otherRepository, zoneDeltas, policyVersion); + } + } else { + policyRepository = shareWith(otherRepository); + } + + zonePolicyRepositories.put(zoneName, policyRepository); + } + } + + List unzonedDeltas = servicePolicies.getPolicyDeltas(); + + if (LOG.isDebugEnabled()) { + LOG.debug("ServicePolicies.policyDeltas:[" + Arrays.toString(servicePolicies.getPolicyDeltas().toArray()) + "]"); + } + + for (RangerPolicyDelta delta : unzonedDeltas) { + if (servicePolicies.getServiceDef().getName().equals(delta.getServiceType())) { + defaultZoneDeltas.add(delta); + } else { + defaultZoneDeltasForTagPolicies.add(delta); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("defaultZoneDeltas:[" + Arrays.toString(defaultZoneDeltas.toArray()) + "]"); + LOG.debug("defaultZoneDeltasForTagPolicies:[" + Arrays.toString(defaultZoneDeltasForTagPolicies.toArray()) + "]"); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== getDeltasSortedByZones()"); + } + } +} + diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/PolicyEvaluatorForTag.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/PolicyEvaluatorForTag.java new file mode 100644 index 00000000000..4f6dad2992d --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/PolicyEvaluatorForTag.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import org.apache.atlas.plugin.contextenricher.RangerTagForEval; +import org.apache.atlas.plugin.policyevaluator.RangerPolicyEvaluator; + +import java.io.Serializable; +import java.util.Comparator; + +public class PolicyEvaluatorForTag { + public static final Comparator EVAL_ORDER_COMPARATOR = new PolicyEvalOrderComparator(); + public static final Comparator NAME_COMPARATOR = new PolicyNameComparator(); + + private final RangerPolicyEvaluator evaluator; + private final RangerTagForEval tag; + + PolicyEvaluatorForTag(RangerPolicyEvaluator evaluator, RangerTagForEval tag) { + this.evaluator = evaluator; + this.tag = tag; + } + + RangerPolicyEvaluator getEvaluator() { + return evaluator; + } + + RangerTagForEval getTag() { + return tag; + } + + static class PolicyNameComparator implements Comparator, Serializable { + @Override + public int compare(PolicyEvaluatorForTag me, PolicyEvaluatorForTag other) { + return RangerPolicyEvaluator.NAME_COMPARATOR.compare(me.getEvaluator(), other.getEvaluator()); + } + } + + static class PolicyEvalOrderComparator implements Comparator, Serializable { + @Override + public int compare(PolicyEvaluatorForTag me, PolicyEvaluatorForTag other) { + return RangerPolicyEvaluator.EVAL_ORDER_COMPARATOR.compare(me.getEvaluator(), other.getEvaluator()); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessRequest.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessRequest.java new file mode 100644 index 00000000000..31a32a01232 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessRequest.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public interface RangerAccessRequest { + String RANGER_ACCESS_REQUEST_SCOPE_STRING = "Scope"; + + RangerAccessResource getResource(); + + String getAccessType(); + + boolean isAccessorsRequested(); + + boolean isAccessTypeAny(); + + boolean isAccessTypeDelegatedAdmin(); + + String getUser(); + + Set getUserGroups(); + + Set getUserRoles(); + + Date getAccessTime(); + + String getClientIPAddress(); + + String getRemoteIPAddress(); + + List getForwardedAddresses(); + + String getClientType(); + + String getAction(); + + String getRequestData(); + + String getSessionId(); + + String getClusterName(); + + String getClusterType(); + + Map getContext(); + + RangerAccessRequest getReadOnlyCopy(); + + ResourceMatchingScope getResourceMatchingScope(); + + enum ResourceMatchingScope {SELF, SELF_OR_DESCENDANTS, SELF_OR_CHILD} +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessRequestImpl.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessRequestImpl.java new file mode 100644 index 00000000000..52bf384fabb --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessRequestImpl.java @@ -0,0 +1,373 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class RangerAccessRequestImpl implements RangerAccessRequest { + private static final Logger LOG = LoggerFactory.getLogger(RangerAccessRequestImpl.class); + + private RangerAccessResource resource; + private String accessType; + private String user; + private Set userGroups; + private Set userRoles; + private Date accessTime; + private String clientIPAddress; + private List forwardedAddresses; + private String remoteIPAddress; + private String clientType; + private String action; + private String requestData; + private String sessionId; + private Map context; + private String clusterName; + private String clusterType; + + private boolean isAccessorsRequested; + private boolean isAccessTypeAny; + private boolean isAccessTypeDelegatedAdmin; + private ResourceMatchingScope resourceMatchingScope = ResourceMatchingScope.SELF; + + public RangerAccessRequestImpl() { + this(null, null, null, null, null); + } + + public RangerAccessRequestImpl(RangerAccessResource resource, String accessType, String user, Set userGroups, Set userRoles) { + setResource(resource); + setAccessType(accessType); + setUser(user); + setUserGroups(userGroups); + setUserRoles(userRoles); + setForwardedAddresses(null); + + // set remaining fields to default value + setAccessTime(null); + setRemoteIPAddress(null); + setClientType(null); + setAction(null); + setRequestData(null); + setSessionId(null); + setContext(null); + setClusterName(null); + } + + public RangerAccessRequestImpl(RangerAccessRequest request) { + setResource(request.getResource()); + setAccessType(request.getAccessType()); + setAccessorsRequested(request.isAccessorsRequested()); + setUser(request.getUser()); + setUserGroups(request.getUserGroups()); + setUserRoles(request.getUserRoles()); + setForwardedAddresses(request.getForwardedAddresses()); + setAccessTime(request.getAccessTime()); + setRemoteIPAddress(request.getRemoteIPAddress()); + setClientType(request.getClientType()); + setAction(request.getAction()); + setRequestData(request.getRequestData()); + setSessionId(request.getSessionId()); + setContext(request.getContext()); + setClusterName(request.getClusterName()); + setResourceMatchingScope(request.getResourceMatchingScope()); + setClientIPAddress(request.getClientIPAddress()); + setClusterType(request.getClusterType()); + } + + @Override + public RangerAccessResource getResource() { + return resource; + } + + @Override + public String getAccessType() { + return accessType; + } + + @Override + public String getUser() { + return user; + } + + @Override + public Set getUserGroups() { + return userGroups; + } + + @Override + public Set getUserRoles() { + return userRoles; + } + + @Override + public Date getAccessTime() { + return accessTime; + } + + @Override + public String getClientIPAddress() { return clientIPAddress;} + + @Override + public String getRemoteIPAddress() { + return remoteIPAddress; + } + + @Override + public List getForwardedAddresses() { return forwardedAddresses; } + + @Override + public String getClientType() { + return clientType; + } + + @Override + public String getAction() { + return action; + } + + @Override + public String getRequestData() { + return requestData; + } + + @Override + public String getSessionId() { + return sessionId; + } + + @Override + public Map getContext() { + return context; + } + + @Override + public ResourceMatchingScope getResourceMatchingScope() { + return resourceMatchingScope; + } + + @Override + public boolean isAccessTypeAny() { + return isAccessTypeAny; + } + + @Override + public boolean isAccessTypeDelegatedAdmin() { + return isAccessTypeDelegatedAdmin; + } + + @Override + public boolean isAccessorsRequested() { + return isAccessorsRequested; + } + + public void setAccessorsRequested(boolean accessorsRequested) { + isAccessorsRequested = accessorsRequested; + } + + public void setResource(RangerAccessResource resource) { + this.resource = resource; + } + + public void setAccessType(String accessType) { + if (StringUtils.isEmpty(accessType)) { + accessType = RangerPolicyEngine.ANY_ACCESS; + } + + this.accessType = accessType; + isAccessTypeAny = StringUtils.equals(accessType, RangerPolicyEngine.ANY_ACCESS); + isAccessTypeDelegatedAdmin = StringUtils.equals(accessType, RangerPolicyEngine.ADMIN_ACCESS); + } + + public void setUser(String user) { + this.user = user; + } + + public void setUserGroups(Set userGroups) { + this.userGroups = (userGroups == null) ? new HashSet() : userGroups; + } + + public void setUserRoles(Set userRoles) { + this.userRoles = (userRoles == null) ? new HashSet() : userRoles; + } + + public void setAccessTime(Date accessTime) { + this.accessTime = accessTime; + } + + public void setClientIPAddress(String ipAddress) { + this.clientIPAddress = ipAddress; + } + + public void setForwardedAddresses(List forwardedAddresses) { + this.forwardedAddresses = (forwardedAddresses == null) ? new ArrayList() : forwardedAddresses; + } + + public void setRemoteIPAddress(String remoteIPAddress) { + this.remoteIPAddress = remoteIPAddress; + } + + public void setClientType(String clientType) { + this.clientType = clientType; + } + + public void setAction(String action) { + this.action = action; + } + + public void setRequestData(String requestData) { + this.requestData = requestData; + } + + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } + + public String getClusterName() { + return clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public String getClusterType() { + return clusterType; + } + + public void setClusterType(String clusterType) { + this.clusterType = clusterType; + } + + public void setResourceMatchingScope(ResourceMatchingScope scope) { this.resourceMatchingScope = scope; } + + public void setContext(Map context) { + this.context = (context == null) ? new HashMap() : context; + } + + public void extractAndSetClientIPAddress(boolean useForwardedIPAddress, String[]trustedProxyAddresses) { + String ip = getRemoteIPAddress(); + if (ip == null) { + ip = getClientIPAddress(); + } + + String newIp = ip; + + if (useForwardedIPAddress) { + if (LOG.isDebugEnabled()) { + LOG.debug("Using X-Forward-For..."); + } + if (CollectionUtils.isNotEmpty(getForwardedAddresses())) { + if (trustedProxyAddresses != null && trustedProxyAddresses.length > 0) { + if (StringUtils.isNotEmpty(ip)) { + for (String trustedProxyAddress : trustedProxyAddresses) { + if (StringUtils.equals(ip, trustedProxyAddress)) { + newIp = getForwardedAddresses().get(0); + break; + } + } + } + } else { + newIp = getForwardedAddresses().get(0); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("No X-Forwarded-For addresses in the access-request"); + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Old Remote/Client IP Address=" + ip + ", new IP Address=" + newIp); + } + setClientIPAddress(newIp); + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerAccessRequestImpl={"); + + sb.append("resource={").append(resource).append("} "); + sb.append("accessType={").append(accessType).append("} "); + sb.append("isAccessorsRequested=").append(isAccessorsRequested).append(","); + sb.append("user={").append(user).append("} "); + + sb.append("userGroups={"); + if(userGroups != null) { + for(String userGroup : userGroups) { + sb.append(userGroup).append(" "); + } + } + sb.append("} "); + + sb.append("userRoles={"); + if(userRoles != null) { + for(String role : userRoles) { + sb.append(role).append(" "); + } + } + sb.append("} "); + + sb.append("accessTime={").append(accessTime).append("} "); + sb.append("clientIPAddress={").append(getClientIPAddress()).append("} "); + sb.append("forwardedAddresses={").append(StringUtils.join(forwardedAddresses, " ")).append("} "); + sb.append("remoteIPAddress={").append(remoteIPAddress).append("} "); + sb.append("clientType={").append(clientType).append("} "); + sb.append("action={").append(action).append("} "); + sb.append("requestData={").append(requestData).append("} "); + sb.append("sessionId={").append(sessionId).append("} "); + sb.append("resourceMatchingScope={").append(resourceMatchingScope).append("} "); + sb.append("clusterName={").append(clusterName).append("} "); + sb.append("clusterType={").append(clusterType).append("} "); + + sb.append("context={"); + if(context != null) { + for(Map.Entry e : context.entrySet()) { + sb.append(e.getKey()).append("={").append(e.getValue()).append("} "); + } + } + sb.append("} "); + + sb.append("}"); + + return sb; + } + @Override + public RangerAccessRequest getReadOnlyCopy() { + return new RangerAccessRequestReadOnly(this); + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessRequestProcessor.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessRequestProcessor.java new file mode 100644 index 00000000000..e1ff23e711f --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessRequestProcessor.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +public interface RangerAccessRequestProcessor { + void preProcess(RangerAccessRequest request); + + default void enrich(RangerAccessRequest request) {} +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessRequestReadOnly.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessRequestReadOnly.java new file mode 100644 index 00000000000..e7fd1324cab --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessRequestReadOnly.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class RangerAccessRequestReadOnly implements RangerAccessRequest { + private final RangerAccessRequest source; + + // Cached here for reducing access overhead + private final RangerAccessResource resource; + private final Set userGroups; + private final Set userRoles; + private final List forwardedAddresses; + private final Map context; + + RangerAccessRequestReadOnly(final RangerAccessRequest source) { + this.source = source; + this.resource = source.getResource().getReadOnlyCopy(); + this.userGroups = Collections.unmodifiableSet(source.getUserGroups()); + this.userRoles = Collections.unmodifiableSet(source.getUserRoles()); + this.context = Collections.unmodifiableMap(source.getContext()); + this.forwardedAddresses = Collections.unmodifiableList(source.getForwardedAddresses()); + } + + @Override + public RangerAccessResource getResource() { return resource; } + + @Override + public String getAccessType() { return source.getAccessType(); } + + @Override + public boolean isAccessorsRequested() { + return source.isAccessorsRequested(); + } + + @Override + public boolean isAccessTypeAny() { return source.isAccessTypeAny(); } + + @Override + public boolean isAccessTypeDelegatedAdmin() { return source.isAccessTypeDelegatedAdmin(); } + + @Override + public String getUser() { return source.getUser(); } + + @Override + public Set getUserGroups() { return userGroups; } + + @Override + public Set getUserRoles() { return userRoles; } + + @Override + public Date getAccessTime() { return source.getAccessTime(); } + + @Override + public String getClientIPAddress() { return source.getClientIPAddress(); } + + @Override + public String getRemoteIPAddress() { return source.getRemoteIPAddress(); } + + @Override + public List getForwardedAddresses() { return forwardedAddresses; } + + @Override + public String getClientType() { return source.getClientType(); } + + @Override + public String getAction() { return source.getAction(); } + + @Override + public String getRequestData() { return source.getRequestData(); } + + @Override + public String getSessionId() { return source.getSessionId(); } + + @Override + public Map getContext() { return context; } + + @Override + public RangerAccessRequest getReadOnlyCopy() { return this; } + + @Override + public ResourceMatchingScope getResourceMatchingScope() { return source.getResourceMatchingScope(); } + + @Override + public String getClusterName() { return source.getClusterName(); } + + @Override + public String getClusterType() { return source.getClusterType(); } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResource.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResource.java new file mode 100644 index 00000000000..dec7ee8bf17 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResource.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import org.apache.atlas.plugin.model.RangerServiceDef; + +import java.util.Map; +import java.util.Set; + + +public interface RangerAccessResource { + String RESOURCE_SEP = "/"; + String RESOURCE_NAME_VAL_SEP = "="; + + String getOwnerUser(); + + boolean exists(String name); + + Object getValue(String name); + + RangerServiceDef getServiceDef(); + + Set getKeys(); + + String getLeafName(); + + String getAsString(); + + String getCacheKey(); + + Map getAsMap(); + + RangerAccessResource getReadOnlyCopy(); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResourceImpl.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResourceImpl.java new file mode 100644 index 00000000000..6ac4787c65b --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResourceImpl.java @@ -0,0 +1,268 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import org.apache.commons.lang.ObjectUtils; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerResourceDef; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class RangerAccessResourceImpl implements RangerMutableResource { + private String ownerUser; + private Map elements; + private String stringifiedValue; + private String stringifiedCacheKeyValue; + private String leafName; + private RangerServiceDef serviceDef; + + public RangerAccessResourceImpl() { + this(null, null); + } + + public RangerAccessResourceImpl(Map elements) { + this(elements, null); + } + + public RangerAccessResourceImpl(Map elements, String ownerUser) { + this.elements = elements; + this.ownerUser = ownerUser; + } + + @Override + public String getOwnerUser() { + return ownerUser; + } + + @Override + public boolean exists(String name) { + return elements != null && elements.containsKey(name); + } + + @Override + public Object getValue(String name) { + Object ret = null; + + if(elements != null && elements.containsKey(name)) { + ret = elements.get(name); + } + + return ret; + } + + @Override + public Set getKeys() { + Set ret = null; + + if(elements != null) { + ret = elements.keySet(); + } + + return ret; + } + + @Override + public void setOwnerUser(String ownerUser) { + this.ownerUser = ownerUser; + } + + @Override + public void setValue(String name, Object value) { + if(value == null) { + if(elements != null) { + elements.remove(name); + + if(elements.isEmpty()) { + elements = null; + } + } + } else { + if(elements == null) { + elements = new HashMap<>(); + } + elements.put(name, value); + } + + // reset, so that these will be computed again with updated elements + stringifiedValue = stringifiedCacheKeyValue = leafName = null; + } + + @Override + public void setServiceDef(final RangerServiceDef serviceDef) { + this.serviceDef = serviceDef; + this.stringifiedValue = this.stringifiedCacheKeyValue = this.leafName = null; + } + + @Override + public RangerServiceDef getServiceDef() { + return this.serviceDef; + } + + @Override + public String getLeafName() { + String ret = leafName; + + if(ret == null) { + if(serviceDef != null && serviceDef.getResources() != null) { + List resourceDefs = serviceDef.getResources(); + + for(int idx = resourceDefs.size() - 1; idx >= 0; idx--) { + RangerResourceDef resourceDef = resourceDefs.get(idx); + + if(resourceDef != null && exists(resourceDef.getName())) { + ret = leafName = resourceDef.getName(); + break; + } + } + } + } + + return ret; + } + + @Override + public String getAsString() { + String ret = stringifiedValue; + + if(ret == null) { + if(serviceDef != null && serviceDef.getResources() != null) { + StringBuilder sb = new StringBuilder(); + + for(RangerResourceDef resourceDef : serviceDef.getResources()) { + if(resourceDef == null || !exists(resourceDef.getName())) { + continue; + } + + if(sb.length() > 0) { + sb.append(RESOURCE_SEP); + } + + sb.append(getValue(resourceDef.getName())); + } + + if(sb.length() > 0) { + ret = stringifiedValue = sb.toString(); + } + } + } + + return ret; + } + + @Override + public String getCacheKey() { + String ret = stringifiedCacheKeyValue; + + if(ret == null) { + if(serviceDef != null && serviceDef.getResources() != null) { + StringBuilder sb = new StringBuilder(); + + for(RangerResourceDef resourceDef : serviceDef.getResources()) { + if(resourceDef == null || !exists(resourceDef.getName())) { + continue; + } + + if(sb.length() > 0) { + sb.append(RESOURCE_SEP); + } + + sb.append(resourceDef.getName()).append(RESOURCE_NAME_VAL_SEP).append(getValue(resourceDef.getName())); + } + + if(sb.length() > 0) { + ret = stringifiedCacheKeyValue = sb.toString(); + } + } + } + + return ret; + } + + @Override + public Map getAsMap() { + return elements == null ? Collections.EMPTY_MAP : Collections.unmodifiableMap(elements); + } + + @Override + public RangerAccessResource getReadOnlyCopy() { + return new RangerAccessResourceReadOnly(this); + } + + @Override + public boolean equals(Object obj) { + if(obj == null || !(obj instanceof RangerAccessResourceImpl)) { + return false; + } + + if(this == obj) { + return true; + } + + RangerAccessResourceImpl other = (RangerAccessResourceImpl) obj; + + return ObjectUtils.equals(ownerUser, other.ownerUser) && + ObjectUtils.equals(elements, other.elements); + } + + @Override + public int hashCode() { + int ret = 7; + + ret = 31 * ret + ObjectUtils.hashCode(ownerUser); + ret = 31 * ret + ObjectUtils.hashCode(elements); + + return ret; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerResourceImpl={"); + + sb.append("ownerUser={").append(ownerUser).append("} "); + + sb.append("elements={"); + if(elements != null) { + for(Map.Entry e : elements.entrySet()) { + sb.append(e.getKey()).append("=").append(e.getValue()).append("; "); + } + } + sb.append("} "); + + sb.append("}"); + + return sb; + } + + protected String getStringifiedValue() { return stringifiedValue; } + + protected void setStringifiedValue(String val) { this.stringifiedValue = val; } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResourceReadOnly.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResourceReadOnly.java new file mode 100644 index 00000000000..1556d15dc0f --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResourceReadOnly.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.atlas.plugin.model.RangerServiceDef; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class RangerAccessResourceReadOnly implements RangerAccessResource { + + private final RangerAccessResource source; + private final Set keys; + private final Map map; + + public RangerAccessResourceReadOnly(final RangerAccessResource source) { + this.source = source; + + // Cached here for reducing access overhead + Set sourceKeys = source.getKeys(); + + if (CollectionUtils.isEmpty(sourceKeys)) { + sourceKeys = new HashSet<>(); + } + this.keys = Collections.unmodifiableSet(sourceKeys); + + Map sourceMap = source.getAsMap(); + + if (MapUtils.isEmpty(sourceMap)) { + sourceMap = new HashMap<>(); + } + this.map = Collections.unmodifiableMap(sourceMap); + } + + public String getOwnerUser() { return source.getOwnerUser(); } + + public boolean exists(String name) { return source.exists(name); } + + public Object getValue(String name) { return source.getValue(name); } + + public RangerServiceDef getServiceDef() { return source.getServiceDef(); } + + public Set getKeys() { return keys; } + + public String getLeafName() { return source.getLeafName(); } + + public String getAsString() { return source.getAsString(); } + + public String getCacheKey() { return source.getCacheKey(); } + + public Map getAsMap() { return map; } + + public RangerAccessResource getReadOnlyCopy() { return this; } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResult.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResult.java new file mode 100644 index 00000000000..ab6d5f037b1 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResult.java @@ -0,0 +1,382 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.policyevaluator.RangerPolicyItemEvaluator; +import org.apache.atlas.plugin.util.ServiceDefUtil; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class RangerAccessResult { + public final static String KEY_MASK_TYPE = "maskType"; + public final static String KEY_MASK_CONDITION = "maskCondition"; + public final static String KEY_MASKED_VALUE = "maskedValue"; + + private static String KEY_FILTER_EXPR = "filterExpr"; + + private final String serviceName; + private final RangerServiceDef serviceDef; + private final RangerAccessRequest request; + + private final String policyType; // Really, policy-type for audit purpose + private boolean isAccessDetermined; + private boolean isAllowed; + private boolean isAuditedDetermined; + private boolean isAudited; + private String auditPolicyId = "-1"; + private String auditLogId; + private String policyId = "-1"; + private int policyPriority; + private String zoneName; + private Long policyVersion; + private long evaluatedPoliciesCount; + private String reason; + private Map additionalInfo; + private List matchedItemEvaluators = new ArrayList<>(); + + public RangerAccessResult(final String policyType, final String serviceName, final RangerServiceDef serviceDef, final RangerAccessRequest request) { + this.serviceName = serviceName; + this.serviceDef = serviceDef; + this.request = request; + this.policyType = policyType; + this.isAccessDetermined = false; + this.isAllowed = false; + this.isAuditedDetermined = false; + this.isAudited = false; + this.auditPolicyId = "-1"; + this.policyId = "-1"; + this.zoneName = null; + this.policyVersion = null; + this.policyPriority = RangerPolicy.POLICY_PRIORITY_NORMAL; + this.evaluatedPoliciesCount = 0; + this.reason = null; + } + + public void setAccessResultFrom(final RangerAccessResult other) { + this.isAccessDetermined = other.getIsAccessDetermined(); + this.isAllowed = other.getIsAllowed(); + this.policyId = other.getPolicyId(); + this.policyPriority = other.getPolicyPriority(); + this.zoneName = other.zoneName; + this.policyVersion = other.policyVersion; + this.evaluatedPoliciesCount = other.evaluatedPoliciesCount; + this.reason = other.getReason(); + this.additionalInfo = other.additionalInfo == null ? new HashMap() : new HashMap<>(other.additionalInfo); + this.matchedItemEvaluators = new ArrayList<>(other.matchedItemEvaluators); + } + + public void setAuditResultFrom(final RangerAccessResult other) { + this.isAuditedDetermined = other.getIsAuditedDetermined(); + this.isAudited = other.getIsAudited(); + this.auditPolicyId = other.getAuditPolicyId(); + this.policyVersion = other.policyVersion; + } + + /** + * @return the serviceName + */ + public String getServiceName() { + return serviceName; + } + + /** + * @return the serviceDef + */ + public RangerServiceDef getServiceDef() { + return serviceDef; + } + + /** + * @return the request + */ + public RangerAccessRequest getAccessRequest() { + return request; + } + + public String getPolicyType() { return policyType; } + + public boolean getIsAccessDetermined() { return isAccessDetermined; } + + public void setIsAccessDetermined(boolean value) { isAccessDetermined = value; } + + /** + * @return the isAllowed + */ + public boolean getIsAllowed() { + return isAllowed; + } + + /** + * @param isAllowed the isAllowed to set + */ + public void setIsAllowed(boolean isAllowed) { + if(! isAllowed) { + setIsAccessDetermined(true); + } + + this.isAllowed = isAllowed; + } + public int getPolicyPriority() { return policyPriority;} + + public void setPolicyPriority(int policyPriority) { this.policyPriority = policyPriority; } + + public String getZoneName() { return zoneName; } + + public void setZoneName(String zoneName) { this.zoneName = zoneName; } + + public Long getPolicyVersion() { return policyVersion; } + + public void setPolicyVersion(Long policyVersion) { this.policyVersion = policyVersion; } + + /** + * @param reason the reason to set + */ + public void setReason(String reason) { + this.reason = reason; + } + + public boolean getIsAuditedDetermined() { return isAuditedDetermined; } + + public void setIsAuditedDetermined(boolean value) { isAuditedDetermined = value; } + + /** + * @return the isAudited + */ + public boolean getIsAudited() { + return isAudited; + } + + + + /** + * @param isAudited the isAudited to set + */ + public void setIsAudited(boolean isAudited) { + setIsAuditedDetermined(true); + this.isAudited = isAudited; + } + + /** + * @return the reason + */ + public String getReason() { + return reason; + } + + /** + * @return the policyId + */ + public String getPolicyId() { + return policyId; + } + + /** + * @return the auditPolicyId + */ + public String getAuditPolicyId() { + return auditPolicyId; + } + + public long getEvaluatedPoliciesCount() { return this.evaluatedPoliciesCount; } + /** + * @param policyId the policyId to set + */ + public void setPolicyId(String policyId) { + this.policyId = policyId; + } + + public String getAuditLogId() { + return auditLogId; + } + + public void setAuditLogId(String auditLogId) { + this.auditLogId = auditLogId; + } + + + /** + * @param policyId the auditPolicyId to set + */ + public void setAuditPolicyId(String policyId) { + this.auditPolicyId = policyId; + } + + public void incrementEvaluatedPoliciesCount() { this.evaluatedPoliciesCount++; } + + public int getServiceType() { + int ret = -1; + + if(serviceDef != null && serviceDef.getId() != null) { + ret = serviceDef.getId().intValue(); + } + + return ret; + } + + public void setAdditionalInfo(Map additionalInfo) { + this.additionalInfo = additionalInfo; + } + + public Map getAdditionalInfo() { + return additionalInfo; + } + + public void addAdditionalInfo(String key, Object value) { + if (additionalInfo == null) { + additionalInfo = new HashMap(); + } + additionalInfo.put(key, value); + } + + public void removeAdditionalInfo(String key) { + if (MapUtils.isNotEmpty(additionalInfo)) { + additionalInfo.remove(key); + } + } + + public List getMatchedItemEvaluators() { + return matchedItemEvaluators; + } + + public void setMatchedItemEvaluators(List matchedItemEvaluators) { + this.matchedItemEvaluators = matchedItemEvaluators; + } + + public void addMatchedItemEvaluator(RangerPolicyItemEvaluator matchItemEvaluator) { + this.matchedItemEvaluators.add(matchItemEvaluator); + } + + /** + * @return the maskType + */ + public String getMaskType() { + return additionalInfo == null ? null : (String) additionalInfo.get(KEY_MASK_TYPE); + } + + /** + * @param maskType the maskType to set + */ + public void setMaskType(String maskType) { + addAdditionalInfo(KEY_MASK_TYPE, maskType); + } + + /** + * @return the maskCondition + */ + public String getMaskCondition() { + return additionalInfo == null ? null : (String) additionalInfo.get(KEY_MASK_CONDITION); + } + + /** + * @param maskCondition the maskCondition to set + */ + public void setMaskCondition(String maskCondition) { + addAdditionalInfo(KEY_MASK_CONDITION, maskCondition); + } + + /** + * @return the maskedValue + */ + public String getMaskedValue() { + return additionalInfo == null ? null : (String) additionalInfo.get(KEY_MASKED_VALUE); + } + /** + * @param maskedValue the maskedValue to set + */ + public void setMaskedValue(String maskedValue) { + addAdditionalInfo(KEY_MASKED_VALUE, maskedValue); + } + + public boolean isMaskEnabled() { + return StringUtils.isNotEmpty(this.getMaskType()) && !StringUtils.equalsIgnoreCase(this.getMaskType(), RangerPolicy.MASK_TYPE_NONE); + } + + public RangerServiceDef.RangerDataMaskTypeDef getMaskTypeDef() { + RangerServiceDef.RangerDataMaskTypeDef ret = null; + + String maskType = getMaskType(); + if(StringUtils.isNotEmpty(maskType)) { + ret = ServiceDefUtil.getDataMaskType(getServiceDef(), maskType); + } + + return ret; + } + + /** + * @return the filterExpr + */ + public String getFilterExpr() { + return additionalInfo == null ? null : (String) additionalInfo.get(KEY_FILTER_EXPR); + } + + /** + * @param filterExpr the filterExpr to set + */ + public void setFilterExpr(String filterExpr) { + addAdditionalInfo(KEY_FILTER_EXPR, filterExpr); + } + + public boolean isRowFilterEnabled() { + return StringUtils.isNotEmpty(getFilterExpr()); + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerAccessResult={"); + + sb.append("isAccessDetermined={").append(isAccessDetermined).append("} "); + sb.append("isAllowed={").append(isAllowed).append("} "); + sb.append("isAuditedDetermined={").append(isAuditedDetermined).append("} "); + sb.append("isAudited={").append(isAudited).append("} "); + sb.append("auditLogId={").append(auditLogId).append("} "); + sb.append("policyType={").append(policyType).append("} "); + sb.append("policyId={").append(policyId).append("} "); + sb.append("zoneName={").append(zoneName).append("} "); + sb.append("auditPolicyId={").append(auditPolicyId).append("} "); + sb.append("policyVersion={").append(policyVersion).append("} "); + sb.append("evaluatedPoliciesCount={").append(evaluatedPoliciesCount).append("} "); + sb.append("reason={").append(reason).append("} "); + sb.append("additionalInfo={"); + if (additionalInfo != null) { + for (Map.Entry entry : additionalInfo.entrySet()) { + sb.append(entry.getKey()).append("=").append(entry.getValue()).append(", "); + } + } + sb.append("}"); + + sb.append("}"); + + return sb; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResultProcessor.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResultProcessor.java new file mode 100644 index 00000000000..7b1374106ea --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerAccessResultProcessor.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import java.util.Collection; + + +public interface RangerAccessResultProcessor { + void processResult(RangerAccessResult result); + + void processResults(Collection results); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerMutableResource.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerMutableResource.java new file mode 100644 index 00000000000..7b7e038b376 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerMutableResource.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + + +import org.apache.atlas.plugin.model.RangerServiceDef; + +public interface RangerMutableResource extends RangerAccessResource { + void setOwnerUser(String ownerUser); + + void setValue(String type, Object value); + void setServiceDef(RangerServiceDef serviceDef); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPluginContext.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPluginContext.java new file mode 100644 index 00000000000..aed2c768754 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPluginContext.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import org.apache.atlas.authz.admin.client.AtlasAuthAdminClient; +import org.apache.atlas.authz.admin.client.AtlasAuthRESTClient; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.authorization.config.RangerPluginConfig; +import org.apache.atlas.plugin.service.RangerAuthContext; +import org.apache.atlas.plugin.service.RangerAuthContextListener; + +public class RangerPluginContext { + private static final Log LOG = LogFactory.getLog(RangerPluginContext.class); + + private final RangerPluginConfig config; + private RangerAuthContext authContext; + private RangerAuthContextListener authContextListener; + private AtlasAuthAdminClient atlasAdminClient; + + + public RangerPluginContext(RangerPluginConfig config) { + this.config = config; + } + + public RangerPluginConfig getConfig() { return config; } + + public String getClusterName() { + return config.getClusterName(); + } + + public String getClusterType() { + return config.getClusterType(); + } + + public RangerAuthContext getAuthContext() { return authContext; } + + public void setAuthContext(RangerAuthContext authContext) { this.authContext = authContext; } + + public void setAuthContextListener(RangerAuthContextListener authContextListener) { this.authContextListener = authContextListener; } + + public void notifyAuthContextChanged() { + RangerAuthContextListener authContextListener = this.authContextListener; + + if (authContextListener != null) { + authContextListener.contextChanged(); + } + } + + public AtlasAuthAdminClient getAtlasAuthAdminClient() { + if (atlasAdminClient == null) { + atlasAdminClient = initAtlasAuthAdminClient(); + } + + return atlasAdminClient; + } + + private AtlasAuthAdminClient initAtlasAuthAdminClient() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerBasePlugin.createAdminClient(" + config.getServiceName() + ", " + config.getAppId() + ", " + config.getPropertyPrefix() + ")"); + } + + AtlasAuthAdminClient ret = null; + String propertyName = config.getPropertyPrefix() + ".policy.source.impl"; + String policySourceImpl = config.get(propertyName); + + if(StringUtils.isEmpty(policySourceImpl)) { + if (LOG.isDebugEnabled()) { + LOG.error("Value for property[%s] was null or empty"); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug(String.format("Value for property[%s] was [%s].", propertyName, policySourceImpl)); + } + + try { + @SuppressWarnings("unchecked") + Class adminClass = (Class)Class.forName(policySourceImpl); + + ret = adminClass.newInstance(); + } catch (Exception excp) { + LOG.error("failed to instantiate policy source of type " + policySourceImpl ); + } + } + + if(ret == null) { + ret = new AtlasAuthRESTClient(); + } + + ret.init(config); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerBasePlugin.createAdminClient(" + config.getServiceName() + ", " + config.getAppId() + ", " + config.getPropertyPrefix() + "): policySourceImpl=" + policySourceImpl + ", client=" + ret); + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPolicyEngine.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPolicyEngine.java new file mode 100644 index 00000000000..98852f910d1 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPolicyEngine.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.util.GrantRevokeRequest; +import org.apache.atlas.plugin.util.RangerAccessRequestUtil; +import org.apache.atlas.plugin.util.RangerRoles; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +public interface RangerPolicyEngine { + String GROUP_PUBLIC = "public"; + String ANY_ACCESS = "_any"; + String ADMIN_ACCESS = "_admin"; + String SUPER_USER_ACCESS = "_super_user"; + + String AUDIT_ALL = "audit-all"; + String AUDIT_NONE = "audit-none"; + String AUDIT_DEFAULT = "audit-default"; + + String PLUGIN_AUDIT_EXCLUDE_USERS = "ranger.plugin.audit.exclude.users"; + String PLUGIN_AUDIT_EXCLUDE_GROUPS = "ranger.plugin.audit.exclude.groups"; + String PLUGIN_AUDIT_EXCLUDE_ROLES = "ranger.plugin.audit.exclude.roles"; + String PLUGIN_SUPER_USERS = "ranger.plugin.super.users"; + String PLUGIN_SUPER_GROUPS = "ranger.plugin.super.groups"; + String PLUGIN_AUDIT_FILTER = "ranger.plugin.audit.filters"; + String PLUGIN_SERVICE_ADMINS = "ranger.plugin.service.admins"; + + String USER_CURRENT = "{" + RangerAccessRequestUtil.KEY_USER + "}"; + String RESOURCE_OWNER = "{OWNER}"; + + void setUseForwardedIPAddress(boolean useForwardedIPAddress); + + void setTrustedProxyAddresses(String[] trustedProxyAddresses); + + RangerServiceDef getServiceDef(); + + long getPolicyVersion(); + + long getRoleVersion(); + + void setRoles(RangerRoles roles); + + RangerAccessResult evaluatePolicies(RangerAccessRequest request, String policyType, RangerAccessResultProcessor resultProcessor); + + Collection evaluatePolicies(Collection requests, String policyType, RangerAccessResultProcessor resultProcessor); + + void evaluateAuditPolicies(RangerAccessResult result); + + RangerResourceACLs getResourceACLs(RangerAccessRequest request); + + RangerResourceACLs getResourceACLs(RangerAccessRequest request, String requestedPolicyType); + + Set getRolesFromUserAndGroups(String user, Set groups); + + RangerRoles getRangerRoles(); + + RangerPluginContext getPluginContext(); + + String getUniquelyMatchedZoneName(GrantRevokeRequest grantRevokeRequest); + + // Helpers + + List getResourcePolicies(String zoneName); + + List getResourcePolicies(); + + List getTagPolicies(); + + // This API is used only used by test code + RangerResourceAccessInfo getResourceAccessInfo(RangerAccessRequest request); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPolicyEngineImpl.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPolicyEngineImpl.java new file mode 100644 index 00000000000..02e845a6fb4 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPolicyEngineImpl.java @@ -0,0 +1,1351 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.ListUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.atlas.authorization.config.RangerPluginConfig; +import org.apache.atlas.authorization.utils.RangerUtil; +import org.apache.atlas.plugin.contextenricher.RangerTagForEval; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemRowFilterInfo; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.policyengine.RangerResourceACLs.DataMaskResult; +import org.apache.atlas.plugin.policyengine.RangerResourceACLs.RowFilterResult; +import org.apache.atlas.plugin.policyevaluator.RangerPolicyEvaluator; +import org.apache.atlas.plugin.policyevaluator.RangerPolicyEvaluator.PolicyACLSummary; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher.MatchType; +import org.apache.atlas.plugin.service.RangerDefaultRequestProcessor; +import org.apache.atlas.plugin.util.GrantRevokeRequest; +import org.apache.atlas.plugin.util.RangerAccessRequestUtil; +import org.apache.atlas.plugin.util.RangerCommonConstants; +import org.apache.atlas.plugin.util.RangerPerfTracer; +import org.apache.atlas.plugin.util.RangerReadWriteLock; +import org.apache.atlas.plugin.util.RangerRoles; +import org.apache.atlas.plugin.util.ServicePolicies; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.apache.atlas.plugin.policyevaluator.RangerPolicyEvaluator.ACCESS_CONDITIONAL; + +public class RangerPolicyEngineImpl implements RangerPolicyEngine { + private static final Log LOG = LogFactory.getLog(RangerPolicyEngineImpl.class); + + private static final Log PERF_POLICYENGINE_REQUEST_LOG = RangerPerfTracer.getPerfLogger("policyengine.request"); + private static final Log PERF_POLICYENGINE_AUDIT_LOG = RangerPerfTracer.getPerfLogger("policyengine.audit"); + private static final Log PERF_POLICYENGINE_GET_ACLS_LOG = RangerPerfTracer.getPerfLogger("policyengine.getResourceACLs"); + + private final PolicyEngine policyEngine; + private final RangerAccessRequestProcessor requestProcessor; + private final ServiceConfig serviceConfig; + + + static public RangerPolicyEngine getPolicyEngine(final RangerPolicyEngineImpl other, final ServicePolicies servicePolicies) { + RangerPolicyEngine ret = null; + + if (other != null && servicePolicies != null) { + PolicyEngine policyEngine = other.policyEngine.cloneWithDelta(servicePolicies); + + if (policyEngine != null) { + if (policyEngine == other.policyEngine) { + ret = other; + } else { + ret = new RangerPolicyEngineImpl(policyEngine, other); + } + } + } + + return ret; + } + + public RangerPolicyEngineImpl(ServicePolicies servicePolicies, RangerPluginContext pluginContext, RangerRoles roles) { + final boolean isUseReadWriteLock; + + Configuration config = pluginContext != null ? pluginContext.getConfig() : null; + + if (config != null) { + boolean isDeltasSupported = config.getBoolean(pluginContext.getConfig().getPropertyPrefix() + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_POLICY_DELTA, RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_POLICY_DELTA_DEFAULT); + isUseReadWriteLock = isDeltasSupported && config.getBoolean(pluginContext.getConfig().getPropertyPrefix() + RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_IN_PLACE_POLICY_UPDATES, RangerCommonConstants.PLUGIN_CONFIG_SUFFIX_IN_PLACE_POLICY_UPDATES_DEFAULT); + } else { + isUseReadWriteLock = false; + } + + policyEngine = new PolicyEngine(servicePolicies, pluginContext, roles, isUseReadWriteLock); + serviceConfig = new ServiceConfig(servicePolicies.getServiceConfig()); + requestProcessor = new RangerDefaultRequestProcessor(policyEngine); + } + + @Override + public String toString() { + return policyEngine.toString(); + } + + @Override + public RangerAccessResult evaluatePolicies(RangerAccessRequest request, String policyType, RangerAccessResultProcessor resultProcessor) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.evaluatePolicies(" + request + ", policyType=" + policyType + ")"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_REQUEST_LOG)) { + String requestHashCode = Integer.toHexString(System.identityHashCode(request)) + "_" + policyType; + + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_REQUEST_LOG, "RangerPolicyEngine.evaluatePolicies(requestHashCode=" + requestHashCode + ")"); + } + + RangerAccessResult ret; + + try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) { + if (LOG.isDebugEnabled()) { + if (readLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + readLock); + } + } + + requestProcessor.preProcess(request); + + ret = zoneAwareAccessEvaluationWithNoAudit(request, policyType); + + if (resultProcessor != null) { + RangerPerfTracer perfAuditTracer = null; + + if (RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_AUDIT_LOG)) { + String requestHashCode = Integer.toHexString(System.identityHashCode(request)) + "_" + policyType; + + perfAuditTracer = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_AUDIT_LOG, "RangerPolicyEngine.processAudit(requestHashCode=" + requestHashCode + ")"); + } + + resultProcessor.processResult(ret); + + RangerPerfTracer.log(perfAuditTracer); + } + } + + RangerPerfTracer.log(perf); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.evaluatePolicies(" + request + ", policyType=" + policyType + "): " + ret); + } + + return ret; + } + + @Override + public Collection evaluatePolicies(Collection requests, String policyType, RangerAccessResultProcessor resultProcessor) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.evaluatePolicies(" + requests + ", policyType=" + policyType + ")"); + } + + Collection ret = new ArrayList<>(); + + try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) { + if (LOG.isDebugEnabled()) { + if (readLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + readLock); + } + } + if (requests != null) { + for (RangerAccessRequest request : requests) { + requestProcessor.preProcess(request); + + RangerAccessResult result = zoneAwareAccessEvaluationWithNoAudit(request, policyType); + + ret.add(result); + } + } + + if (resultProcessor != null) { + resultProcessor.processResults(ret); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.evaluatePolicies(" + requests + ", policyType=" + policyType + "): " + ret); + } + + return ret; + } + + @Override + public void evaluateAuditPolicies(RangerAccessResult result) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.evaluateAuditPolicies(result=" + result + ")"); + } + + try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) { + if (LOG.isDebugEnabled()) { + if (readLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + readLock); + } + } + + RangerPolicyRepository tagPolicyRepository = policyEngine.getTagPolicyRepository(); + RangerPolicyRepository policyRepository = policyEngine.getPolicyRepository(); + RangerAccessRequest request = result.getAccessRequest(); + boolean savedIsAuditedDetermined = result.getIsAuditedDetermined(); + boolean savedIsAudited = result.getIsAudited(); + + result.setIsAudited(false); + result.setIsAuditedDetermined(false); + + try { + if (tagPolicyRepository != null) { + evaluateTagAuditPolicies(request, result, tagPolicyRepository); + } + + if (!result.getIsAuditedDetermined() && policyRepository != null) { + evaluateResourceAuditPolicies(request, result, policyRepository); + } + } finally { + if (!result.getIsAuditedDetermined()) { + result.setIsAudited(savedIsAudited); + result.setIsAuditedDetermined(savedIsAuditedDetermined); + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.evaluateAuditPolicies(result=" + result + ")"); + } + } + + @Override + public RangerResourceACLs getResourceACLs(RangerAccessRequest request) { + return getResourceACLs(request, null); + } + + @Override + public RangerResourceACLs getResourceACLs(RangerAccessRequest request, String requestedPolicyType) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.getResourceACLs(request=" + request + ", policyType=" + requestedPolicyType + ")"); + } + + RangerResourceACLs ret = new RangerResourceACLs(); + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_GET_ACLS_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_GET_ACLS_LOG, "RangerPolicyEngine.getResourceACLs(requestHashCode=" + request.getResource().getAsString() + ")"); + } + + try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) { + if (LOG.isDebugEnabled()) { + if (readLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + readLock); + } + } + + requestProcessor.preProcess(request); + + String zoneName = policyEngine.getUniquelyMatchedZoneName(request.getResource().getAsMap()); + + if (LOG.isDebugEnabled()) { + LOG.debug("zoneName:[" + zoneName + "]"); + } + + String[] policyTypes = StringUtils.isEmpty(requestedPolicyType) ? RangerPolicy.POLICY_TYPES : new String[] { requestedPolicyType }; + + + for (String policyType : policyTypes) { + List allEvaluators = new ArrayList<>(); + Map tagMatchTypeMap = new HashMap<>(); + Set policyIdForTemporalTags = new HashSet<>(); + + getResourceACLEvaluatorsForZone(request, zoneName, policyType, allEvaluators, tagMatchTypeMap, policyIdForTemporalTags); + + allEvaluators.sort(RangerPolicyEvaluator.EVAL_ORDER_COMPARATOR); + + if (CollectionUtils.isEmpty(allEvaluators)) { + continue; + } + + Integer policyPriority = null; + + for (RangerPolicyEvaluator evaluator : allEvaluators) { + if (policyPriority == null) { + policyPriority = evaluator.getPolicyPriority(); + } + + if (policyPriority != evaluator.getPolicyPriority()) { + if (RangerPolicy.POLICY_TYPE_ACCESS.equals(policyType)) { + ret.finalizeAcls(); + } + + policyPriority = evaluator.getPolicyPriority(); + } + + MatchType matchType = tagMatchTypeMap.get(evaluator.getId()); + + if (matchType == null) { + matchType = evaluator.getPolicyResourceMatcher().getMatchType(request.getResource(), request.getContext()); + } + + final boolean isMatched; + + if (request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS) { + isMatched = matchType != MatchType.NONE; + } else { + isMatched = matchType == MatchType.SELF || matchType == MatchType.SELF_AND_ALL_DESCENDANTS; + } + + if (!isMatched) { + continue; + } + + if (RangerPolicy.POLICY_TYPE_ACCESS.equals(policyType)) { + updateFromPolicyACLs(evaluator, policyIdForTemporalTags, ret); + } else if (RangerPolicy.POLICY_TYPE_ROWFILTER.equals(policyType)) { + updateRowFiltersFromPolicy(evaluator, policyIdForTemporalTags, ret); + } else if (RangerPolicy.POLICY_TYPE_DATAMASK.equals(policyType)) { + updateDataMasksFromPolicy(evaluator, policyIdForTemporalTags, ret); + } + } + + ret.finalizeAcls(); + } + } + + RangerPerfTracer.logAlways(perf); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.getResourceACLs(request=" + request + ", policyType=" + requestedPolicyType + ") : ret=" + ret); + } + + return ret; + } + + @Override + public void setUseForwardedIPAddress(boolean useForwardedIPAddress) { + try (RangerReadWriteLock.RangerLock writeLock = policyEngine.getWriteLock()) { + if (LOG.isDebugEnabled()) { + if (writeLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + writeLock); + } + } + policyEngine.setUseForwardedIPAddress(useForwardedIPAddress); + } + } + + @Override + public void setTrustedProxyAddresses(String[] trustedProxyAddresses) { + try (RangerReadWriteLock.RangerLock writeLock = policyEngine.getWriteLock()) { + if (LOG.isDebugEnabled()) { + if (writeLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + writeLock); + } + } + policyEngine.setTrustedProxyAddresses(trustedProxyAddresses); + } + } + + @Override + public RangerServiceDef getServiceDef() { + final RangerServiceDef ret; + + try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) { + if (LOG.isDebugEnabled()) { + if (readLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + readLock); + } + } + ret = policyEngine.getServiceDef(); + } + return ret; + } + + @Override + public long getPolicyVersion() { + long ret; + + try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) { + if (LOG.isDebugEnabled()) { + if (readLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + readLock); + } + } + ret = policyEngine.getPolicyVersion(); + } + return ret; + } + + @Override + public long getRoleVersion() { return policyEngine.getRoleVersion(); } + + @Override + public void setRoles(RangerRoles roles) { + try (RangerReadWriteLock.RangerLock writeLock = policyEngine.getWriteLock()) { + if (LOG.isDebugEnabled()) { + if (writeLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + writeLock); + } + } + policyEngine.setRoles(roles); + } + + } + + @Override + public Set getRolesFromUserAndGroups(String user, Set groups) { + Set ret; + try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) { + if (LOG.isDebugEnabled()) { + if (readLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + readLock); + } + } + ret = policyEngine.getPluginContext().getAuthContext().getRolesForUserAndGroups(user, groups); + } + return ret; + } + + @Override + public RangerRoles getRangerRoles() { + return policyEngine.getPluginContext().getAuthContext().getRangerRolesUtil().getRoles(); + } + + @Override + public RangerPluginContext getPluginContext() { + return policyEngine.getPluginContext(); + } + + @Override + public String getUniquelyMatchedZoneName(GrantRevokeRequest grantRevokeRequest) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.getUniquelyMatchedZoneName(" + grantRevokeRequest + ")"); + } + + String ret; + + try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) { + if (LOG.isDebugEnabled()) { + if (readLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + readLock); + } + } + ret = policyEngine.getUniquelyMatchedZoneName(grantRevokeRequest.getResource()); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.getUniquelyMatchedZoneName(" + grantRevokeRequest + ") : " + ret); + } + + return ret; + } + + @Override + public List getResourcePolicies(String zoneName) { + List ret; + + try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) { + if (LOG.isDebugEnabled()) { + if (readLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + readLock); + } + } + List oldPolicies = policyEngine.getResourcePolicies(zoneName); + ret = CollectionUtils.isNotEmpty(oldPolicies) ? new ArrayList<>(oldPolicies) : oldPolicies; + } + + return ret; + } + + @Override + public List getResourcePolicies() { + List ret; + + try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) { + if (LOG.isDebugEnabled()) { + if (readLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + readLock); + } + } + RangerPolicyRepository policyRepository = policyEngine.getPolicyRepository(); + List oldPolicies = policyRepository == null ? ListUtils.EMPTY_LIST : policyRepository.getPolicies(); + ret = CollectionUtils.isNotEmpty(oldPolicies) ? new ArrayList<>(oldPolicies) : oldPolicies; + } + return ret; + } + + @Override + public List getTagPolicies() { + List ret; + + try (RangerReadWriteLock.RangerLock readLock = policyEngine.getReadLock()) { + if (LOG.isDebugEnabled()) { + if (readLock.isLockingEnabled()) { + LOG.debug("Acquired lock - " + readLock); + } + } + RangerPolicyRepository tagPolicyRepository = policyEngine.getTagPolicyRepository(); + List oldPolicies = tagPolicyRepository == null ? ListUtils.EMPTY_LIST : tagPolicyRepository.getPolicies(); + ret = CollectionUtils.isNotEmpty(oldPolicies) ? new ArrayList<>(oldPolicies) : oldPolicies; + } + return ret; + } + + // This API is used only used by test code + @Override + public RangerResourceAccessInfo getResourceAccessInfo(RangerAccessRequest request) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.getResourceAccessInfo(" + request + ")"); + } + + requestProcessor.preProcess(request); + + RangerResourceAccessInfo ret = new RangerResourceAccessInfo(request); + Set zoneNames = policyEngine.getMatchedZonesForResourceAndChildren(request.getResource()); + + if (LOG.isDebugEnabled()) { + LOG.debug("zoneNames:[" + zoneNames + "]"); + } + + if (CollectionUtils.isEmpty(zoneNames)) { + getResourceAccessInfoForZone(request, ret, null); + } else { + for (String zoneName : zoneNames) { + getResourceAccessInfoForZone(request, ret, zoneName); + + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.getResourceAccessInfo(" + request + "): " + ret); + } + + return ret; + } + + public void releaseResources(boolean isForced) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.releaseResources(isForced=" + isForced + ")"); + } + + PolicyEngine policyEngine = this.policyEngine; + + if (policyEngine != null) { + policyEngine.preCleanup(isForced); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Cannot preCleanup policy-engine as it is null!"); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.releaseResources(isForced=" + isForced + ")"); + } + } + + public boolean isServiceAdmin(String userName) { + boolean ret = serviceConfig.isServiceAdmin(userName); + + if (!ret) { + + RangerPluginConfig pluginConfig = policyEngine.getPluginContext().getConfig(); + + ret = pluginConfig.isServiceAdmin(userName); + } + + return ret; + } + + PolicyEngine getPolicyEngine() { + return policyEngine; + } + + private RangerPolicyEngineImpl(final PolicyEngine policyEngine, RangerPolicyEngineImpl other) { + this.policyEngine = policyEngine; + this.requestProcessor = new RangerDefaultRequestProcessor(policyEngine); + this.serviceConfig = new ServiceConfig(other.serviceConfig); + } + + private RangerAccessResult zoneAwareAccessEvaluationWithNoAudit(RangerAccessRequest request, String policyType) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.zoneAwareAccessEvaluationWithNoAudit(" + request + ", policyType =" + policyType + ")"); + } + + RangerAccessResult ret = null; + RangerPolicyRepository policyRepository = policyEngine.getPolicyRepository(); + RangerPolicyRepository tagPolicyRepository = policyEngine.getTagPolicyRepository(); + Set zoneNames = policyEngine.getMatchedZonesForResourceAndChildren(request.getResource()); // Evaluate zone-name from request + + if (LOG.isDebugEnabled()) { + LOG.debug("zoneNames:[" + zoneNames + "]"); + } + + if (CollectionUtils.isEmpty(zoneNames) || (zoneNames.size() > 1 && !request.isAccessTypeAny())) { + // Evaluate default policies + policyRepository = policyEngine.getRepositoryForZone(null); + + ret = evaluatePoliciesNoAudit(request, policyType, null, policyRepository, tagPolicyRepository); + + ret.setZoneName(null); + } else if (zoneNames.size() == 1 || request.isAccessTypeAny()) { + // Evaluate zone specific policies + for (String zoneName : zoneNames) { + policyRepository = policyEngine.getRepositoryForZone(zoneName); + + ret = evaluatePoliciesNoAudit(request, policyType, zoneName, policyRepository, tagPolicyRepository); + ret.setZoneName(zoneName); + + if (ret.getIsAllowed()) { + if (LOG.isDebugEnabled()) { + LOG.debug("Zone:[" + zoneName + "] allowed access. Completed processing other zones"); + } + break; + } + } + } + + if (request.isAccessTypeAny() && (request.getResource() == null || CollectionUtils.isEmpty(request.getResource().getKeys())) && ret != null && !ret.getIsAllowed() && MapUtils.isNotEmpty(policyEngine.getZonePolicyRepositories())) { + // resource is empty and access is ANY + if (LOG.isDebugEnabled()) { + LOG.debug("Process all security-zones"); + } + RangerAccessResult accessResult; + + for (Map.Entry entry : policyEngine.getZonePolicyRepositories().entrySet()) { + String someZone = entry.getKey(); + policyRepository = entry.getValue(); + + if (LOG.isDebugEnabled()) { + LOG.debug("Evaluating policies for zone:[" + someZone + "]"); + } + + if (policyRepository != null) { + accessResult = evaluatePoliciesNoAudit(request, policyType, someZone, policyRepository, tagPolicyRepository); + + if (accessResult.getIsAllowed()) { + if (LOG.isDebugEnabled()) { + LOG.debug("Zone:[" + someZone + "] allowed access. Completed processing other zones"); + } + accessResult.setZoneName(someZone); + ret = accessResult; + break; + } + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.zoneAwareAccessEvaluationWithNoAudit(" + request + ", policyType =" + policyType + "): " + ret); + } + + return ret; + } + + private RangerAccessResult evaluatePoliciesNoAudit(RangerAccessRequest request, String policyType, String zoneName, RangerPolicyRepository policyRepository, RangerPolicyRepository tagPolicyRepository) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.evaluatePoliciesNoAudit(" + request + ", policyType =" + policyType + ", zoneName=" + zoneName + ")"); + } + + final RangerAccessResult ret; + + if (request.isAccessTypeAny()) { + RangerAccessResult denyResult = null; + RangerAccessResult allowResult = null; + + ret = createAccessResult(request, policyType); + + List allAccessDefs = getServiceDef().getAccessTypes(); + + for (RangerServiceDef.RangerAccessTypeDef accessTypeDef : allAccessDefs) { + RangerAccessRequestImpl requestForOneAccessType = new RangerAccessRequestImpl(request); + RangerAccessRequestUtil.setIsAnyAccessInContext(requestForOneAccessType.getContext(), Boolean.TRUE); + + requestForOneAccessType.setAccessType(accessTypeDef.getName()); + + RangerAccessResult resultForOneAccessType = evaluatePoliciesForOneAccessTypeNoAudit(requestForOneAccessType, policyType, zoneName, policyRepository, tagPolicyRepository); + + ret.setAuditResultFrom(resultForOneAccessType); + + if (resultForOneAccessType.getIsAccessDetermined()) { + if (resultForOneAccessType.getIsAllowed()) { + allowResult = resultForOneAccessType; + break; + } else if (denyResult == null) { + denyResult = resultForOneAccessType; + } + } + } + + if (allowResult != null) { + ret.setAccessResultFrom(allowResult); + } else if (denyResult != null) { + ret.setAccessResultFrom(denyResult); + } + } else { + ret = evaluatePoliciesForOneAccessTypeNoAudit(request, policyType, zoneName, policyRepository, tagPolicyRepository); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.evaluatePoliciesNoAudit(" + request + ", policyType =" + policyType + ", zoneName=" + zoneName + "): " + ret); + } + + return ret; + } + + private RangerAccessResult evaluatePoliciesForOneAccessTypeNoAudit(RangerAccessRequest request, String policyType, String zoneName, RangerPolicyRepository policyRepository, RangerPolicyRepository tagPolicyRepository) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.evaluatePoliciesForOneAccessTypeNoAudit(" + request + ", policyType =" + policyType + ", zoneName=" + zoneName + ")"); + } + + final boolean isSuperUser = isSuperUser(request.getUser(), request.getUserGroups()); + final Date accessTime = request.getAccessTime() != null ? request.getAccessTime() : new Date(); + final RangerAccessResult ret = createAccessResult(request, policyType); + + if (isSuperUser || StringUtils.equals(request.getAccessType(), RangerPolicyEngine.SUPER_USER_ACCESS)) { + ret.setIsAllowed(isSuperUser); + ret.setIsAccessDetermined(true); + ret.setPolicyId("-1"); + ret.setPolicyPriority(Integer.MAX_VALUE); + ret.setReason("superuser"); + } + + evaluateTagPolicies(request, policyType, zoneName, tagPolicyRepository, ret); + + if (LOG.isDebugEnabled()) { + if (ret.getIsAccessDetermined() && ret.getIsAuditedDetermined()) { + if (!ret.getIsAllowed()) { + LOG.debug("RangerPolicyEngineImpl.evaluatePoliciesNoAudit() - audit determined and access denied by a tag policy. Higher priority resource policies will be evaluated to check for allow, request=" + request + ", result=" + ret); + } else { + LOG.debug("RangerPolicyEngineImpl.evaluatePoliciesNoAudit() - audit determined and access allowed by a tag policy. Same or higher priority resource policies will be evaluated to check for deny, request=" + request + ", result=" + ret); + } + } + } + + boolean isAllowedByTags = ret.getIsAccessDetermined() && ret.getIsAllowed(); + boolean isDeniedByTags = ret.getIsAccessDetermined() && !ret.getIsAllowed(); + boolean evaluateResourcePolicies = policyEngine.hasResourcePolicies(policyRepository); + + if (evaluateResourcePolicies) { + boolean findAuditByResource = !ret.getIsAuditedDetermined(); + boolean foundInCache = findAuditByResource && policyRepository.setAuditEnabledFromCache(request, ret); + + ret.setIsAccessDetermined(false); // discard result by tag-policies, to evaluate resource policies for possible override + + List evaluators = policyRepository.getLikelyMatchPolicyEvaluators(request, policyType); + + for (RangerPolicyEvaluator evaluator : evaluators) { + if (!evaluator.isApplicable(accessTime)) { + continue; + } + + if (isDeniedByTags) { + if (ret.getPolicyPriority() >= evaluator.getPolicyPriority()) { + ret.setIsAccessDetermined(true); + } + } else if (ret.getIsAllowed()) { + if (ret.getPolicyPriority() > evaluator.getPolicyPriority()) { + ret.setIsAccessDetermined(true); + } + } + + ret.incrementEvaluatedPoliciesCount(); + evaluator.evaluate(request, ret); + + if (ret.getIsAllowed()) { + if (!evaluator.hasDeny()) { // No more deny policies left + ret.setIsAccessDetermined(true); + } + } + + if (ret.getIsAuditedDetermined() && ret.getIsAccessDetermined() && !request.isAccessorsRequested()) { + break; + } + } + + if (!ret.getIsAccessDetermined()) { + if (isDeniedByTags) { + ret.setIsAllowed(false); + } else if (isAllowedByTags) { + ret.setIsAllowed(true); + } + if (!ret.getIsAllowed() && + !getIsFallbackSupported()) { + ret.setIsAccessDetermined(true); + } + } + + if (ret.getIsAllowed()) { + ret.setIsAccessDetermined(true); + } + + if (findAuditByResource && !foundInCache) { + policyRepository.storeAuditEnabledInCache(request, ret); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.evaluatePoliciesForOneAccessTypeNoAudit(" + request + ", policyType =" + policyType + ", zoneName=" + zoneName + "): " + ret); + } + + return ret; + } + + private void evaluateTagPolicies(final RangerAccessRequest request, String policyType, String zoneName, RangerPolicyRepository tagPolicyRepository, RangerAccessResult result) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.evaluateTagPolicies(" + request + ", policyType =" + policyType + ", zoneName=" + zoneName + ", " + result + ")"); + } + + Date accessTime = request.getAccessTime() != null ? request.getAccessTime() : new Date(); + Set tags = RangerAccessRequestUtil.getRequestTagsFromContext(request.getContext()); + List policyEvaluators = tagPolicyRepository == null ? null : tagPolicyRepository.getLikelyMatchPolicyEvaluators(request, tags, policyType, accessTime); + + if (CollectionUtils.isNotEmpty(policyEvaluators)) { + final boolean useTagPoliciesFromDefaultZone = !policyEngine.isResourceZoneAssociatedWithTagService(zoneName); + + for (PolicyEvaluatorForTag policyEvaluator : policyEvaluators) { + RangerPolicyEvaluator evaluator = policyEvaluator.getEvaluator(); + String policyZoneName = evaluator.getPolicy().getZoneName(); + + if (useTagPoliciesFromDefaultZone) { + if (StringUtils.isNotEmpty(policyZoneName)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Tag policy [zone:" + policyZoneName + "] does not belong to default zone. Not evaluating this policy:[" + evaluator.getPolicy() + "]"); + } + + continue; + } + } else { + if (!StringUtils.equals(zoneName, policyZoneName)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Tag policy [zone:" + policyZoneName + "] does not belong to the zone:[" + zoneName + "] of the accessed resource. Not evaluating this policy:[" + evaluator.getPolicy() + "]"); + } + + continue; + } + } + + RangerTagForEval tag = policyEvaluator.getTag(); + RangerAccessRequest tagEvalRequest = new RangerTagAccessRequest(tag, tagPolicyRepository.getServiceDef(), request); + RangerAccessResult tagEvalResult = createAccessResult(tagEvalRequest, policyType); + + if (LOG.isDebugEnabled()) { + LOG.debug("RangerPolicyEngineImpl.evaluateTagPolicies: Evaluating policies for tag (" + tag.getType() + ")"); + } + + tagEvalResult.setAccessResultFrom(result); + tagEvalResult.setAuditResultFrom(result); + + result.incrementEvaluatedPoliciesCount(); + + evaluator.evaluate(tagEvalRequest, tagEvalResult); + + if (tagEvalResult.getIsAllowed()) { + if (!evaluator.hasDeny()) { // No Deny policies left now + tagEvalResult.setIsAccessDetermined(true); + } + } + + if (tagEvalResult.getIsAudited()) { + result.setAuditResultFrom(tagEvalResult); + } + + if (!result.getIsAccessDetermined()) { + if (tagEvalResult.getIsAccessDetermined()) { + result.setAccessResultFrom(tagEvalResult); + } else { + if (!result.getIsAllowed() && tagEvalResult.getIsAllowed()) { + result.setAccessResultFrom(tagEvalResult); + } + } + } + + if (result.getIsAuditedDetermined() && result.getIsAccessDetermined() && !request.isAccessorsRequested()) { + break; // Break out of policy-evaluation loop + } + } + } + + if (result.getIsAllowed()) { + result.setIsAccessDetermined(true); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.evaluateTagPolicies(" + request + ", policyType =" + policyType + ", zoneName=" + zoneName + ", " + result + ")"); + } + } + + private RangerAccessResult createAccessResult(RangerAccessRequest request, String policyType) { + RangerPolicyRepository repository = policyEngine.getPolicyRepository(); + RangerAccessResult ret = new RangerAccessResult(policyType, repository.getServiceName(), repository.getServiceDef(), request); + + switch (repository.getAuditModeEnum()) { + case AUDIT_ALL: + ret.setIsAudited(true); + break; + + case AUDIT_NONE: + ret.setIsAudited(false); + break; + + default: + if (CollectionUtils.isEmpty(repository.getPolicies()) && policyEngine.getTagPolicyRepository() == null) { + ret.setIsAudited(true); + } + + break; + } + + if (isAuditExcludedUser(request.getUser(), request.getUserGroups(), RangerAccessRequestUtil.getCurrentUserRolesFromContext(request.getContext()))) { + ret.setIsAudited(false); + } + + return ret; + } + + private boolean isAuditExcludedUser(String userName, Set userGroups, Set userRoles) { + boolean ret = serviceConfig.isAuditExcludedUser(userName); + + if (!ret) { + RangerPluginConfig pluginConfig = policyEngine.getPluginContext().getConfig(); + + ret = pluginConfig.isAuditExcludedUser(userName); + + if (!ret && userGroups != null && userGroups.size() > 0) { + ret = serviceConfig.hasAuditExcludedGroup(userGroups) || pluginConfig.hasAuditExcludedGroup(userGroups); + } + + if (!ret && userRoles != null && userRoles.size() > 0) { + ret = serviceConfig.hasAuditExcludedRole(userRoles) || pluginConfig.hasAuditExcludedRole(userRoles); + } + } + + return ret; + } + + private boolean isSuperUser(String userName, Set userGroups) { + boolean ret = serviceConfig.isSuperUser(userName); + + if (!ret) { + RangerPluginConfig pluginConfig = policyEngine.getPluginContext().getConfig(); + + ret = pluginConfig.isSuperUser(userName); + + if (!ret && userGroups != null && userGroups.size() > 0) { + ret = serviceConfig.hasSuperGroup(userGroups) || pluginConfig.hasSuperGroup(userGroups); + } + } + + return ret; + } + + private void getResourceACLEvaluatorsForZone(RangerAccessRequest request, String zoneName, String policyType, List allEvaluators, Map tagMatchTypeMap, Set policyIdForTemporalTags) { + final RangerPolicyRepository matchedRepository = policyEngine.getRepositoryForZone(zoneName); + + if (matchedRepository == null) { + LOG.error("policyRepository for zoneName:[" + zoneName + "], serviceName:[" + policyEngine.getPolicyRepository().getServiceName() + "], policyVersion:[" + getPolicyVersion() + "] is null!! ERROR!"); + } else { + Set tags = RangerAccessRequestUtil.getRequestTagsFromContext(request.getContext()); + List tagPolicyEvaluators = policyEngine.getTagPolicyRepository() == null ? null : policyEngine.getTagPolicyRepository().getLikelyMatchPolicyEvaluators(request, tags, policyType, null); + + if (CollectionUtils.isNotEmpty(tagPolicyEvaluators)) { + + final boolean useTagPoliciesFromDefaultZone = !policyEngine.isResourceZoneAssociatedWithTagService(zoneName); + + for (PolicyEvaluatorForTag tagEvaluator : tagPolicyEvaluators) { + RangerPolicyEvaluator evaluator = tagEvaluator.getEvaluator(); + String policyZoneName = evaluator.getPolicy().getZoneName(); + + if (useTagPoliciesFromDefaultZone) { + if (StringUtils.isNotEmpty(policyZoneName)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Tag policy [zone:" + policyZoneName + "] does not belong to default zone. Not evaluating this policy:[" + evaluator.getPolicy() + "]"); + } + + continue; + } + } else { + if (!StringUtils.equals(zoneName, policyZoneName)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Tag policy [zone:" + policyZoneName + "] does not belong to the zone:[" + zoneName + "] of the accessed resource. Not evaluating this policy:[" + evaluator.getPolicy() + "]"); + } + + continue; + } + } + + RangerTagForEval tag = tagEvaluator.getTag(); + + allEvaluators.add(evaluator); + tagMatchTypeMap.put(evaluator.getId(), tag.getMatchType()); + + if (CollectionUtils.isNotEmpty(tag.getValidityPeriods())) { + policyIdForTemporalTags.add(evaluator.getId()); + } + } + } + + List resourcePolicyEvaluators = matchedRepository.getLikelyMatchPolicyEvaluators(request, policyType); + + allEvaluators.addAll(resourcePolicyEvaluators); + } + } + + private void getResourceAccessInfoForZone(RangerAccessRequest request, RangerResourceAccessInfo ret, String zoneName) { + final RangerPolicyRepository matchedRepository = policyEngine.getRepositoryForZone(zoneName); + + if (matchedRepository == null) { + LOG.error("policyRepository for zoneName:[" + zoneName + "], serviceName:[" + policyEngine.getPolicyRepository().getServiceName() + "], policyVersion:[" + getPolicyVersion() + "] is null!! ERROR!"); + } else { + List tagPolicyEvaluators = policyEngine.getTagPolicyRepository() == null ? null : policyEngine.getTagPolicyRepository().getPolicyEvaluators(); + + if (CollectionUtils.isNotEmpty(tagPolicyEvaluators)) { + Set tags = RangerAccessRequestUtil.getRequestTagsFromContext(request.getContext()); + + if (CollectionUtils.isNotEmpty(tags)) { + final boolean useTagPoliciesFromDefaultZone = !policyEngine.isResourceZoneAssociatedWithTagService(zoneName); + + for (RangerTagForEval tag : tags) { + RangerAccessRequest tagEvalRequest = new RangerTagAccessRequest(tag, policyEngine.getTagPolicyRepository().getServiceDef(), request); + List evaluators = policyEngine.getTagPolicyRepository().getLikelyMatchPolicyEvaluators(tagEvalRequest, RangerPolicy.POLICY_TYPE_ACCESS); + + for (RangerPolicyEvaluator evaluator : evaluators) { + String policyZoneName = evaluator.getPolicy().getZoneName(); + + if (useTagPoliciesFromDefaultZone) { + if (StringUtils.isNotEmpty(policyZoneName)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Tag policy [zone:" + policyZoneName + "] does not belong to default zone. Not evaluating this policy:[" + evaluator.getPolicy() + "]"); + } + + continue; + } + } else { + if (!StringUtils.equals(zoneName, policyZoneName)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Tag policy [zone:" + policyZoneName + "] does not belong to the zone:[" + zoneName + "] of the accessed resource. Not evaluating this policy:[" + evaluator.getPolicy() + "]"); + } + + continue; + } + } + + evaluator.getResourceAccessInfo(tagEvalRequest, ret); + } + } + } + } + + List resPolicyEvaluators = matchedRepository.getLikelyMatchPolicyEvaluators(request, RangerPolicy.POLICY_TYPE_ACCESS); + + if (CollectionUtils.isNotEmpty(resPolicyEvaluators)) { + for (RangerPolicyEvaluator evaluator : resPolicyEvaluators) { + evaluator.getResourceAccessInfo(request, ret); + } + } + + ret.getAllowedUsers().removeAll(ret.getDeniedUsers()); + ret.getAllowedGroups().removeAll(ret.getDeniedGroups()); + } + } + + private void evaluateTagAuditPolicies(RangerAccessRequest request, RangerAccessResult result, RangerPolicyRepository tagPolicyRepository) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.evaluateTagAuditPolicies(request=" + request + ", result=" + result + ")"); + } + + Set tags = RangerAccessRequestUtil.getRequestTagsFromContext(request.getContext()); + + if (CollectionUtils.isNotEmpty(tags)) { + Date accessTime = request.getAccessTime() != null ? request.getAccessTime() : new Date(); + List evaluators = tagPolicyRepository.getLikelyMatchPolicyEvaluators(request, tags, RangerPolicy.POLICY_TYPE_AUDIT, accessTime); + + if (CollectionUtils.isNotEmpty(evaluators)) { + for (PolicyEvaluatorForTag policyEvaluator : evaluators) { + RangerPolicyEvaluator evaluator = policyEvaluator.getEvaluator(); + RangerTagForEval tag = policyEvaluator.getTag(); + RangerAccessRequest tagEvalRequest = new RangerTagAccessRequest(tag, tagPolicyRepository.getServiceDef(), request); + RangerAccessResult tagEvalResult = createAccessResult(tagEvalRequest, RangerPolicy.POLICY_TYPE_AUDIT); + + if (LOG.isDebugEnabled()) { + LOG.debug("RangerPolicyEngineImpl.evaluateTagAuditPolicies: Evaluating Audit policies for tag (" + tag.getType() + ")" + "Tag Evaluator: " + policyEvaluator); + } + + tagEvalResult.setAccessResultFrom(result); + + result.incrementEvaluatedPoliciesCount(); + + evaluator.evaluate(tagEvalRequest, tagEvalResult); + + if (tagEvalResult.getIsAuditedDetermined()) { + result.setIsAudited(tagEvalResult.getIsAudited()); + break; + } + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.evaluateTagAuditPolicies(request=" + request + ", result=" + result + ")"); + } + } + + private boolean evaluateResourceAuditPolicies(RangerAccessRequest request, RangerAccessResult result, RangerPolicyRepository policyRepository) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.evaluateResourceAuditPolicies(request=" + request + ", result=" + result + ")"); + } + + boolean ret = false; + List evaluators = policyRepository.getLikelyMatchAuditPolicyEvaluators(request); + + if (CollectionUtils.isNotEmpty(evaluators)) { + for (RangerPolicyEvaluator evaluator : evaluators) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyEngineImpl.evaluateResourceAuditPolicies(): Evaluating RangerPolicyEvaluator...: " + evaluator); + } + + result.incrementEvaluatedPoliciesCount(); + + evaluator.evaluate(request, result); + + if (result.getIsAuditedDetermined()) { + ret = true; + + break; + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyEngineImpl.evaluateResourceAuditPolicies(request=" + request + ", result=" + result + "): ret=" + ret); + } + + return ret; + } + + private boolean getIsFallbackSupported() { + return policyEngine.getPluginContext().getConfig().getIsFallbackSupported(); + } + + private void updateFromPolicyACLs(RangerPolicyEvaluator evaluator, Set policyIdForTemporalTags, RangerResourceACLs resourceACLs) { + PolicyACLSummary aclSummary = evaluator.getPolicyACLSummary(); + + if (aclSummary == null) { + return; + } + + boolean isConditional = policyIdForTemporalTags.contains(evaluator.getId()) || evaluator.getValidityScheduleEvaluatorsCount() != 0; + + for (Map.Entry> userAccessInfo : aclSummary.getUsersAccessInfo().entrySet()) { + final String userName = userAccessInfo.getKey(); + + for (Map.Entry accessInfo : userAccessInfo.getValue().entrySet()) { + Integer accessResult; + + if (isConditional) { + accessResult = ACCESS_CONDITIONAL; + } else { + accessResult = accessInfo.getValue().getResult(); + + if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) { + accessResult = RangerPolicyEvaluator.ACCESS_DENIED; + } + } + + RangerPolicy policy = evaluator.getPolicy(); + + resourceACLs.setUserAccessInfo(userName, accessInfo.getKey(), accessResult, policy); + } + } + + for (Map.Entry> groupAccessInfo : aclSummary.getGroupsAccessInfo().entrySet()) { + final String groupName = groupAccessInfo.getKey(); + + for (Map.Entry accessInfo : groupAccessInfo.getValue().entrySet()) { + Integer accessResult; + + if (isConditional) { + accessResult = ACCESS_CONDITIONAL; + } else { + accessResult = accessInfo.getValue().getResult(); + + if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) { + accessResult = RangerPolicyEvaluator.ACCESS_DENIED; + } + } + + RangerPolicy policy = evaluator.getPolicy(); + + resourceACLs.setGroupAccessInfo(groupName, accessInfo.getKey(), accessResult, policy); + } + } + + for (Map.Entry> roleAccessInfo : aclSummary.getRolesAccessInfo().entrySet()) { + final String roleName = roleAccessInfo.getKey(); + + for (Map.Entry accessInfo : roleAccessInfo.getValue().entrySet()) { + Integer accessResult; + + if (isConditional) { + accessResult = ACCESS_CONDITIONAL; + } else { + accessResult = accessInfo.getValue().getResult(); + + if (accessResult.equals(RangerPolicyEvaluator.ACCESS_UNDETERMINED)) { + accessResult = RangerPolicyEvaluator.ACCESS_DENIED; + } + } + + RangerPolicy policy = evaluator.getPolicy(); + + resourceACLs.setRoleAccessInfo(roleName, accessInfo.getKey(), accessResult, policy); + } + } + } + + private void updateRowFiltersFromPolicy(RangerPolicyEvaluator evaluator, Set policyIdForTemporalTags, RangerResourceACLs resourceACLs) { + PolicyACLSummary aclSummary = evaluator.getPolicyACLSummary(); + + if (aclSummary != null) { + boolean isConditional = policyIdForTemporalTags.contains(evaluator.getId()) || evaluator.getValidityScheduleEvaluatorsCount() != 0; + + for (RowFilterResult rowFilterResult : aclSummary.getRowFilters()) { + rowFilterResult = copyRowFilter(rowFilterResult); + + if (isConditional) { + rowFilterResult.setIsConditional(true); + } + + resourceACLs.getRowFilters().add(rowFilterResult); + } + } + } + + private void updateDataMasksFromPolicy(RangerPolicyEvaluator evaluator, Set policyIdForTemporalTags, RangerResourceACLs resourceACLs) { + PolicyACLSummary aclSummary = evaluator.getPolicyACLSummary(); + + if (aclSummary != null) { + boolean isConditional = policyIdForTemporalTags.contains(evaluator.getId()) || evaluator.getValidityScheduleEvaluatorsCount() != 0; + + for (DataMaskResult dataMaskResult : aclSummary.getDataMasks()) { + dataMaskResult = copyDataMask(dataMaskResult); + + if (isConditional) { + dataMaskResult.setIsConditional(true); + } + + resourceACLs.getDataMasks().add(dataMaskResult); + } + } + } + + private DataMaskResult copyDataMask(DataMaskResult dataMask) { + DataMaskResult ret = new DataMaskResult(copyStrings(dataMask.getUsers()), + copyStrings(dataMask.getGroups()), + copyStrings(dataMask.getRoles()), + copyStrings(dataMask.getAccessTypes()), + new RangerPolicyItemDataMaskInfo(dataMask.getMaskInfo())); + + ret.setIsConditional(dataMask.getIsConditional()); + + return ret; + } + + private RowFilterResult copyRowFilter(RowFilterResult rowFilter) { + RowFilterResult ret = new RowFilterResult(copyStrings(rowFilter.getUsers()), + copyStrings(rowFilter.getGroups()), + copyStrings(rowFilter.getRoles()), + copyStrings(rowFilter.getAccessTypes()), + new RangerPolicyItemRowFilterInfo(rowFilter.getFilterInfo())); + + ret.setIsConditional(rowFilter.getIsConditional()); + + return ret; + } + + private Set copyStrings(Set values) { + return values != null ? new HashSet<>(values) : null; + } + + private static class ServiceConfig { + private final Set auditExcludedUsers; + private final Set auditExcludedGroups; + private final Set auditExcludedRoles; + private final Set superUsers; + private final Set superGroups; + private final Set serviceAdmins; + + public ServiceConfig(Map svcConfig) { + if (svcConfig != null) { + auditExcludedUsers = RangerUtil.toSet(svcConfig.get(RangerPolicyEngine.PLUGIN_AUDIT_EXCLUDE_USERS)); + auditExcludedGroups = RangerUtil.toSet(svcConfig.get(RangerPolicyEngine.PLUGIN_AUDIT_EXCLUDE_GROUPS)); + auditExcludedRoles = RangerUtil.toSet(svcConfig.get(RangerPolicyEngine.PLUGIN_AUDIT_EXCLUDE_ROLES)); + superUsers = RangerUtil.toSet(svcConfig.get(RangerPolicyEngine.PLUGIN_SUPER_USERS)); + superGroups = RangerUtil.toSet(svcConfig.get(RangerPolicyEngine.PLUGIN_SUPER_GROUPS)); + serviceAdmins = RangerUtil.toSet(svcConfig.get(RangerPolicyEngine.PLUGIN_SERVICE_ADMINS)); + } else { + auditExcludedUsers = Collections.emptySet(); + auditExcludedGroups = Collections.emptySet(); + auditExcludedRoles = Collections.emptySet(); + superUsers = Collections.emptySet(); + superGroups = Collections.emptySet(); + serviceAdmins = Collections.emptySet(); + } + } + + public ServiceConfig(ServiceConfig other) { + auditExcludedUsers = other == null || CollectionUtils.isEmpty(other.auditExcludedUsers) ? Collections.emptySet() : new HashSet<>(other.auditExcludedUsers); + auditExcludedGroups = other == null || CollectionUtils.isEmpty(other.auditExcludedGroups) ? Collections.emptySet() : new HashSet<>(other.auditExcludedGroups); + auditExcludedRoles = other == null || CollectionUtils.isEmpty(other.auditExcludedRoles) ? Collections.emptySet() : new HashSet<>(other.auditExcludedRoles); + superUsers = other == null || CollectionUtils.isEmpty(other.superUsers) ? Collections.emptySet() : new HashSet<>(other.superUsers); + superGroups = other == null || CollectionUtils.isEmpty(other.superGroups) ? Collections.emptySet() : new HashSet<>(other.superGroups); + serviceAdmins = other == null || CollectionUtils.isEmpty(other.serviceAdmins) ? Collections.emptySet() : new HashSet<>(other.serviceAdmins); + } + + public boolean isAuditExcludedUser(String userName) { + return auditExcludedUsers.contains(userName); + } + + public boolean hasAuditExcludedGroup(Set userGroups) { + return userGroups != null && userGroups.size() > 0 && auditExcludedGroups.size() > 0 && CollectionUtils.containsAny(userGroups, auditExcludedGroups); + } + + public boolean hasAuditExcludedRole(Set userRoles) { + return userRoles != null && userRoles.size() > 0 && auditExcludedRoles.size() > 0 && CollectionUtils.containsAny(userRoles, auditExcludedRoles); + } + + public boolean isSuperUser(String userName) { + return superUsers.contains(userName); + } + + public boolean hasSuperGroup(Set userGroups) { + return userGroups != null && userGroups.size() > 0 && superGroups.size() > 0 && CollectionUtils.containsAny(userGroups, superGroups); + } + + public boolean isServiceAdmin(String userName) { + return serviceAdmins.contains(userName); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPolicyEngineOptions.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPolicyEngineOptions.java new file mode 100644 index 00000000000..8cd7df91b51 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPolicyEngineOptions.java @@ -0,0 +1,208 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import org.apache.hadoop.conf.Configuration; +import org.apache.atlas.plugin.model.validation.RangerServiceDefHelper; +import org.apache.atlas.plugin.policyevaluator.RangerPolicyEvaluator; + +public class RangerPolicyEngineOptions { + public String evaluatorType = RangerPolicyEvaluator.EVALUATOR_TYPE_AUTO; + + public boolean disableContextEnrichers = false; + public boolean disableCustomConditions = false; + public boolean disableTagPolicyEvaluation = false; + public boolean disableTrieLookupPrefilter = false; + public boolean disablePolicyRefresher = false; + public boolean disableTagRetriever = false; + public boolean cacheAuditResults = true; + public boolean evaluateDelegateAdminOnly = false; + public boolean enableTagEnricherWithLocalRefresher = false; + public boolean disableAccessEvaluationWithPolicyACLSummary = true; + public boolean optimizeTrieForRetrieval = false; + public boolean disableRoleResolution = true; + + private RangerServiceDefHelper serviceDefHelper; + + public RangerPolicyEngineOptions() {} + + public RangerPolicyEngineOptions(final RangerPolicyEngineOptions other) { + this.disableContextEnrichers = other.disableContextEnrichers; + this.disableCustomConditions = other.disableCustomConditions; + this.disableTagPolicyEvaluation = other.disableTagPolicyEvaluation; + this.disableTrieLookupPrefilter = other.disableTrieLookupPrefilter; + this.disablePolicyRefresher = other.disablePolicyRefresher; + this.disableTagRetriever = other.disableTagRetriever; + this.cacheAuditResults = other.cacheAuditResults; + this.evaluateDelegateAdminOnly = other.evaluateDelegateAdminOnly; + this.enableTagEnricherWithLocalRefresher = other.enableTagEnricherWithLocalRefresher; + this.disableAccessEvaluationWithPolicyACLSummary = other.disableAccessEvaluationWithPolicyACLSummary; + this.optimizeTrieForRetrieval = other.optimizeTrieForRetrieval; + this.disableRoleResolution = other.disableRoleResolution; + this.serviceDefHelper = null; + } + + public void configureForPlugin(Configuration conf, String propertyPrefix) { + disableContextEnrichers = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.context.enrichers", false); + disableCustomConditions = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.custom.conditions", false); + disableTagPolicyEvaluation = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.tagpolicy.evaluation", false); + disableTrieLookupPrefilter = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.trie.lookup.prefilter", false); + disablePolicyRefresher = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.policy.refresher", false); + disableTagRetriever = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.tag.retriever", false); + + cacheAuditResults = conf.getBoolean(propertyPrefix + ".policyengine.option.cache.audit.results", true); + + if (!disableTrieLookupPrefilter) { + cacheAuditResults = false; + } + evaluateDelegateAdminOnly = false; + enableTagEnricherWithLocalRefresher = false; + disableAccessEvaluationWithPolicyACLSummary = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.access.evaluation.with.policy.acl.summary", true); + optimizeTrieForRetrieval = conf.getBoolean(propertyPrefix + ".policyengine.option.optimize.trie.for.retrieval", false); + disableRoleResolution = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.role.resolution", true); + + } + + public void configureDefaultRangerAdmin(Configuration conf, String propertyPrefix) { + disableContextEnrichers = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.context.enrichers", true); + disableCustomConditions = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.custom.conditions", true); + disableTagPolicyEvaluation = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.tagpolicy.evaluation", true); + disableTrieLookupPrefilter = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.trie.lookup.prefilter", false); + disablePolicyRefresher = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.policy.refresher", true); + disableTagRetriever = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.tag.retriever", true); + + cacheAuditResults = false; + evaluateDelegateAdminOnly = false; + enableTagEnricherWithLocalRefresher = false; + disableAccessEvaluationWithPolicyACLSummary = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.access.evaluation.with.policy.acl.summary", true); + optimizeTrieForRetrieval = conf.getBoolean(propertyPrefix + ".policyengine.option.optimize.trie.for.retrieval", false); + disableRoleResolution = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.role.resolution", true); + + } + + public void configureDelegateAdmin(Configuration conf, String propertyPrefix) { + disableContextEnrichers = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.context.enrichers", true); + disableCustomConditions = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.custom.conditions", true); + disableTagPolicyEvaluation = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.tagpolicy.evaluation", true); + disableTrieLookupPrefilter = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.trie.lookup.prefilter", false); + disablePolicyRefresher = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.policy.refresher", true); + disableTagRetriever = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.tag.retriever", true); + optimizeTrieForRetrieval = conf.getBoolean(propertyPrefix + ".policyengine.option.optimize.trie.for.retrieval", false); + + + cacheAuditResults = false; + evaluateDelegateAdminOnly = true; + enableTagEnricherWithLocalRefresher = false; + + } + + public void configureRangerAdminForPolicySearch(Configuration conf, String propertyPrefix) { + disableContextEnrichers = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.context.enrichers", true); + disableCustomConditions = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.custom.conditions", true); + disableTagPolicyEvaluation = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.tagpolicy.evaluation", false); + disableTrieLookupPrefilter = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.trie.lookup.prefilter", false); + disablePolicyRefresher = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.policy.refresher", true); + disableTagRetriever = conf.getBoolean(propertyPrefix + ".policyengine.option.disable.tag.retriever", false); + optimizeTrieForRetrieval = conf.getBoolean(propertyPrefix + ".policyengine.option.optimize.trie.for.retrieval", false); + + + cacheAuditResults = false; + evaluateDelegateAdminOnly = false; + enableTagEnricherWithLocalRefresher = true; + } + + public RangerServiceDefHelper getServiceDefHelper() { + return serviceDefHelper; + } + + void setServiceDefHelper(RangerServiceDefHelper serviceDefHelper) { + this.serviceDefHelper = serviceDefHelper; + } + + /* + * There is no need to implement these, as the options are predefined in a component ServiceREST and hence + * guaranteed to be unique objects. That implies that the default equals and hashCode should suffice. + */ + + @Override + public boolean equals(Object other) { + boolean ret = false; + if (other instanceof RangerPolicyEngineOptions) { + RangerPolicyEngineOptions that = (RangerPolicyEngineOptions) other; + ret = this.disableContextEnrichers == that.disableContextEnrichers + && this.disableCustomConditions == that.disableCustomConditions + && this.disableTagPolicyEvaluation == that.disableTagPolicyEvaluation + && this.disableTrieLookupPrefilter == that.disableTrieLookupPrefilter + && this.disablePolicyRefresher == that.disablePolicyRefresher + && this.disableTagRetriever == that.disableTagRetriever + && this.cacheAuditResults == that.cacheAuditResults + && this.evaluateDelegateAdminOnly == that.evaluateDelegateAdminOnly + && this.enableTagEnricherWithLocalRefresher == that.enableTagEnricherWithLocalRefresher + && this.optimizeTrieForRetrieval == that.optimizeTrieForRetrieval + && this.disableRoleResolution == that.disableRoleResolution; + } + return ret; + } + + @Override + public int hashCode() { + int ret = 0; + ret += disableContextEnrichers ? 1 : 0; + ret *= 2; + ret += disableCustomConditions ? 1 : 0; + ret *= 2; + ret += disableTagPolicyEvaluation ? 1 : 0; + ret *= 2; + ret += disableTrieLookupPrefilter ? 1 : 0; + ret *= 2; + ret += disablePolicyRefresher ? 1 : 0; + ret *= 2; + ret += disableTagRetriever ? 1 : 0; + ret *= 2; + ret += cacheAuditResults ? 1 : 0; + ret *= 2; + ret += evaluateDelegateAdminOnly ? 1 : 0; + ret *= 2; + ret += enableTagEnricherWithLocalRefresher ? 1 : 0; + ret *= 2; + ret += optimizeTrieForRetrieval ? 1 : 0; + ret *= 2; + ret += disableRoleResolution ? 1 : 0; + ret *= 2; return ret; + } + + @Override + public String toString() { + return "PolicyEngineOptions: {" + + " evaluatorType: " + evaluatorType + + ", evaluateDelegateAdminOnly: " + evaluateDelegateAdminOnly + + ", disableContextEnrichers: " + disableContextEnrichers + + ", disableCustomConditions: " + disableContextEnrichers + + ", disableTagPolicyEvaluation: " + disableTagPolicyEvaluation + + ", disablePolicyRefresher: " + disablePolicyRefresher + + ", disableTagRetriever: " + disableTagRetriever + + ", enableTagEnricherWithLocalRefresher: " + enableTagEnricherWithLocalRefresher + + ", disableTrieLookupPrefilter: " + disableTrieLookupPrefilter + + ", optimizeTrieForRetrieval: " + optimizeTrieForRetrieval + + ", cacheAuditResult: " + cacheAuditResults + + ", disableRoleResolution: " + disableRoleResolution + + " }"; + + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPolicyRepository.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPolicyRepository.java new file mode 100644 index 00000000000..398155cf5e2 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerPolicyRepository.java @@ -0,0 +1,1556 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import org.apache.atlas.constants.RangerAtlasConstants; +import org.apache.atlas.authorization.utils.RangerUtil; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.contextenricher.RangerAbstractContextEnricher; +import org.apache.atlas.plugin.contextenricher.RangerContextEnricher; +import org.apache.atlas.plugin.contextenricher.RangerTagEnricher; +import org.apache.atlas.plugin.contextenricher.RangerTagForEval; +import org.apache.atlas.plugin.model.AuditFilter; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo; +import org.apache.atlas.plugin.model.RangerPolicyDelta; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.validation.RangerServiceDefHelper; +import org.apache.atlas.plugin.policyevaluator.RangerAbstractPolicyEvaluator; +import org.apache.atlas.plugin.policyevaluator.RangerAuditPolicyEvaluator; +import org.apache.atlas.plugin.policyevaluator.RangerCachedPolicyEvaluator; +import org.apache.atlas.plugin.policyevaluator.RangerOptimizedPolicyEvaluator; +import org.apache.atlas.plugin.policyevaluator.RangerPolicyEvaluator; +import org.apache.atlas.plugin.util.RangerPerfTracer; +import org.apache.atlas.plugin.util.ServiceDefUtil; +import org.apache.atlas.plugin.util.ServicePolicies; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.apache.atlas.plugin.contextenricher.RangerTagEnricher.TAG_RETRIEVER_CLASSNAME_OPTION; +import static org.apache.atlas.plugin.policyengine.RangerPolicyEngine.PLUGIN_AUDIT_FILTER; + +public class RangerPolicyRepository { + private static final Log LOG = LogFactory.getLog(RangerPolicyRepository.class); + + private static final Log PERF_CONTEXTENRICHER_INIT_LOG = RangerPerfTracer.getPerfLogger("contextenricher.init"); + private static final Log PERF_TRIE_OP_LOG = RangerPerfTracer.getPerfLogger("resourcetrie.retrieval"); + + enum AuditModeEnum { + AUDIT_ALL, AUDIT_NONE, AUDIT_DEFAULT + } + + private final String serviceName; + private final String zoneName; + private final String appId; + private final RangerPolicyEngineOptions options; + private final RangerPluginContext pluginContext; + private final RangerServiceDef serviceDef; + private /*final*/ List policies; + private final long policyVersion; + private /*final*/ List contextEnrichers; + private final AuditModeEnum auditModeEnum; + private final Map accessAuditCache; + private final String componentServiceName; + private final RangerServiceDef componentServiceDef; + private final Map policyResourceTrie; + private final Map dataMaskResourceTrie; + private final Map rowFilterResourceTrie; + private final Map auditFilterResourceTrie; + private List policyEvaluators; + private List dataMaskPolicyEvaluators; + private List rowFilterPolicyEvaluators; + private final List auditPolicyEvaluators; + private Map policyEvaluatorsMap; + private boolean isContextEnrichersShared = false; + private boolean isPreCleaned = false; + + RangerPolicyRepository(final RangerPolicyRepository other, final List deltas, long policyVersion) { + this.serviceName = other.serviceName; + this.zoneName = other.zoneName; + this.appId = other.appId; + this.options = other.options; + this.pluginContext = other.pluginContext; + this.serviceDef = other.serviceDef; + this.policies = new ArrayList<>(other.policies); + this.policyEvaluators = new ArrayList<>(other.policyEvaluators); + this.dataMaskPolicyEvaluators = new ArrayList<>(other.dataMaskPolicyEvaluators); + this.rowFilterPolicyEvaluators = new ArrayList<>(other.rowFilterPolicyEvaluators); + this.auditPolicyEvaluators = new ArrayList<>(other.auditPolicyEvaluators); + this.auditModeEnum = other.auditModeEnum; + this.componentServiceName = other.componentServiceName; + this.componentServiceDef = other.componentServiceDef; + this.policyEvaluatorsMap = new HashMap<>(other.policyEvaluatorsMap); + + if (other.policyResourceTrie != null) { + this.policyResourceTrie = new HashMap<>(); + + for (Map.Entry entry : other.policyResourceTrie.entrySet()) { + policyResourceTrie.put(entry.getKey(), new RangerResourceTrie(entry.getValue())); + } + } else { + this.policyResourceTrie = null; + } + + if (other.dataMaskResourceTrie != null) { + this.dataMaskResourceTrie = new HashMap<>(); + + for (Map.Entry entry : other.dataMaskResourceTrie.entrySet()) { + dataMaskResourceTrie.put(entry.getKey(), new RangerResourceTrie(entry.getValue())); + } + } else { + this.dataMaskResourceTrie = null; + } + + if (other.rowFilterResourceTrie != null) { + this.rowFilterResourceTrie = new HashMap<>(); + + for (Map.Entry entry : other.rowFilterResourceTrie.entrySet()) { + rowFilterResourceTrie.put(entry.getKey(), new RangerResourceTrie(entry.getValue())); + } + } else { + this.rowFilterResourceTrie = null; + } + + if (other.auditFilterResourceTrie != null) { + this.auditFilterResourceTrie = new HashMap<>(); + + for (Map.Entry entry : other.auditFilterResourceTrie.entrySet()) { + auditFilterResourceTrie.put(entry.getKey(), new RangerResourceTrie(entry.getValue())); + } + } else { + this.auditFilterResourceTrie = null; + } + + if (other.accessAuditCache != null) { + int auditResultCacheSize = other.accessAuditCache.size(); + + this.accessAuditCache = Collections.synchronizedMap(new CacheMap(auditResultCacheSize)); + } else { + this.accessAuditCache = null; + } + + final boolean isExistingPolicies = CollectionUtils.isNotEmpty(this.policies); + + updateResourceTrie(deltas); + + if (CollectionUtils.isNotEmpty(this.policies)) { + this.contextEnrichers = isExistingPolicies ? shareWith(other) : buildContextEnrichers(options); + } else { + this.contextEnrichers = null; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("other.serviceName=" + other.serviceName + ", other.isContextEnrichersShared=" + other.isContextEnrichersShared + ", Context-enrichers are " + (CollectionUtils.isNotEmpty(contextEnrichers) ? " not empty " : "empty ")); + } + + this.policyVersion = policyVersion; + } + + public RangerPolicyRepository(ServicePolicies servicePolicies, RangerPluginContext pluginContext) { + this(servicePolicies, pluginContext, null); + } + + RangerPolicyRepository(ServicePolicies servicePolicies, RangerPluginContext pluginContext, String zoneName) { + super(); + + this.componentServiceName = this.serviceName = servicePolicies.getServiceName(); + this.componentServiceDef = this.serviceDef = ServiceDefUtil.normalize(servicePolicies.getServiceDef()); + this.zoneName = zoneName; + this.appId = pluginContext.getConfig().getAppId(); + this.options = new RangerPolicyEngineOptions(pluginContext.getConfig().getPolicyEngineOptions()); + this.pluginContext = pluginContext; + + if (StringUtils.isEmpty(zoneName)) { + this.policies = servicePolicies.getPolicies(); + } else { + this.policies = servicePolicies.getSecurityZones().get(zoneName).getPolicies(); + } + this.policyVersion = servicePolicies.getPolicyVersion() != null ? servicePolicies.getPolicyVersion() : -1; + + String auditMode = servicePolicies.getAuditMode(); + + if (StringUtils.equals(auditMode, RangerPolicyEngine.AUDIT_ALL)) { + auditModeEnum = AuditModeEnum.AUDIT_ALL; + } else if (StringUtils.equals(auditMode, RangerPolicyEngine.AUDIT_NONE)) { + auditModeEnum = AuditModeEnum.AUDIT_NONE; + } else { + auditModeEnum = AuditModeEnum.AUDIT_DEFAULT; + } + + if (auditModeEnum == AuditModeEnum.AUDIT_DEFAULT) { + String propertyName = "ranger.plugin." + serviceName + ".policyengine.auditcachesize"; + + if (options.cacheAuditResults) { + final int RANGER_POLICYENGINE_AUDITRESULT_CACHE_SIZE = 64 * 1024; + + int auditResultCacheSize = pluginContext.getConfig().getInt(propertyName, RANGER_POLICYENGINE_AUDITRESULT_CACHE_SIZE); + accessAuditCache = Collections.synchronizedMap(new CacheMap(auditResultCacheSize)); + } else { + accessAuditCache = null; + } + } else { + this.accessAuditCache = null; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("RangerPolicyRepository : building policy-repository for service[" + serviceName + "], and zone:[" + zoneName + "] with auditMode[" + auditModeEnum + "]"); + } + + init(options); + + if (StringUtils.isEmpty(zoneName)) { + this.contextEnrichers = buildContextEnrichers(options); + this.auditPolicyEvaluators = buildAuditPolicyEvaluators(servicePolicies.getServiceConfig()); + } else { + this.contextEnrichers = null; + this.auditPolicyEvaluators = Collections.emptyList(); + } + + if (options.disableTrieLookupPrefilter) { + policyResourceTrie = null; + dataMaskResourceTrie = null; + rowFilterResourceTrie = null; + auditFilterResourceTrie = null; + } else { + policyResourceTrie = createResourceTrieMap(policyEvaluators, options.optimizeTrieForRetrieval); + dataMaskResourceTrie = createResourceTrieMap(dataMaskPolicyEvaluators, options.optimizeTrieForRetrieval); + rowFilterResourceTrie = createResourceTrieMap(rowFilterPolicyEvaluators, options.optimizeTrieForRetrieval); + auditFilterResourceTrie = createResourceTrieMap(auditPolicyEvaluators, options.optimizeTrieForRetrieval); + } + } + + RangerPolicyRepository(ServicePolicies.TagPolicies tagPolicies, RangerPluginContext pluginContext, + RangerServiceDef componentServiceDef, String componentServiceName) { + super(); + + this.serviceName = tagPolicies.getServiceName(); + this.componentServiceName = componentServiceName; + this.zoneName = null; + this.serviceDef = ServiceDefUtil.normalizeAccessTypeDefs(ServiceDefUtil.normalize(tagPolicies.getServiceDef()), componentServiceDef.getName()); + this.componentServiceDef = componentServiceDef; + this.appId = pluginContext.getConfig().getAppId(); + this.options = new RangerPolicyEngineOptions(pluginContext.getConfig().getPolicyEngineOptions()); + this.pluginContext = pluginContext; + this.policies = normalizeAndPrunePolicies(tagPolicies.getPolicies(), componentServiceDef.getName()); + this.policyVersion = tagPolicies.getPolicyVersion() != null ? tagPolicies.getPolicyVersion() : -1; + + String auditMode = tagPolicies.getAuditMode(); + + if (StringUtils.equals(auditMode, RangerPolicyEngine.AUDIT_ALL)) { + auditModeEnum = AuditModeEnum.AUDIT_ALL; + } else if (StringUtils.equals(auditMode, RangerPolicyEngine.AUDIT_NONE)) { + auditModeEnum = AuditModeEnum.AUDIT_NONE; + } else { + auditModeEnum = AuditModeEnum.AUDIT_DEFAULT; + } + + this.accessAuditCache = null; + + if (LOG.isDebugEnabled()) { + LOG.debug("RangerPolicyRepository : building tag-policy-repository for tag service:[" + serviceName +"], with auditMode[" + auditModeEnum +"]"); + } + + init(options); + + if (StringUtils.isEmpty(zoneName)) { + this.contextEnrichers = buildContextEnrichers(options); + this.auditPolicyEvaluators = buildAuditPolicyEvaluators(tagPolicies.getServiceConfig()); + } else { + this.contextEnrichers = null; + this.auditPolicyEvaluators = Collections.emptyList(); + } + + if (options.disableTrieLookupPrefilter) { + policyResourceTrie = null; + dataMaskResourceTrie = null; + rowFilterResourceTrie = null; + auditFilterResourceTrie = null; + } else { + policyResourceTrie = createResourceTrieMap(policyEvaluators, options.optimizeTrieForRetrieval); + dataMaskResourceTrie = createResourceTrieMap(dataMaskPolicyEvaluators, options.optimizeTrieForRetrieval); + rowFilterResourceTrie = createResourceTrieMap(rowFilterPolicyEvaluators, options.optimizeTrieForRetrieval); + auditFilterResourceTrie = createResourceTrieMap(auditPolicyEvaluators, options.optimizeTrieForRetrieval); + } + } + + private List buildAuditPolicyEvaluators(Map svcConfigs) { + List ret = Collections.emptyList(); + String jsonStr = svcConfigs != null ? svcConfigs.get(PLUGIN_AUDIT_FILTER) : null; + + if (StringUtils.isNotBlank(jsonStr)) { + List auditFilters = RangerUtil.jsonToAuditFilterList(jsonStr); + int filterCount = auditFilters != null ? auditFilters.size() : 0; + + if (filterCount > 0) { + ret = new ArrayList<>(filterCount); + + // set priority so that policies will be evaluated in the same order as in the list + int policyPriority = filterCount; + + for (AuditFilter auditFilter : auditFilters) { + RangerAuditPolicyEvaluator evaluator = new RangerAuditPolicyEvaluator(auditFilter, policyPriority--); + + evaluator.init(evaluator.getAuditPolicy(), serviceDef, options); + + ret.add(evaluator); + } + } + } + + return ret; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + if (sb == null) { + sb = new StringBuilder(); + } + + sb.append("RangerPolicyRepository={"); + + sb.append("serviceName={").append(serviceName).append("} "); + sb.append("zoneName={").append(zoneName).append("} "); + sb.append("serviceDef={").append(serviceDef).append("} "); + sb.append("appId={").append(appId).append("} "); + + sb.append("policyEvaluators={"); + if (policyEvaluators != null) { + for (RangerPolicyEvaluator policyEvaluator : policyEvaluators) { + if (policyEvaluator != null) { + sb.append(policyEvaluator).append(" "); + } + } + } + sb.append("} "); + + sb.append("dataMaskPolicyEvaluators={"); + if (this.dataMaskPolicyEvaluators != null) { + for (RangerPolicyEvaluator policyEvaluator : dataMaskPolicyEvaluators) { + if (policyEvaluator != null) { + sb.append(policyEvaluator).append(" "); + } + } + } + sb.append("} "); + + sb.append("rowFilterPolicyEvaluators={"); + if (this.rowFilterPolicyEvaluators != null) { + for (RangerPolicyEvaluator policyEvaluator : rowFilterPolicyEvaluators) { + if (policyEvaluator != null) { + sb.append(policyEvaluator).append(" "); + } + } + } + sb.append("} "); + + sb.append("auditPolicyEvaluators={"); + if (this.auditPolicyEvaluators != null) { + for (RangerPolicyEvaluator policyEvaluator : auditPolicyEvaluators) { + if (policyEvaluator != null) { + sb.append(policyEvaluator).append(" "); + } + } + } + sb.append("} "); + + sb.append("contextEnrichers={"); + if (contextEnrichers != null) { + for (RangerContextEnricher contextEnricher : contextEnrichers) { + if (contextEnricher != null) { + sb.append(contextEnricher).append(" "); + } + } + } + sb.append("} "); + + sb.append("} "); + + return sb; + } + + List shareWith(RangerPolicyRepository other) { + if (other != null && other.contextEnrichers != null) { + other.setShared(); + } + return other == null ? null : other.contextEnrichers; + } + + void setShared() { + isContextEnrichersShared = true; + } + + void preCleanup(boolean isForced) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> preCleanup(isForced=" + isForced + " )"); + LOG.debug("Repository holds [" + (CollectionUtils.isEmpty(this.contextEnrichers) ? 0 : this.contextEnrichers.size()) + "] enrichers. isPreCleaned=" + isPreCleaned); + } + if (!isPreCleaned) { + if (CollectionUtils.isNotEmpty(this.contextEnrichers) && (!isContextEnrichersShared || isForced)) { + isPreCleaned = true; + if (LOG.isDebugEnabled()) { + LOG.debug("preCleaning context-enrichers"); + } + for (RangerContextEnricher enricher : this.contextEnrichers) { + enricher.preCleanup(); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("No preCleaning of context-enrichers; Context-enrichers are " + (CollectionUtils.isNotEmpty(contextEnrichers) ? " not empty " : "empty ") + ", isContextEnrichersShared=" + isContextEnrichersShared + ", isForced=" + isForced + ")"); + } + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("preCleanup() already done. No need to do it again"); + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== preCleanup(isForced=" + isForced + " )"); + } + } + + void cleanup() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> cleanup()"); + } + preCleanup(false); + + if (CollectionUtils.isNotEmpty(this.contextEnrichers) && !isContextEnrichersShared) { + for (RangerContextEnricher enricher : this.contextEnrichers) { + enricher.cleanup(); + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== cleanup()"); + } + } + + @Override + protected void finalize() throws Throwable { + try { + cleanup(); + } finally { + super.finalize(); + } + } + + void reorderPolicyEvaluators() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> reorderEvaluators()"); + } + + if (policyResourceTrie == null) { + policyEvaluators = getReorderedPolicyEvaluators(policyEvaluators); + } + + if (dataMaskResourceTrie == null) { + dataMaskPolicyEvaluators = getReorderedPolicyEvaluators(dataMaskPolicyEvaluators); + } + + if (rowFilterResourceTrie == null) { + rowFilterPolicyEvaluators = getReorderedPolicyEvaluators(rowFilterPolicyEvaluators); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== reorderEvaluators()"); + } + } + + public String getServiceName() { return serviceName; } + + String getZoneName() { return zoneName; } + + public RangerServiceDef getServiceDef() { + return serviceDef; + } + + List getPolicies() { + return policies; + } + + long getPolicyVersion() { + return policyVersion; + } + + AuditModeEnum getAuditModeEnum() { return auditModeEnum; } + + boolean setAuditEnabledFromCache(RangerAccessRequest request, RangerAccessResult result) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyRepository.setAuditEnabledFromCache()"); + } + + final AuditInfo auditInfo = accessAuditCache != null ? accessAuditCache.get(request.getResource().getAsString()) : null; + + if (auditInfo != null) { + result.setIsAudited(auditInfo.getIsAudited()); + result.setAuditPolicyId(auditInfo.getAuditPolicyId()); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyRepository.setAuditEnabledFromCache():" + (auditInfo != null)); + } + + return auditInfo != null; + } + + void storeAuditEnabledInCache(RangerAccessRequest request, RangerAccessResult result) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyRepository.storeAuditEnabledInCache()"); + } + + if (accessAuditCache != null && result.getIsAuditedDetermined()) { + accessAuditCache.put(request.getResource().getAsString(), new AuditInfo(result.getIsAudited(), result.getAuditPolicyId())); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyRepository.storeAuditEnabledInCache()"); + } + } + + List getContextEnrichers() { return contextEnrichers; } + + List getPolicyEvaluators(String policyType) { + switch (policyType) { + case RangerPolicy.POLICY_TYPE_ACCESS: + return getPolicyEvaluators(); + case RangerPolicy.POLICY_TYPE_DATAMASK: + return getDataMaskPolicyEvaluators(); + case RangerPolicy.POLICY_TYPE_ROWFILTER: + return getRowFilterPolicyEvaluators(); + default: + return getPolicyEvaluators(); + } + } + + public List getPolicyEvaluators() { + return policyEvaluators; + } + + List getDataMaskPolicyEvaluators() { + return dataMaskPolicyEvaluators; + } + + List getRowFilterPolicyEvaluators() { + return rowFilterPolicyEvaluators; + } + + List getAuditPolicyEvaluators() { + return auditPolicyEvaluators; + } + + String getAppId() { return appId; } + + RangerPolicyEngineOptions getOptions() { return options; } + + List getLikelyMatchPolicyEvaluators(RangerAccessRequest request, Set tags, String policyType, Date accessTime) { + List ret = Collections.EMPTY_LIST; + + if (CollectionUtils.isNotEmpty(tags) && getServiceDef() != null) { + + ret = new ArrayList(); + + for (RangerTagForEval tag : tags) { + if (tag.isApplicable(accessTime)) { + RangerAccessRequest tagRequest = new RangerTagAccessRequest(tag, getServiceDef(), request); + List evaluators = getLikelyMatchPolicyEvaluators(tagRequest, policyType); + + if (CollectionUtils.isNotEmpty(evaluators)) { + for (RangerPolicyEvaluator evaluator : evaluators) { + if (evaluator.isApplicable(accessTime)) { + ret.add(new PolicyEvaluatorForTag(evaluator, tag)); + } + } + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Tag:[" + tag.getType() + "] is not applicable at accessTime:[" + accessTime +"]"); + } + } + } + + if (CollectionUtils.isNotEmpty(ret)) { + switch (policyType) { + case RangerPolicy.POLICY_TYPE_ACCESS: + case RangerPolicy.POLICY_TYPE_AUDIT: + Collections.sort(ret, PolicyEvaluatorForTag.EVAL_ORDER_COMPARATOR); + break; + case RangerPolicy.POLICY_TYPE_DATAMASK: + Collections.sort(ret, PolicyEvaluatorForTag.NAME_COMPARATOR); + break; + case RangerPolicy.POLICY_TYPE_ROWFILTER: + Collections.sort(ret, PolicyEvaluatorForTag.NAME_COMPARATOR); + break; + default: + LOG.warn("Unknown policy-type:[" + policyType + "]. Ignoring.."); + break; + } + } + } + return ret; + } + + public List getLikelyMatchPolicyEvaluators(RangerAccessRequest request) { + List ret = new ArrayList<>(); + + for (String policyType : RangerPolicy.POLICY_TYPES) { + List evaluators = getLikelyMatchPolicyEvaluators(request, policyType); + if (CollectionUtils.isNotEmpty(evaluators)) { + ret.addAll(evaluators); + } + } + return ret; + } + + public List getLikelyMatchPolicyEvaluators(RangerAccessRequest request, String policyType) { + switch (policyType) { + case RangerPolicy.POLICY_TYPE_ACCESS: + return getLikelyMatchAccessPolicyEvaluators(request); + case RangerPolicy.POLICY_TYPE_DATAMASK: + return getLikelyMatchDataMaskPolicyEvaluators(request); + case RangerPolicy.POLICY_TYPE_ROWFILTER: + return getLikelyMatchRowFilterPolicyEvaluators(request); + case RangerPolicy.POLICY_TYPE_AUDIT: + return getLikelyMatchAuditPolicyEvaluators(request); + default: + return Collections.EMPTY_LIST; + } + } + + + public Map getPolicyEvaluatorsMap() { return policyEvaluatorsMap; } + + RangerPolicyEvaluator getPolicyEvaluator(String id) { + return policyEvaluatorsMap.get(id); + } + + private List getLikelyMatchAccessPolicyEvaluators(RangerAccessRequest request) { + RangerAccessResource resource = request.getResource(); + String resourceStr = resource == null ? null : resource.getAsString(); + + return policyResourceTrie == null || StringUtils.isEmpty(resourceStr) ? getPolicyEvaluators() : getLikelyMatchPolicyEvaluators(policyResourceTrie, request); + } + + private List getLikelyMatchDataMaskPolicyEvaluators(RangerAccessRequest request) { + RangerAccessResource resource = request.getResource(); + String resourceStr = resource == null ? null : resource.getAsString(); + + return dataMaskResourceTrie == null || StringUtils.isEmpty(resourceStr) ? getDataMaskPolicyEvaluators() : getLikelyMatchPolicyEvaluators(dataMaskResourceTrie, request); + } + + private List getLikelyMatchRowFilterPolicyEvaluators(RangerAccessRequest request) { + RangerAccessResource resource = request.getResource(); + String resourceStr = resource == null ? null : resource.getAsString(); + + return rowFilterResourceTrie == null || StringUtils.isEmpty(resourceStr) ? getRowFilterPolicyEvaluators() : getLikelyMatchPolicyEvaluators(rowFilterResourceTrie, request); + } + + List getLikelyMatchAuditPolicyEvaluators(RangerAccessRequest request) { + RangerAccessResource resource = request.getResource(); + String resourceStr = resource == null ? null : resource.getAsString(); + + return auditFilterResourceTrie == null || StringUtils.isEmpty(resourceStr) ? getAuditPolicyEvaluators() : getLikelyMatchPolicyEvaluators(auditFilterResourceTrie, request); + } + + private List getLikelyMatchPolicyEvaluators(Map resourceTrie, RangerAccessRequest request) { + List ret = Collections.EMPTY_LIST; + + RangerAccessResource resource = request.getResource(); + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_TRIE_OP_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_TRIE_OP_LOG, "RangerPolicyRepository.getLikelyMatchEvaluators(resource=" + resource.getAsString() + ")"); + } + + List resourceKeys = resource == null ? null : options.getServiceDefHelper().getOrderedResourceNames(resource.getKeys()); + Set smallestList = null; + + if (CollectionUtils.isNotEmpty(resourceKeys)) { + + for (String resourceName : resourceKeys) { + RangerResourceTrie trie = resourceTrie.get(resourceName); + + if (trie == null) { // if no trie exists for this resource level, ignore and continue to next level + continue; + } + + Set serviceResourceMatchersForResource = trie.getEvaluatorsForResource(resource.getValue(resourceName), request.getResourceMatchingScope()); + Set inheritedResourceMatchers = trie.getInheritedEvaluators(); + + if (smallestList != null) { + if (CollectionUtils.isEmpty(inheritedResourceMatchers) && CollectionUtils.isEmpty(serviceResourceMatchersForResource)) { + smallestList = null; + } else if (CollectionUtils.isEmpty(inheritedResourceMatchers)) { + smallestList.retainAll(serviceResourceMatchersForResource); + } else if (CollectionUtils.isEmpty(serviceResourceMatchersForResource)) { + smallestList.retainAll(inheritedResourceMatchers); + } else { + Set smaller, bigger; + if (serviceResourceMatchersForResource.size() < inheritedResourceMatchers.size()) { + smaller = serviceResourceMatchersForResource; + bigger = inheritedResourceMatchers; + } else { + smaller = inheritedResourceMatchers; + bigger = serviceResourceMatchersForResource; + } + Set tmp = new HashSet<>(); + if (smallestList.size() < smaller.size()) { + smallestList.stream().filter(smaller::contains).forEach(tmp::add); + smallestList.stream().filter(bigger::contains).forEach(tmp::add); + } else { + smaller.stream().filter(smallestList::contains).forEach(tmp::add); + if (smallestList.size() < bigger.size()) { + smallestList.stream().filter(bigger::contains).forEach(tmp::add); + } else { + bigger.stream().filter(smallestList::contains).forEach(tmp::add); + } + } + smallestList = tmp; + } + } else { + if (CollectionUtils.isEmpty(inheritedResourceMatchers) || CollectionUtils.isEmpty(serviceResourceMatchersForResource)) { + Set tmp = CollectionUtils.isEmpty(inheritedResourceMatchers) ? serviceResourceMatchersForResource : inheritedResourceMatchers; + smallestList = resourceKeys.size() == 1 || CollectionUtils.isEmpty(tmp) ? tmp : new HashSet<>(tmp); + } else { + smallestList = new HashSet<>(serviceResourceMatchersForResource); + smallestList.addAll(inheritedResourceMatchers); + } + } + + if (CollectionUtils.isEmpty(smallestList)) {// no tags for this resource, bail out + smallestList = null; + break; + } + } + } + + if (smallestList != null) { + ret = new ArrayList<>(smallestList); + ret.sort(RangerPolicyEvaluator.EVAL_ORDER_COMPARATOR); + } + + RangerPerfTracer.logAlways(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyRepository.getLikelyMatchPolicyEvaluators(" + resource.getAsString() + "): evaluatorCount=" + ret.size()); + } + + return ret; + } + + private List normalizeAndPrunePolicies(List rangerPolicies, final String componentType) { + if (CollectionUtils.isNotEmpty(rangerPolicies) && StringUtils.isNotBlank(componentType)) { + List policiesToPrune = null; + + for (RangerPolicy policy : rangerPolicies) { + if (isPolicyNeedsPruning(policy, componentType)) { + + if(policiesToPrune == null) { + policiesToPrune = new ArrayList<>(); + } + + policiesToPrune.add(policy); + } + } + + if(policiesToPrune != null) { + rangerPolicies.removeAll(policiesToPrune); + } + } + + return rangerPolicies == null ? new ArrayList<>() : rangerPolicies; + } + + private boolean isPolicyNeedsPruning(RangerPolicy policy, final String componentType) { + + normalizeAndPrunePolicyItems(policy.getPolicyItems(), componentType); + normalizeAndPrunePolicyItems(policy.getDenyPolicyItems(), componentType); + normalizeAndPrunePolicyItems(policy.getAllowExceptions(), componentType); + normalizeAndPrunePolicyItems(policy.getDenyExceptions(), componentType); + normalizeAndPrunePolicyItems(policy.getDataMaskPolicyItems(), componentType); + normalizeAndPrunePolicyItems(policy.getRowFilterPolicyItems(), componentType); + + if (!policy.getIsAuditEnabled() && + CollectionUtils.isEmpty(policy.getPolicyItems()) && + CollectionUtils.isEmpty(policy.getDenyPolicyItems()) && + CollectionUtils.isEmpty(policy.getAllowExceptions()) && + CollectionUtils.isEmpty(policy.getDenyExceptions()) && + CollectionUtils.isEmpty(policy.getDataMaskPolicyItems()) && + CollectionUtils.isEmpty(policy.getRowFilterPolicyItems())) { + return true; + } else { + return false; + } + } + + private List normalizeAndPrunePolicyItems(List policyItems, final String componentType) { + if(CollectionUtils.isNotEmpty(policyItems)) { + final String prefix = componentType + RangerAtlasConstants.COMPONENT_ACCESSTYPE_SEPARATOR; + List itemsToPrune = null; + + for (RangerPolicy.RangerPolicyItem policyItem : policyItems) { + List policyItemAccesses = policyItem.getAccesses(); + + if (CollectionUtils.isNotEmpty(policyItemAccesses)) { + List accessesToPrune = null; + + for (RangerPolicy.RangerPolicyItemAccess access : policyItemAccesses) { + String accessType = access.getType(); + + if (StringUtils.startsWith(accessType, prefix)) { + String newAccessType = StringUtils.removeStart(accessType, prefix); + + access.setType(newAccessType); + } else if (accessType.contains(RangerAtlasConstants.COMPONENT_ACCESSTYPE_SEPARATOR)) { + if(accessesToPrune == null) { + accessesToPrune = new ArrayList<>(); + } + + accessesToPrune.add(access); + } + } + + if(accessesToPrune != null) { + policyItemAccesses.removeAll(accessesToPrune); + } + + if (policyItemAccesses.isEmpty() && !policyItem.getDelegateAdmin()) { + if(itemsToPrune == null) { + itemsToPrune = new ArrayList<>(); + } + + itemsToPrune.add(policyItem); + + continue; + } + } + + if (policyItem instanceof RangerPolicy.RangerDataMaskPolicyItem) { + RangerPolicyItemDataMaskInfo dataMaskInfo = ((RangerPolicy.RangerDataMaskPolicyItem) policyItem).getDataMaskInfo(); + String maskType = dataMaskInfo.getDataMaskType(); + + if (StringUtils.startsWith(maskType, prefix)) { + dataMaskInfo.setDataMaskType(StringUtils.removeStart(maskType, prefix)); + } else if (maskType.contains(RangerAtlasConstants.COMPONENT_ACCESSTYPE_SEPARATOR)) { + if (itemsToPrune == null) { + itemsToPrune = new ArrayList<>(); + } + + itemsToPrune.add(policyItem); + } + } + } + + if(itemsToPrune != null) { + policyItems.removeAll(itemsToPrune); + } + } + + return policyItems; + } + + private static boolean isDelegateAdminPolicy(RangerPolicy policy) { + boolean ret = hasDelegateAdminItems(policy.getPolicyItems()) + || hasDelegateAdminItems(policy.getDenyPolicyItems()) + || hasDelegateAdminItems(policy.getAllowExceptions()) + || hasDelegateAdminItems(policy.getDenyExceptions()); + + return ret; + } + + private static boolean hasDelegateAdminItems(List items) { + boolean ret = false; + + if (CollectionUtils.isNotEmpty(items)) { + for (RangerPolicy.RangerPolicyItem item : items) { + if(item.getDelegateAdmin()) { + ret = true; + + break; + } + } + } + return ret; + } + + private static boolean skipBuildingPolicyEvaluator(RangerPolicy policy, RangerPolicyEngineOptions options) { + boolean ret = false; + if (!policy.getIsEnabled()) { + ret = true; + } else if (options.evaluateDelegateAdminOnly && !isDelegateAdminPolicy(policy)) { + ret = true; + } + return ret; + } + + private void init(RangerPolicyEngineOptions options) { + RangerServiceDefHelper serviceDefHelper = new RangerServiceDefHelper(serviceDef, false); + options.setServiceDefHelper(serviceDefHelper); + + List policyEvaluators = new ArrayList<>(); + List dataMaskPolicyEvaluators = new ArrayList<>(); + List rowFilterPolicyEvaluators = new ArrayList<>(); + + for (RangerPolicy policy : policies) { + if (skipBuildingPolicyEvaluator(policy, options)) { + continue; + } + + RangerPolicyEvaluator evaluator = buildPolicyEvaluator(policy, serviceDef, options); + + if (evaluator != null) { + if(StringUtils.isEmpty(policy.getPolicyType()) || RangerPolicy.POLICY_TYPE_ACCESS.equals(policy.getPolicyType())) { + policyEvaluators.add(evaluator); + } else if(RangerPolicy.POLICY_TYPE_DATAMASK.equals(policy.getPolicyType())) { + dataMaskPolicyEvaluators.add(evaluator); + } else if(RangerPolicy.POLICY_TYPE_ROWFILTER.equals(policy.getPolicyType())) { + rowFilterPolicyEvaluators.add(evaluator); + } else { + LOG.warn("RangerPolicyEngine: ignoring policy id=" + policy.getId() + " - invalid policyType '" + policy.getPolicyType() + "'"); + } + } + } + if (LOG.isInfoEnabled()) { + LOG.info("This policy engine contains " + (policyEvaluators.size()+dataMaskPolicyEvaluators.size()+rowFilterPolicyEvaluators.size()) + " policy evaluators"); + } + RangerPolicyEvaluator.PolicyEvalOrderComparator comparator = new RangerPolicyEvaluator.PolicyEvalOrderComparator(); + Collections.sort(policyEvaluators, comparator); + this.policyEvaluators = policyEvaluators; + + Collections.sort(dataMaskPolicyEvaluators, comparator); + this.dataMaskPolicyEvaluators = dataMaskPolicyEvaluators; + + Collections.sort(rowFilterPolicyEvaluators, comparator); + this.rowFilterPolicyEvaluators = rowFilterPolicyEvaluators; + + this.policyEvaluatorsMap = createPolicyEvaluatorsMap(); + + if(LOG.isDebugEnabled()) { + LOG.debug("policy evaluation order: " + this.policyEvaluators.size() + " policies"); + + int order = 0; + for(RangerPolicyEvaluator policyEvaluator : this.policyEvaluators) { + RangerPolicy policy = policyEvaluator.getPolicy(); + + LOG.debug("policy evaluation order: #" + (++order) + " - policy id=" + policy.getId() + "; name=" + policy.getName() + "; evalOrder=" + policyEvaluator.getEvalOrder()); + } + + LOG.debug("dataMask policy evaluation order: " + this.dataMaskPolicyEvaluators.size() + " policies"); + order = 0; + for(RangerPolicyEvaluator policyEvaluator : this.dataMaskPolicyEvaluators) { + RangerPolicy policy = policyEvaluator.getPolicy(); + + LOG.debug("dataMask policy evaluation order: #" + (++order) + " - policy id=" + policy.getId() + "; name=" + policy.getName() + "; evalOrder=" + policyEvaluator.getEvalOrder()); + } + + LOG.debug("rowFilter policy evaluation order: " + this.rowFilterPolicyEvaluators.size() + " policies"); + order = 0; + for(RangerPolicyEvaluator policyEvaluator : this.rowFilterPolicyEvaluators) { + RangerPolicy policy = policyEvaluator.getPolicy(); + + LOG.debug("rowFilter policy evaluation order: #" + (++order) + " - policy id=" + policy.getId() + "; name=" + policy.getName() + "; evalOrder=" + policyEvaluator.getEvalOrder()); + } + + LOG.debug("audit policy evaluation order: " + this.auditPolicyEvaluators.size() + " policies"); + order = 0; + for(RangerPolicyEvaluator policyEvaluator : this.auditPolicyEvaluators) { + RangerPolicy policy = policyEvaluator.getPolicy(); + + LOG.debug("rowFilter policy evaluation order: #" + (++order) + " - policy id=" + policy.getId() + "; name=" + policy.getName() + "; evalOrder=" + policyEvaluator.getEvalOrder()); + } + } + } + + private List buildContextEnrichers(RangerPolicyEngineOptions options) { + List contextEnrichers = new ArrayList<>(); + + if (StringUtils.isEmpty(zoneName) && CollectionUtils.isNotEmpty(serviceDef.getContextEnrichers())) { + for (RangerServiceDef.RangerContextEnricherDef enricherDef : serviceDef.getContextEnrichers()) { + if (enricherDef == null) { + continue; + } + + if (options.disableTagRetriever && StringUtils.equals(enricherDef.getEnricher(), RangerTagEnricher.class.getName())) { + if (MapUtils.isNotEmpty(enricherDef.getEnricherOptions())) { + Map enricherOptions = new HashMap<>(enricherDef.getEnricherOptions()); + + enricherOptions.remove(TAG_RETRIEVER_CLASSNAME_OPTION); + + enricherDef = new RangerServiceDef.RangerContextEnricherDef(enricherDef.getItemId(), enricherDef.getName(), enricherDef.getEnricher(), enricherOptions); + } + } + + if (!options.disableContextEnrichers || options.enableTagEnricherWithLocalRefresher && StringUtils.equals(enricherDef.getEnricher(), RangerTagEnricher.class.getName())) { + // This will be true only if the engine is initialized within ranger-admin + RangerServiceDef.RangerContextEnricherDef contextEnricherDef = enricherDef; + + if (options.enableTagEnricherWithLocalRefresher && StringUtils.equals(enricherDef.getEnricher(), RangerTagEnricher.class.getName())) { + contextEnricherDef = new RangerServiceDef.RangerContextEnricherDef(enricherDef.getItemId(), enricherDef.getName(), "org.apache.atlas.common.RangerAdminTagEnricher", null); + } + + RangerContextEnricher contextEnricher = buildContextEnricher(contextEnricherDef, options); + + if (contextEnricher != null) { + contextEnrichers.add(contextEnricher); + } + } + } + } + return contextEnrichers; + } + + private RangerContextEnricher buildContextEnricher(RangerServiceDef.RangerContextEnricherDef enricherDef, RangerPolicyEngineOptions options) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyRepository.buildContextEnricher(" + enricherDef + ")"); + } + + RangerContextEnricher ret = null; + + Map enricherDefOptions = enricherDef.getEnricherOptions(); + + String isEnabledAsString = enricherDefOptions.get("IsEnabled"); + + if (!StringUtils.equalsIgnoreCase(isEnabledAsString, "false")) { + RangerPerfTracer perf = null; + + if (RangerPerfTracer.isPerfTraceEnabled(PERF_CONTEXTENRICHER_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_CONTEXTENRICHER_INIT_LOG, "RangerContextEnricher.init(appId=" + appId + ",name=" + enricherDef.getName() + ")"); + } + + String name = enricherDef != null ? enricherDef.getName() : null; + String clsName = enricherDef != null ? enricherDef.getEnricher() : null; + + if (!StringUtils.isEmpty(clsName)) { + try { + @SuppressWarnings("unchecked") + Class enricherClass = (Class) Class.forName(clsName); + + ret = enricherClass.newInstance(); + } catch (Exception excp) { + LOG.error("failed to instantiate context enricher '" + clsName + "' for '" + name + "'", excp); + } + } + + if (ret != null) { + ret.setEnricherDef(enricherDef); + ret.setServiceName(componentServiceName); + ret.setServiceDef(componentServiceDef); + ret.setAppId(appId); + if (ret instanceof RangerAbstractContextEnricher) { + RangerAbstractContextEnricher abstractContextEnricher = (RangerAbstractContextEnricher) ret; + abstractContextEnricher.setPluginContext(pluginContext); + abstractContextEnricher.setPolicyEngineOptions(options); + } + ret.init(); + } + + RangerPerfTracer.log(perf); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyRepository.buildContextEnricher(" + enricherDef + "): " + ret); + } + return ret; + } + + private RangerPolicyEvaluator buildPolicyEvaluator(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyRepository.buildPolicyEvaluator(" + policy + "," + serviceDef + ", " + options + ")"); + } + + scrubPolicy(policy); + RangerAbstractPolicyEvaluator ret; + + if(StringUtils.equalsIgnoreCase(options.evaluatorType, RangerPolicyEvaluator.EVALUATOR_TYPE_CACHED)) { + ret = new RangerCachedPolicyEvaluator(); + } else { + ret = new RangerOptimizedPolicyEvaluator(); + } + + ret.setPluginContext(pluginContext); + ret.init(policy, serviceDef, options); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyRepository.buildPolicyEvaluator(" + policy + "," + serviceDef + "): " + ret); + } + + return ret; + } + + private boolean scrubPolicy(RangerPolicy policy) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyRepository.scrubPolicy(" + policy + ")"); + } + boolean altered = false; + Long policyId = policy.getId(); + Map resourceMap = policy.getResources(); + for (Map.Entry entry : resourceMap.entrySet()) { + String resourceName = entry.getKey(); + RangerPolicy.RangerPolicyResource resource = entry.getValue(); + Iterator iterator = resource.getValues().iterator(); + while (iterator.hasNext()) { + String value = iterator.next(); + if (value == null) { + LOG.warn("RangerPolicyRepository.scrubPolicyResource: found null resource value for " + resourceName + " in policy " + policyId + "! Removing..."); + iterator.remove(); + altered = true; + } + } + } + + scrubPolicyItems(policyId, policy.getPolicyItems()); + scrubPolicyItems(policyId, policy.getAllowExceptions()); + scrubPolicyItems(policyId, policy.getDenyPolicyItems()); + scrubPolicyItems(policyId, policy.getDenyExceptions()); + scrubPolicyItems(policyId, policy.getRowFilterPolicyItems()); + scrubPolicyItems(policyId, policy.getDataMaskPolicyItems()); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyRepository.scrubPolicy(" + policy + "): " + altered); + } + return altered; + } + + private void scrubPolicyItems(final Long policyId, final List policyItems) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyRepository.scrubPolicyItems(" + policyId + "): "); + } + + for (RangerPolicy.RangerPolicyItem policyItem : policyItems) { + removeNulls(policyItem.getUsers(), policyId, policyItem); + removeNulls(policyItem.getGroups(), policyId, policyItem); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyRepository.scrubPolicyItems(" + policyId + "): "); + } + } + + private void removeNulls(Collection strings, final Long policyId, final RangerPolicy.RangerPolicyItem policyItem) { + Iterator iterator = strings.iterator(); + + while (iterator.hasNext()) { + String value = iterator.next(); + if (value == null) { + LOG.warn("RangerPolicyRepository.removeNulls: found null user/group in policyItem '" + policyItem + "' in policy " + policyId + "! Removing..."); + iterator.remove(); + } + } + } + + private List getReorderedPolicyEvaluators(List evaluators) { + List ret = evaluators; + + if (CollectionUtils.isNotEmpty(evaluators)) { + ret = new ArrayList<>(evaluators); + Collections.sort(ret, new RangerPolicyEvaluator.PolicyEvalOrderComparator()); + } + + return ret; + } + + private Map createResourceTrieMap(List evaluators, boolean optimizeTrieForRetrieval) { + final Map ret; + + if (serviceDef != null && CollectionUtils.isNotEmpty(serviceDef.getResources())) { + ret = new HashMap<>(); + + for (RangerServiceDef.RangerResourceDef resourceDef : serviceDef.getResources()) { + ret.put(resourceDef.getName(), new RangerResourceTrie(resourceDef, evaluators, optimizeTrieForRetrieval, pluginContext)); + } + } else { + ret = null; + } + + return ret; + } + + private void updateTrie(Map trieMap, Integer policyDeltaType, RangerPolicyEvaluator oldEvaluator, RangerPolicyEvaluator newEvaluator) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyRepository.updateTrie(policyDeltaType=" + policyDeltaType + "): "); + } + for (RangerServiceDef.RangerResourceDef resourceDef : serviceDef.getResources()) { + + String resourceDefName = resourceDef.getName(); + + RangerResourceTrie trie = trieMap.get(resourceDefName); + + if (trie == null) { + if (RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE == policyDeltaType || RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE == policyDeltaType) { + LOG.warn("policyDeltaType is not for POLICY_CREATE and trie for resourceDef:[" + resourceDefName + "] was null! Should not have happened!!"); + } + trie = new RangerResourceTrie<>(resourceDef, new ArrayList<>(), true, pluginContext); + trieMap.put(resourceDefName, trie); + } + + if (policyDeltaType == RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE) { + removeEvaluatorFromTrie(oldEvaluator, trie, resourceDefName); + addEvaluatorToTrie(newEvaluator, trie, resourceDefName); + } else if (policyDeltaType == RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE) { + removeEvaluatorFromTrie(oldEvaluator, trie, resourceDefName); + } else if (policyDeltaType == RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE) { + removeEvaluatorFromTrie(oldEvaluator, trie, resourceDefName); + addEvaluatorToTrie(newEvaluator, trie, resourceDefName); + } else { + LOG.error("policyDeltaType:" + policyDeltaType + " is currently not handled, policy-id:[" + oldEvaluator.getPolicy().getId() +"]"); + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyRepository.updateTrie(policyDeltaType=" + policyDeltaType + "): "); + } + } + + private void addEvaluatorToTrie(RangerPolicyEvaluator newEvaluator, RangerResourceTrie trie, String resourceDefName) { + if (newEvaluator != null) { + RangerPolicy.RangerPolicyResource resource = newEvaluator.getPolicyResource().get(resourceDefName); + trie.add(resource, newEvaluator); + } else { + LOG.warn("Unexpected: newPolicyEvaluator is null for resource:[" + resourceDefName + "]"); + } + } + + private void removeEvaluatorFromTrie(RangerPolicyEvaluator oldEvaluator, RangerResourceTrie trie, String resourceDefName) { + if (oldEvaluator != null) { + trie.delete(oldEvaluator.getPolicyResource().get(resourceDefName), oldEvaluator); + } + } + + private Map createPolicyEvaluatorsMap() { + Map tmpPolicyEvaluatorMap = new HashMap<>(); + + for (RangerPolicyEvaluator evaluator : getPolicyEvaluators()) { + tmpPolicyEvaluatorMap.put(evaluator.getPolicy().getGuid(), evaluator); + } + for (RangerPolicyEvaluator evaluator : getDataMaskPolicyEvaluators()) { + tmpPolicyEvaluatorMap.put(evaluator.getPolicy().getGuid(), evaluator); + } + for (RangerPolicyEvaluator evaluator : getRowFilterPolicyEvaluators()) { + tmpPolicyEvaluatorMap.put(evaluator.getPolicy().getGuid(), evaluator); + } + + return tmpPolicyEvaluatorMap; + } + + + private RangerPolicyEvaluator addPolicy(RangerPolicy policy) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyRepository.addPolicy(" + policy +")"); + } + RangerPolicyEvaluator ret = null; + + if (StringUtils.equals(this.serviceDef.getName(), this.componentServiceDef.getName()) || !isPolicyNeedsPruning(policy, this.componentServiceDef.getName())) { + policies.add(policy); + + if (!skipBuildingPolicyEvaluator(policy, options)) { + + ret = buildPolicyEvaluator(policy, serviceDef, options); + + if (ret != null) { + if (StringUtils.isEmpty(policy.getPolicyType()) || RangerPolicy.POLICY_TYPE_ACCESS.equals(policy.getPolicyType())) { + policyEvaluators.add(ret); + } else if (RangerPolicy.POLICY_TYPE_DATAMASK.equals(policy.getPolicyType())) { + dataMaskPolicyEvaluators.add(ret); + } else if (RangerPolicy.POLICY_TYPE_ROWFILTER.equals(policy.getPolicyType())) { + rowFilterPolicyEvaluators.add(ret); + } else { + LOG.warn("RangerPolicyEngine: ignoring policy id=" + policy.getId() + " - invalid policyType '" + policy.getPolicyType() + "'"); + } + + if (!RangerPolicy.POLICY_TYPE_AUDIT.equals(policy.getPolicyType())) { + policyEvaluatorsMap.put(policy.getGuid(), ret); + } + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyRepository.addPolicy(" + policy +"): " + ret); + } + return ret; + } + + private void removePolicy(String guid) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyRepository.removePolicy(" + guid +")"); + } + Iterator iterator = policies.iterator(); + while (iterator.hasNext()) { + if (guid.equals(iterator.next().getGuid())) { + iterator.remove(); + //break; + } + } + + policyEvaluatorsMap.remove(guid); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyRepository.removePolicy(" + guid +")"); + } + } + + private void deletePolicyEvaluator(RangerPolicyEvaluator evaluator) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyRepository.deletePolicyEvaluator(" + evaluator.getPolicy() + ")"); + } + String policyType = evaluator.getPolicy().getPolicyType(); + if (StringUtils.isEmpty(policyType)) { + policyType = RangerPolicy.POLICY_TYPE_ACCESS; + } + + List evaluators = null; + + if (RangerPolicy.POLICY_TYPE_ACCESS.equals(policyType)) { + evaluators = this.policyEvaluators; + } else if (RangerPolicy.POLICY_TYPE_DATAMASK.equals(policyType)) { + evaluators = this.dataMaskPolicyEvaluators; + } else if (RangerPolicy.POLICY_TYPE_ROWFILTER.equals(policyType)) { + evaluators = this.rowFilterPolicyEvaluators; + } else { + LOG.error("Unknown policyType:[" + policyType +"]"); + } + if (evaluators != null) { + evaluators.remove(evaluator); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyRepository.deletePolicyEvaluator(" + evaluator.getPolicy() + ")"); + } + } + + private RangerPolicyEvaluator update(final RangerPolicyDelta delta, final RangerPolicyEvaluator currentEvaluator) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerPolicyRepository.update(delta=" + delta + ", currentEvaluator=" + (currentEvaluator == null ? null : currentEvaluator.getPolicy()) + ")"); + } + Integer changeType = delta.getChangeType(); + String policyType = delta.getPolicyType(); + String policyId = delta.getPolicyGuid(); + + RangerPolicy policy = delta.getPolicy(); + + RangerPolicyEvaluator newEvaluator = null; + + switch (changeType) { + case RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE: + if (currentEvaluator != null) { + removePolicy(policyId); + } + if (policy != null) { + newEvaluator = addPolicy(policy); + } + break; + case RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE: { + if (currentEvaluator != null) { + removePolicy(policyId); + } + if (policy != null) { + newEvaluator = addPolicy(policy); + } + } + break; + case RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE: { + if (currentEvaluator != null) { + removePolicy(policyId); + } + } + break; + } + + Map trieMap = getTrie(policyType); + + if (trieMap != null) { + updateTrie(trieMap, changeType, currentEvaluator, newEvaluator); + } + + if (changeType == RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE || changeType == RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE) { + if (currentEvaluator != null) { + deletePolicyEvaluator(currentEvaluator); + } + } + + RangerPolicyEvaluator ret = changeType == RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE ? currentEvaluator : newEvaluator; + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerPolicyRepository.update(delta=" + delta + ", currentEvaluator=" + (currentEvaluator == null ? null : currentEvaluator.getPolicy()) + ")"); + } + + return ret; + } + + Map getTrie(final String policyType) { + final Map ret; + switch (policyType) { + case RangerPolicy.POLICY_TYPE_ACCESS: + ret = policyResourceTrie; + break; + case RangerPolicy.POLICY_TYPE_DATAMASK: + ret = dataMaskResourceTrie; + break; + case RangerPolicy.POLICY_TYPE_ROWFILTER: + ret = rowFilterResourceTrie; + break; + case RangerPolicy.POLICY_TYPE_AUDIT: + ret = auditFilterResourceTrie; + break; + default: + ret = null; + } + return ret; + } + + static private final class AuditInfo { + final boolean isAudited; + final String auditPolicyId; + + AuditInfo(boolean isAudited, String auditPolicyId) { + this.isAudited = isAudited; + this.auditPolicyId = auditPolicyId; + } + String getAuditPolicyId() { + return this.auditPolicyId; + } + boolean getIsAudited() { + return isAudited; + } + } + + void reinit(List deltas) { + final boolean isExistingPolicies = CollectionUtils.isNotEmpty(this.policies); + + updateResourceTrie(deltas); + + if (StringUtils.isEmpty(zoneName) && CollectionUtils.isNotEmpty(this.policies)) { + if (!isExistingPolicies) { + this.contextEnrichers = buildContextEnrichers(options); + } + } else { + this.contextEnrichers = null; + } + } + + private void updateResourceTrie(List deltas) { + + Set flags = new HashSet<>(); + + for (RangerPolicyDelta delta : deltas) { + final Integer changeType = delta.getChangeType(); + final String serviceType = delta.getServiceType(); + final String policyId = delta.getPolicyGuid(); + final String policyType = delta.getPolicyType(); + + if (!serviceType.equals(this.serviceDef.getName())) { + continue; + } + + RangerPolicyEvaluator evaluator = null; + + switch (changeType) { + case RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE: + if (delta.getPolicy() == null) { + LOG.warn("Could not find policy for policy-id:[" + policyId + "]"); + continue; + } + evaluator = getPolicyEvaluator(policyId); + if (evaluator != null) { + LOG.warn("Unexpected: Found evaluator for policy-id:[" + policyId + "], changeType=CHANGE_TYPE_POLICY_CREATE"); + } + + break; + + case RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE: + evaluator = getPolicyEvaluator(policyId); + + if (evaluator == null) { + LOG.warn("Unexpected: Did not find evaluator for policy-id:[" + policyId + "], changeType=CHANGE_TYPE_POLICY_UPDATE"); + } + break; + + case RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE: + evaluator = getPolicyEvaluator(policyId); + if (evaluator == null) { + LOG.warn("Unexpected: Did not find evaluator for policy-id:[" + policyId + "], changeType=CHANGE_TYPE_POLICY_DELETE"); + } + break; + + default: + LOG.error("Unknown changeType:[" + changeType + "], Ignoring"); + break; + } + + evaluator = update(delta, evaluator); + + if (evaluator != null) { + switch (changeType) { + case RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE: + policyEvaluatorsMap.put(policyId, evaluator); + break; + + case RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE: + policyEvaluatorsMap.put(policyId, evaluator); + break; + + case RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE: + policyEvaluatorsMap.remove(policyId); + break; + + default: + break; + } + + flags.add(policyType); + } + } + + for (String policyType : flags) { + Map trie = getTrie(policyType); + + if (trie != null) { + for (Map.Entry entry : trie.entrySet()) { + entry.getValue().wrapUpUpdate(); + } + } + } + + if (auditFilterResourceTrie != null) { + for (Map.Entry entry : auditFilterResourceTrie.entrySet()) { + entry.getValue().wrapUpUpdate(); + } + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerResourceACLs.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerResourceACLs.java new file mode 100644 index 00000000000..e4a34c917ba --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerResourceACLs.java @@ -0,0 +1,548 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import org.apache.commons.lang.StringUtils; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemRowFilterInfo; +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import static org.apache.atlas.plugin.policyevaluator.RangerPolicyEvaluator.ACCESS_ALLOWED; +import static org.apache.atlas.plugin.policyevaluator.RangerPolicyEvaluator.ACCESS_DENIED; + +public class RangerResourceACLs { + final private Map> userACLs = new HashMap<>(); + final private Map> groupACLs = new HashMap<>(); + final private Map> roleACLs = new HashMap<>(); + final private List rowFilters = new ArrayList<>(); + final private List dataMasks = new ArrayList<>(); + + public RangerResourceACLs() { + } + + public Map> getUserACLs() { + return userACLs; + } + + public Map> getGroupACLs() { + return groupACLs; + } + + public Map> getRoleACLs() { return roleACLs; } + + public List getRowFilters() { return rowFilters; } + + public List getDataMasks() { return dataMasks; } + + public void finalizeAcls() { + Map publicGroupAccessInfo = groupACLs.get(RangerPolicyEngine.GROUP_PUBLIC); + if (publicGroupAccessInfo != null) { + + for (Map.Entry entry : publicGroupAccessInfo.entrySet()) { + String accessType = entry.getKey(); + AccessResult accessResult = entry.getValue(); + int access = accessResult.getResult(); + + if (access == ACCESS_DENIED || access == ACCESS_ALLOWED) { + for (Map.Entry> mapEntry : userACLs.entrySet()) { + Map mapValue = mapEntry.getValue(); + AccessResult savedAccessResult = mapValue.get(accessType); + if (savedAccessResult != null && !savedAccessResult.getIsFinal()) { + mapValue.remove(accessType); + } + } + + for (Map.Entry> mapEntry : groupACLs.entrySet()) { + if (!StringUtils.equals(mapEntry.getKey(), RangerPolicyEngine.GROUP_PUBLIC)) { + Map mapValue = mapEntry.getValue(); + AccessResult savedAccessResult = mapValue.get(accessType); + if (savedAccessResult != null && !savedAccessResult.getIsFinal()) { + mapValue.remove(accessType); + } + } + } + } + } + } + finalizeAcls(userACLs); + finalizeAcls(groupACLs); + finalizeAcls(roleACLs); + } + + public void setUserAccessInfo(String userName, String accessType, Integer access, RangerPolicy policy) { + Map userAccessInfo = userACLs.get(userName); + + if (userAccessInfo == null) { + userAccessInfo = new HashMap<>(); + + userACLs.put(userName, userAccessInfo); + } + + AccessResult accessResult = userAccessInfo.get(accessType); + + if (accessResult == null) { + accessResult = new AccessResult(access, policy); + + userAccessInfo.put(accessType, accessResult); + } else { + accessResult.setResult(access); + accessResult.setPolicy(policy); + } + } + + public void setGroupAccessInfo(String groupName, String accessType, Integer access, RangerPolicy policy) { + Map groupAccessInfo = groupACLs.get(groupName); + + if (groupAccessInfo == null) { + groupAccessInfo = new HashMap<>(); + + groupACLs.put(groupName, groupAccessInfo); + } + + AccessResult accessResult = groupAccessInfo.get(accessType); + + if (accessResult == null) { + accessResult = new AccessResult(access, policy); + + groupAccessInfo.put(accessType, accessResult); + } else { + accessResult.setResult(access); + accessResult.setPolicy(policy); + } + } + + public void setRoleAccessInfo(String roleName, String accessType, Integer access, RangerPolicy policy) { + Map roleAccessInfo = roleACLs.get(roleName); + + if (roleAccessInfo == null) { + roleAccessInfo = new HashMap<>(); + + roleACLs.put(roleName, roleAccessInfo); + } + + AccessResult accessResult = roleAccessInfo.get(accessType); + + if (accessResult == null) { + accessResult = new AccessResult(access, policy); + + roleAccessInfo.put(accessType, accessResult); + } else { + accessResult.setResult(access); + accessResult.setPolicy(policy); + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("{"); + + sb.append("UserACLs={"); + for (Map.Entry> entry : userACLs.entrySet()) { + sb.append("user=").append(entry.getKey()).append(":"); + sb.append("permissions={"); + for (Map.Entry permission : entry.getValue().entrySet()) { + sb.append("{Permission=").append(permission.getKey()).append(", value=").append(permission.getValue()).append("},"); + sb.append("{RangerPolicyID=").append(permission.getValue().getPolicy() == null ? null : permission.getValue().getPolicy().getId()).append("},"); + } + sb.append("},"); + } + sb.append("}"); + + sb.append(", GroupACLs={"); + for (Map.Entry> entry : groupACLs.entrySet()) { + sb.append("group=").append(entry.getKey()).append(":"); + sb.append("permissions={"); + for (Map.Entry permission : entry.getValue().entrySet()) { + sb.append("{Permission=").append(permission.getKey()).append(", value=").append(permission.getValue()).append("}, "); + sb.append("{RangerPolicy ID=").append(permission.getValue().getPolicy() == null ? null : permission.getValue().getPolicy().getId()).append("},"); + } + sb.append("},"); + } + sb.append("}"); + + sb.append(", RoleACLs={"); + for (Map.Entry> entry : roleACLs.entrySet()) { + sb.append("role=").append(entry.getKey()).append(":"); + sb.append("permissions={"); + for (Map.Entry permission : entry.getValue().entrySet()) { + sb.append("{Permission=").append(permission.getKey()).append(", value=").append(permission.getValue()).append("}, "); + sb.append("{RangerPolicy ID=").append(permission.getValue().getPolicy() == null ? null : permission.getValue().getPolicy().getId()).append("},"); + } + sb.append("},"); + } + sb.append("}"); + + sb.append("}"); + + sb.append(", rowFilters=["); + for (RowFilterResult rowFilter : rowFilters) { + rowFilter.toString(sb); + sb.append(" "); + } + sb.append("]"); + + sb.append(", dataMasks=["); + for (DataMaskResult dataMask : dataMasks) { + dataMask.toString(sb); + sb.append(" "); + } + sb.append("]"); + + return sb.toString(); + } + + private void finalizeAcls(Map> acls) { + List keysToRemove = new ArrayList<>(); + for (Map.Entry> entry : acls.entrySet()) { + if (entry.getValue().isEmpty()) { + keysToRemove.add(entry.getKey()); + } else { + for (Map.Entry permission : entry.getValue().entrySet()) { + permission.getValue().setIsFinal(true); + } + } + + } + for (String keyToRemove : keysToRemove) { + acls.remove(keyToRemove); + } + } + + @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY) + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @JsonIgnoreProperties(ignoreUnknown=true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class AccessResult { + private int result; + private boolean isFinal; + private RangerPolicy policy; + + public AccessResult() { + this(-1, null); + } + + public AccessResult(int result, RangerPolicy policy) { + this(result, false, policy); + } + + public AccessResult(int result, boolean isFinal, RangerPolicy policy) { + setIsFinal(isFinal); + setResult(result); + setPolicy(policy); + } + + public int getResult() { return result; } + + public void setResult(int result) { + if (!isFinal) { + this.result = result; + + if (this.result == ACCESS_DENIED) { + isFinal = true; + } + } + } + + public boolean getIsFinal() { return isFinal; } + + public void setIsFinal(boolean isFinal) { this.isFinal = isFinal; } + + public RangerPolicy getPolicy() { + return policy; + } + + public void setPolicy(RangerPolicy policy){ + this.policy = policy; + } + + @Override + public boolean equals(Object other) { + if (other == null) + return false; + if (other instanceof AccessResult) { + AccessResult otherObject = (AccessResult)other; + return result == otherObject.result && isFinal == otherObject.isFinal; + } else + return false; + + } + @Override + public String toString() { + if (result == ACCESS_ALLOWED) { + return "ALLOWED, final=" + isFinal; + } + if (result == ACCESS_DENIED) { + return "NOT_ALLOWED, final=" + isFinal; + } + return "CONDITIONAL_ALLOWED, final=" + isFinal; + } + } + + @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY) + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @JsonIgnoreProperties(ignoreUnknown=true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class DataMaskResult implements Serializable { + private static final long serialVersionUID = 1L; + + private final Set users; + private final Set groups; + private final Set roles; + private final Set accessTypes; + private final RangerPolicyItemDataMaskInfo maskInfo; + private boolean isConditional = false; + + public DataMaskResult(Set users, Set groups, Set roles, Set accessTypes, RangerPolicyItemDataMaskInfo maskInfo) { + this.users = users; + this.groups = groups; + this.roles = roles; + this.accessTypes = accessTypes; + this.maskInfo = maskInfo; + } + + public DataMaskResult(DataMaskResult that) { + this.users = that.users; + this.groups = that.groups; + this.roles = that.roles; + this.accessTypes = that.accessTypes; + this.maskInfo = that.maskInfo; + this.isConditional = that.isConditional; + } + + public Set getUsers() { return users; } + + public Set getGroups() { return groups; } + + public Set getRoles() { return roles; } + + public Set getAccessTypes() { return accessTypes; } + + public RangerPolicyItemDataMaskInfo getMaskInfo() { return maskInfo; } + + public boolean getIsConditional() { return isConditional; } + + public void setIsConditional(boolean isConditional) { this.isConditional = isConditional; } + + @Override + public int hashCode() { return Objects.hash(users, groups, roles, accessTypes, maskInfo, isConditional); } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } else if (other == null || getClass() != other.getClass()) { + return false; + } else { + DataMaskResult that = (DataMaskResult) other; + + return Objects.equals(users, that.users) && + Objects.equals(groups, that.groups) && + Objects.equals(roles, that.roles) && + Objects.equals(accessTypes, that.accessTypes) && + Objects.equals(maskInfo, that.maskInfo) && + isConditional == that.isConditional; + } + } + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("{"); + + if (users != null && !users.isEmpty()) { + sb.append("users:["); + for (String user : users) { + sb.append(user).append(' '); + } + sb.append("] "); + } + + if (groups != null && !groups.isEmpty()) { + sb.append("groups:["); + for (String group : groups) { + sb.append(group).append(' '); + } + sb.append("] "); + } + + if (roles != null && !roles.isEmpty()) { + sb.append("roles:["); + for (String role : roles) { + sb.append(role).append(' '); + } + sb.append("] "); + } + + if (accessTypes != null && !accessTypes.isEmpty()) { + sb.append("accessTypes:["); + for (String accessType : accessTypes) { + sb.append(accessType).append(' '); + } + sb.append("] "); + } + + sb.append("maskInfo="); + maskInfo.toString(sb); + sb.append(" isConditional=").append(isConditional); + + sb.append("}"); + + return sb; + } + } + + @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.ANY) + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @JsonIgnoreProperties(ignoreUnknown=true) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RowFilterResult implements Serializable { + private static final long serialVersionUID = 1L; + + private final Set users; + private final Set groups; + private final Set roles; + private final Set accessTypes; + private final RangerPolicyItemRowFilterInfo filterInfo; + private boolean isConditional = false; + + public RowFilterResult(Set users, Set groups, Set roles, Set accessTypes, RangerPolicyItemRowFilterInfo filterInfo) { + this.users = users; + this.groups = groups; + this.roles = roles; + this.accessTypes = accessTypes; + this.filterInfo = filterInfo; + } + + public RowFilterResult(RowFilterResult that) { + this.users = that.users; + this.groups = that.groups; + this.roles = that.roles; + this.accessTypes = that.accessTypes; + this.filterInfo = that.filterInfo; + this.isConditional = that.isConditional; + } + + public Set getUsers() { return users; } + + public Set getGroups() { return groups; } + + public Set getRoles() { return roles; } + + public Set getAccessTypes() { return accessTypes; } + + public RangerPolicyItemRowFilterInfo getFilterInfo() { return filterInfo; } + + public boolean getIsConditional() { return isConditional; } + + public void setIsConditional(boolean isConditional) { this.isConditional = isConditional; } + + @Override + public int hashCode() { return Objects.hash(users, groups, roles, accessTypes, filterInfo, isConditional); } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } else if (other == null || getClass() != other.getClass()) { + return false; + } else { + RowFilterResult that = (RowFilterResult) other; + + return Objects.equals(users, that.users) && + Objects.equals(groups, that.groups) && + Objects.equals(roles, that.roles) && + Objects.equals(accessTypes, that.accessTypes) && + Objects.equals(filterInfo, that.filterInfo) && + isConditional == that.isConditional; + } + } + + @Override + public String toString() { + return toString(new StringBuilder()).toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("{"); + + if (users != null && !users.isEmpty()) { + sb.append("users:["); + for (String user : users) { + sb.append(user).append(' '); + } + sb.append("] "); + } + + if (groups != null && !groups.isEmpty()) { + sb.append("groups:["); + for (String group : groups) { + sb.append(group).append(' '); + } + sb.append("] "); + } + + if (roles != null && !roles.isEmpty()) { + sb.append("roles:["); + for (String role : roles) { + sb.append(role).append(' '); + } + sb.append("] "); + } + + if (accessTypes != null && !accessTypes.isEmpty()) { + sb.append("accessTypes:["); + for (String accessType : accessTypes) { + sb.append(accessType).append(' '); + } + sb.append("] "); + } + + sb.append("filterInfo="); + filterInfo.toString(sb); + sb.append(" isConditional=").append(isConditional); + + sb.append("}"); + + return sb; + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerResourceAccessInfo.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerResourceAccessInfo.java new file mode 100644 index 00000000000..12f3dfd3f26 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerResourceAccessInfo.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + +import java.util.HashSet; +import java.util.Set; + +public class RangerResourceAccessInfo { + final private RangerAccessRequest request; + final private Set allowedUsers; + final private Set allowedGroups; + final private Set deniedUsers; + final private Set deniedGroups; + + + public RangerResourceAccessInfo(RangerAccessRequest request) { + this.request = request; + this.allowedUsers = new HashSet<>(); + this.allowedGroups = new HashSet<>(); + this.deniedUsers = new HashSet<>(); + this.deniedGroups = new HashSet<>(); + } + + public RangerResourceAccessInfo(RangerResourceAccessInfo other) { + this.request = other.request; + this.allowedUsers = other.allowedUsers == null ? new HashSet() : new HashSet(other.allowedUsers); + this.allowedGroups = other.allowedGroups == null ? new HashSet() : new HashSet(other.allowedGroups); + this.deniedUsers = other.deniedUsers == null ? new HashSet() : new HashSet(other.deniedUsers); + this.deniedGroups = other.deniedGroups == null ? new HashSet() : new HashSet(other.deniedGroups); + } + + public RangerAccessRequest getRequest() { + return request; + } + + public Set getAllowedUsers() { + return allowedUsers; + } + + public Set getAllowedGroups() { + return allowedGroups; + } + + public Set getDeniedUsers() { + return deniedUsers; + } + + public Set getDeniedGroups() { + return deniedGroups; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerResourceAccessInfo={"); + + sb.append("request={"); + if(request != null) { + sb.append(request); + } + sb.append("} "); + + sb.append("allowedUsers={"); + for(String user : allowedUsers) { + sb.append(user).append(" "); + } + sb.append("} "); + + sb.append("allowedGroups={"); + for(String group : allowedGroups) { + sb.append(group).append(" "); + } + sb.append("} "); + + sb.append("deniedUsers={"); + for(String user : deniedUsers) { + sb.append(user).append(" "); + } + sb.append("} "); + + sb.append("deniedGroups={"); + for(String group : deniedGroups) { + sb.append(group).append(" "); + } + sb.append("} "); + + sb.append("}"); + + return sb; + } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerResourceTrie.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerResourceTrie.java new file mode 100644 index 00000000000..ffcf768b19e --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerResourceTrie.java @@ -0,0 +1,1217 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyResource; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerResourceDef; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceEvaluator; +import org.apache.atlas.plugin.resourcematcher.RangerAbstractResourceMatcher; +import org.apache.atlas.plugin.resourcematcher.RangerResourceMatcher; +import org.apache.atlas.plugin.util.RangerPerfTracer; +import org.apache.atlas.plugin.util.ServiceDefUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +import static org.apache.atlas.plugin.resourcematcher.RangerPathResourceMatcher.DEFAULT_PATH_SEPARATOR_CHAR; +import static org.apache.atlas.plugin.resourcematcher.RangerPathResourceMatcher.OPTION_PATH_SEPARATOR; + +public class RangerResourceTrie { + private static final Log LOG = LogFactory.getLog(RangerResourceTrie.class); + private static final Log TRACE_LOG = RangerPerfTracer.getPerfLogger("resourcetrie.trace"); + private static final Log PERF_TRIE_INIT_LOG = RangerPerfTracer.getPerfLogger("resourcetrie.init"); + private static final Log PERF_TRIE_OP_LOG = RangerPerfTracer.getPerfLogger("resourcetrie.op"); + + private static final String DEFAULT_WILDCARD_CHARS = "*?"; + private static final String TRIE_BUILDER_THREAD_COUNT = "ranger.policyengine.trie.builder.thread.count"; + + private final RangerResourceDef resourceDef; + private final boolean optIgnoreCase; + private final boolean optWildcard; + private final String wildcardChars; + private final boolean isOptimizedForRetrieval; + private final Character separatorChar; + private Set inheritedEvaluators; + private final TrieNode root; + + public RangerResourceTrie(RangerResourceDef resourceDef, List evaluators) { + this(resourceDef, evaluators, true, null); + } + + public RangerResourceTrie(RangerResourceTrie other) { + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_TRIE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_TRIE_INIT_LOG, "RangerResourceTrie.copyTrie(name=" + other.resourceDef.getName() + ")"); + } + + this.resourceDef = other.resourceDef; + this.optIgnoreCase = other.optIgnoreCase; + this.optWildcard = other.optWildcard; + this.wildcardChars = other.wildcardChars; + this.isOptimizedForRetrieval = false; + this.separatorChar = other.separatorChar; + this.inheritedEvaluators = other.inheritedEvaluators != null ? new HashSet<>(other.inheritedEvaluators) : null; + this.root = copyTrieSubtree(other.root, null); + + RangerPerfTracer.logAlways(perf); + + if (PERF_TRIE_INIT_LOG.isDebugEnabled()) { + PERF_TRIE_INIT_LOG.debug(toString()); + } + + if (TRACE_LOG.isTraceEnabled()) { + StringBuilder sb = new StringBuilder(); + root.toString("", sb); + TRACE_LOG.trace("Trie Dump from RangerResourceTrie.copyTrie(name=" + other.resourceDef.getName() + "):\n{" + sb.toString() + "}"); + } + } + + public RangerResourceTrie(RangerResourceDef resourceDef, List evaluators, boolean isOptimizedForRetrieval, RangerPluginContext pluginContext) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerResourceTrie(" + resourceDef.getName() + ", evaluatorCount=" + evaluators.size() + ", isOptimizedForRetrieval=" + isOptimizedForRetrieval + ")"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_TRIE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_TRIE_INIT_LOG, "RangerResourceTrie.init(name=" + resourceDef.getName() + ")"); + } + + Configuration config = pluginContext != null ? pluginContext.getConfig() : null; + int builderThreadCount = config != null ? config.getInt(TRIE_BUILDER_THREAD_COUNT, 1) : 1; + + if (builderThreadCount < 1) { + builderThreadCount = 1; + } + + if (TRACE_LOG.isTraceEnabled()) { + TRACE_LOG.trace("builderThreadCount is set to [" + builderThreadCount + "]"); + } + + Map matcherOptions = resourceDef.getMatcherOptions(); + boolean optReplaceTokens = RangerAbstractResourceMatcher.getOptionReplaceTokens(matcherOptions); + String tokenReplaceSpecialChars = ""; + + if(optReplaceTokens) { + char delimiterStart = RangerAbstractResourceMatcher.getOptionDelimiterStart(matcherOptions); + char delimiterEnd = RangerAbstractResourceMatcher.getOptionDelimiterEnd(matcherOptions); + char delimiterEscape = RangerAbstractResourceMatcher.getOptionDelimiterEscape(matcherOptions); + + tokenReplaceSpecialChars += delimiterStart; + tokenReplaceSpecialChars += delimiterEnd; + tokenReplaceSpecialChars += delimiterEscape; + } + + this.resourceDef = resourceDef; + this.optIgnoreCase = RangerAbstractResourceMatcher.getOptionIgnoreCase(matcherOptions); + this.optWildcard = RangerAbstractResourceMatcher.getOptionWildCard(matcherOptions); + this.wildcardChars = optWildcard ? DEFAULT_WILDCARD_CHARS + tokenReplaceSpecialChars : "" + tokenReplaceSpecialChars; + this.isOptimizedForRetrieval = isOptimizedForRetrieval; + this.separatorChar = ServiceDefUtil.getCharOption(matcherOptions, OPTION_PATH_SEPARATOR, DEFAULT_PATH_SEPARATOR_CHAR); + + TrieNode tmpRoot = buildTrie(resourceDef, evaluators, builderThreadCount); + + if (builderThreadCount > 1 && tmpRoot == null) { // if multi-threaded trie-creation failed, build using a single thread + this.root = buildTrie(resourceDef, evaluators, 1); + } else { + this.root = tmpRoot; + } + + wrapUpUpdate(); + + RangerPerfTracer.logAlways(perf); + + if (PERF_TRIE_INIT_LOG.isDebugEnabled()) { + PERF_TRIE_INIT_LOG.debug(toString()); + } + + if (TRACE_LOG.isTraceEnabled()) { + StringBuilder sb = new StringBuilder(); + root.toString("", sb); + TRACE_LOG.trace("Trie Dump from RangerResourceTrie.init(name=" + resourceDef.getName() + "):\n{" + sb.toString() + "}"); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerResourceTrie(" + resourceDef.getName() + ", evaluatorCount=" + evaluators.size() + ", isOptimizedForRetrieval=" + isOptimizedForRetrieval + "): " + toString()); + } + } + + public Set getInheritedEvaluators() { + return inheritedEvaluators; + } + + public Set getEvaluatorsForResource(Object resource) { + return getEvaluatorsForResource(resource, RangerAccessRequest.ResourceMatchingScope.SELF); + } + + public Set getEvaluatorsForResource(Object resource, RangerAccessRequest.ResourceMatchingScope scope) { + if (resource instanceof String) { + return getEvaluatorsForResource((String) resource, scope); + } else if (resource instanceof Collection) { + if (CollectionUtils.isEmpty((Collection) resource)) { // treat empty collection same as empty-string + return getEvaluatorsForResource("", scope); + } else { + @SuppressWarnings("unchecked") + Collection resources = (Collection) resource; + + return getEvaluatorsForResources(resources, scope); + } + } + + return null; + } + + public void add(RangerPolicyResource resource, T evaluator) { + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_TRIE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_TRIE_INIT_LOG, "RangerResourceTrie.add(name=" + resource + ")"); + } + + if (resource == null) { + if (evaluator.isAncestorOf(resourceDef)) { + addInheritedEvaluator(evaluator); + } + } else { + if (resource.getIsExcludes()) { + addInheritedEvaluator(evaluator); + } else { + if (CollectionUtils.isNotEmpty(resource.getValues())) { + for (String value : resource.getValues()) { + insert(root, value, resource.getIsRecursive(), evaluator); + } + } + } + } + + RangerPerfTracer.logAlways(perf); + + if (TRACE_LOG.isTraceEnabled()) { + StringBuilder sb = new StringBuilder(); + root.toString("", sb); + TRACE_LOG.trace("Trie Dump from RangerResourceTrie.add(name=" + resource + "):\n{" + sb.toString() + "}"); + } + } + + public void delete(RangerPolicyResource resource, T evaluator) { + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_TRIE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_TRIE_INIT_LOG, "RangerResourceTrie.delete(name=" + resource + ")"); + } + + if (resource == null) { + if (evaluator.isAncestorOf(resourceDef)) { + removeInheritedEvaluator(evaluator); + } + } else if (resource.getIsExcludes()) { + removeInheritedEvaluator(evaluator); + } else { + for (String value : resource.getValues()) { + TrieNode node = getNodeForResource(value); + if (node != null) { + node.removeEvaluatorFromSubtree(evaluator); + } + } + } + + RangerPerfTracer.logAlways(perf); + + if (TRACE_LOG.isTraceEnabled()) { + StringBuilder sb = new StringBuilder(); + root.toString("", sb); + TRACE_LOG.trace("Trie Dump from RangerResourceTrie.delete(name=" + resource + "):\n{" + sb.toString() + "}"); + } + } + + public void wrapUpUpdate() { + if (root != null) { + root.wrapUpUpdate(); + if (TRACE_LOG.isTraceEnabled()) { + StringBuilder sb = new StringBuilder(); + root.toString("", sb); + TRACE_LOG.trace("Trie Dump from RangerResourceTrie.wrapUpUpdate(name=" + resourceDef.getName() + "):\n{" + sb.toString() + "}"); + } + } + } + + TrieNode getRoot() { + return root; + } + + private void addInheritedEvaluator(T evaluator) { + if (inheritedEvaluators == null) { + inheritedEvaluators = new HashSet<>(); + } + + inheritedEvaluators.add(evaluator); + } + + private void removeInheritedEvaluator(T evaluator) { + if (CollectionUtils.isNotEmpty(inheritedEvaluators) && inheritedEvaluators.contains(evaluator)) { + inheritedEvaluators.remove(evaluator); + if (CollectionUtils.isEmpty(inheritedEvaluators)) { + inheritedEvaluators = null; + } + } + } + + private TrieNode copyTrieSubtree(final TrieNode source, final TrieNode parent) { + if (TRACE_LOG.isTraceEnabled()) { + StringBuilder sb = new StringBuilder(); + source.toString(sb); + TRACE_LOG.trace("==> copyTrieSubtree(" + sb + ")"); + } + + TrieNode dest = new TrieNode<>(source.str); + + if (parent != null) { + parent.addChild(dest); + } + + synchronized (source.children) { + dest.isSetup = source.isSetup; + dest.isSharingParentWildcardEvaluators = source.isSharingParentWildcardEvaluators; + + if (source.isSharingParentWildcardEvaluators) { + if (dest.getParent() != null) { + dest.wildcardEvaluators = dest.getParent().getWildcardEvaluators(); + } else { + dest.wildcardEvaluators = null; + } + } else { + if (source.wildcardEvaluators != null) { + dest.wildcardEvaluators = new HashSet<>(source.wildcardEvaluators); + } else { + dest.wildcardEvaluators = null; + } + } + + if (source.evaluators != null) { + if (source.evaluators == source.wildcardEvaluators) { + dest.evaluators = dest.wildcardEvaluators; + } else { + dest.evaluators = new HashSet<>(source.evaluators); + } + } else { + dest.evaluators = null; + } + } + + Map> children = source.getChildren(); + + for (Map.Entry> entry : children.entrySet()) { + copyTrieSubtree(entry.getValue(), dest); + } + + if (TRACE_LOG.isTraceEnabled()) { + StringBuilder sourceAsString = new StringBuilder(), destAsString = new StringBuilder(); + source.toString(sourceAsString); + dest.toString(destAsString); + + TRACE_LOG.trace("<== copyTrieSubtree(" + sourceAsString + ") : " + destAsString); + } + + return dest; + } + + private TrieNode buildTrie(RangerResourceDef resourceDef, List evaluators, int builderThreadCount) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> buildTrie(" + resourceDef.getName() + ", evaluatorCount=" + evaluators.size() + ", isMultiThreaded=" + (builderThreadCount > 1) + ")"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_TRIE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_TRIE_INIT_LOG, "RangerResourceTrie.init(resourceDef=" + resourceDef.getName() + ")"); + } + + TrieNode ret = new TrieNode<>(null); + final boolean isMultiThreaded = builderThreadCount > 1; + final List builderThreads; + final Map builderThreadMap; + final String resourceName = resourceDef.getName(); + int lastUsedThreadIndex = 0; + + if (isMultiThreaded) { + builderThreads = new ArrayList<>(); + + for (int i = 0; i < builderThreadCount; i++) { + ResourceTrieBuilderThread t = new ResourceTrieBuilderThread(); + + t.setDaemon(true); + builderThreads.add(t); + t.start(); + } + + builderThreadMap = new HashMap<>(); + } else { + builderThreads = null; + builderThreadMap = null; + } + + for (T evaluator : evaluators) { + Map policyResources = evaluator.getPolicyResource(); + RangerPolicyResource policyResource = policyResources != null ? policyResources.get(resourceName) : null; + + if (policyResource == null) { + if (evaluator.isAncestorOf(resourceDef)) { + addInheritedEvaluator(evaluator); + } + + continue; + } + + if (policyResource.getIsExcludes()) { + addInheritedEvaluator(evaluator); + } else { + RangerResourceMatcher resourceMatcher = evaluator.getResourceMatcher(resourceName); + + if (resourceMatcher != null && (resourceMatcher.isMatchAny())) { + ret.addWildcardEvaluator(evaluator); + } else { + if (CollectionUtils.isNotEmpty(policyResource.getValues())) { + for (String resource : policyResource.getValues()) { + if (!isMultiThreaded) { + insert(ret, resource, policyResource.getIsRecursive(), evaluator); + } else { + try { + lastUsedThreadIndex = insert(ret, resource, policyResource.getIsRecursive(), evaluator, builderThreadMap, builderThreads, lastUsedThreadIndex); + } catch (InterruptedException ex) { + LOG.error("Failed to dispatch " + resource + " to " + builderThreads.get(lastUsedThreadIndex)); + LOG.error("Failing and retrying with one thread"); + + ret = null; + + break; + } + } + } + + if (ret == null) { + break; + } + } + } + } + } + + if (ret != null) { + if (isMultiThreaded) { + for (ResourceTrieBuilderThread t : builderThreads) { + try { + // Send termination signal to each thread + t.add("", false, null); + // Wait for threads to finish work + t.join(); + ret.getChildren().putAll(t.getSubtrees()); + } catch (InterruptedException ex) { + LOG.error("BuilderThread " + t + " was interrupted:", ex); + LOG.error("Failing and retrying with one thread"); + + ret = null; + + break; + } + } + + cleanUpThreads(builderThreads); + } + } + + RangerPerfTracer.logAlways(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== buildTrie(" + resourceDef.getName() + ", evaluatorCount=" + evaluators.size() + ", isMultiThreaded=" + isMultiThreaded + ") :" + ret); + } + + return ret; + } + + private void cleanUpThreads(List builderThreads) { + if (CollectionUtils.isNotEmpty(builderThreads)) { + for (ResourceTrieBuilderThread t : builderThreads) { + try { + if (t.isAlive()) { + t.interrupt(); + t.join(); + } + } catch (InterruptedException ex) { + LOG.error("Could not terminate thread " + t); + } + } + } + } + + private TrieData getTrieData() { + TrieData ret = new TrieData(); + + root.populateTrieData(ret); + + ret.maxDepth = getMaxDepth(); + + return ret; + } + + private int getMaxDepth() { + return root.getMaxDepth(); + } + + private Character getLookupChar(char ch) { + return optIgnoreCase ? Character.toLowerCase(ch) : ch; + } + + private Character getLookupChar(String str, int index) { + return getLookupChar(str.charAt(index)); + } + + private int insert(TrieNode currentRoot, String resource, boolean isRecursive, T evaluator, Map builderThreadMap, List builderThreads, int lastUsedThreadIndex) throws InterruptedException { + int ret = lastUsedThreadIndex; + final String prefix = getNonWildcardPrefix(resource); + + if (StringUtils.isNotEmpty(prefix)) { + char c = getLookupChar(prefix.charAt(0)); + Integer index = builderThreadMap.get(c); + + if (index == null) { + ret = index = (lastUsedThreadIndex + 1) % builderThreads.size(); + builderThreadMap.put(c, index); + } + + builderThreads.get(index).add(resource, isRecursive, evaluator); + } else { + currentRoot.addWildcardEvaluator(evaluator); + } + + return ret; + } + + private void insert(TrieNode currentRoot, String resource, boolean isRecursive, T evaluator) { + TrieNode curr = currentRoot; + final String prefix = getNonWildcardPrefix(resource); + final boolean isWildcard = prefix.length() != resource.length(); + + if (StringUtils.isNotEmpty(prefix)) { + curr = curr.getOrCreateChild(prefix); + } + + if(isWildcard || isRecursive) { + curr.addWildcardEvaluator(evaluator); + } else { + curr.addEvaluator(evaluator); + } + + } + + private String getNonWildcardPrefix(String str) { + int minIndex = str.length(); + + for (int i = 0; i < wildcardChars.length(); i++) { + int index = str.indexOf(wildcardChars.charAt(i)); + + if (index != -1 && index < minIndex) { + minIndex = index; + } + } + + return str.substring(0, minIndex); + } + + private Set getEvaluatorsForResource(String resource, RangerAccessRequest.ResourceMatchingScope scope) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerResourceTrie.getEvaluatorsForResource(" + resource + ", " + scope + ")"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_TRIE_OP_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_TRIE_OP_LOG, "RangerResourceTrie.getEvaluatorsForResource(resource=" + resource + ")"); + } + + TrieNode curr = root; + TrieNode parent = null; + TrieNode child = null; + final int len = resource.length(); + int i = 0; + + while (i < len) { + if (!isOptimizedForRetrieval) { + curr.setupIfNeeded(parent); + } + + child = curr.getChild(getLookupChar(resource, i)); + + if (child == null) { + break; + } + + final String childStr = child.getStr(); + + if (!resource.regionMatches(optIgnoreCase, i, childStr, 0, childStr.length())) { + break; + } + + parent = curr; + curr = child; + i += childStr.length(); + } + + if (!isOptimizedForRetrieval) { + curr.setupIfNeeded(parent); + } + + boolean isSelfMatch = (i == len); + Set ret = isSelfMatch ? curr.getEvaluators() : curr.getWildcardEvaluators(); + boolean includeEvaluatorsOfChildResources = scope == RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD; + + if (includeEvaluatorsOfChildResources) { + final Set childEvalautors = new HashSet<>(); + final boolean resourceEndsWithSep = resource.charAt(resource.length() - 1) == separatorChar; + + if (isSelfMatch) { // resource == path(curr) + if (resourceEndsWithSep) { // ex: resource=/tmp/ + curr.getChildren().values().stream().forEach(c -> c.collectChildEvaluators(separatorChar, 0, childEvalautors)); + } else { // ex: resource=/tmp + curr = curr.getChild(separatorChar); + + if (curr != null) { + curr.collectChildEvaluators(separatorChar, 1, childEvalautors); + } + } + } else if (child != null) { // resource != path(child) ex: (resource=/tmp, path(child)=/tmp/test.txt or path(child)=/tmpdir) + int remainingLen = len - i; + boolean isPrefixMatch = child.getStr().regionMatches(optIgnoreCase, 0, resource, i, remainingLen); + + if (isPrefixMatch) { + if (resourceEndsWithSep) { // ex: resource=/tmp/ + child.collectChildEvaluators(separatorChar, remainingLen, childEvalautors); + } else if (child.getStr().charAt(remainingLen) == separatorChar) { // ex: resource=/tmp + child.collectChildEvaluators(separatorChar, remainingLen + 1, childEvalautors); + } + } + } + + if (CollectionUtils.isNotEmpty(childEvalautors)) { + if (CollectionUtils.isNotEmpty(ret)) { + childEvalautors.addAll(ret); + } + + ret = childEvalautors; + } + } + + RangerPerfTracer.logAlways(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerResourceTrie.getEvaluatorsForResource(" + resource + ", " + scope + "): evaluatorCount=" + (ret == null ? 0 : ret.size())); + } + + return ret; + } + + private TrieNode getNodeForResource(String resource) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerResourceTrie.getNodeForResource(" + resource + ")"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_TRIE_OP_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_TRIE_OP_LOG, "RangerResourceTrie.getNodeForResource(resource=" + resource + ")"); + } + + TrieNode curr = root; + final int len = resource.length(); + int i = 0; + + while (i < len) { + final TrieNode child = curr.getChild(getLookupChar(resource, i)); + + if (child == null) { + break; + } + + final String childStr = child.getStr(); + + if (!resource.regionMatches(optIgnoreCase, i, childStr, 0, childStr.length())) { + break; + } + + curr = child; + i += childStr.length(); + } + + RangerPerfTracer.logAlways(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerResourceTrie.getNodeForResource(" + resource + ")"); + } + + return curr; + } + + private Set getEvaluatorsForResources(Collection resources, RangerAccessRequest.ResourceMatchingScope scope) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerResourceTrie.getEvaluatorsForResources(" + resources + ")"); + } + + Set ret = null; + Map evaluatorsMap = null; + + for (String resource : resources) { + Set resourceEvaluators = getEvaluatorsForResource(resource, scope); + + if (CollectionUtils.isEmpty(resourceEvaluators)) { + continue; + } + + if (evaluatorsMap == null) { + if (ret == null) { // first resource: don't create map yet + ret = resourceEvaluators; + } else if (ret != resourceEvaluators) { // if evaluator list is same as earlier resources, retain the list, else create a map + evaluatorsMap = new HashMap<>(); + + for (T evaluator : ret) { + evaluatorsMap.put(evaluator.getGuid(), evaluator); + } + + ret = null; + } + } + + if (evaluatorsMap != null) { + for (T evaluator : resourceEvaluators) { + evaluatorsMap.put(evaluator.getGuid(), evaluator); + } + } + } + + if (ret == null && evaluatorsMap != null) { + ret = new HashSet<>(evaluatorsMap.values()); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerResourceTrie.getEvaluatorsForResources(" + resources + "): evaluatorCount=" + (ret == null ? 0 : ret.size())); + } + + return ret; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + TrieData trieData = getTrieData(); + + sb.append("resourceName=").append(resourceDef.getName()); + sb.append("; optIgnoreCase=").append(optIgnoreCase); + sb.append("; optWildcard=").append(optWildcard); + sb.append("; wildcardChars=").append(wildcardChars); + sb.append("; nodeCount=").append(trieData.nodeCount); + sb.append("; leafNodeCount=").append(trieData.leafNodeCount); + sb.append("; singleChildNodeCount=").append(trieData.singleChildNodeCount); + sb.append("; maxDepth=").append(trieData.maxDepth); + sb.append("; evaluatorListCount=").append(trieData.evaluatorListCount); + sb.append("; wildcardEvaluatorListCount=").append(trieData.wildcardEvaluatorListCount); + sb.append("; evaluatorListRefCount=").append(trieData.evaluatorListRefCount); + sb.append("; wildcardEvaluatorListRefCount=").append(trieData.wildcardEvaluatorListRefCount); + + return sb.toString(); + } + + class ResourceTrieBuilderThread extends Thread { + + class WorkItem { + final String resourceName; + final boolean isRecursive; + final T evaluator; + + WorkItem(String resourceName, boolean isRecursive, T evaluator) { + this.resourceName = resourceName; + this.isRecursive = isRecursive; + this.evaluator = evaluator; + } + + @Override + public String toString() { + return + "resourceName=" + resourceName + + "isRecursive=" + isRecursive + + "evaluator=" + (evaluator != null? evaluator.getId() : null); + } + } + + private final TrieNode thisRoot = new TrieNode<>(null); + private final BlockingQueue workQueue = new LinkedBlockingQueue<>(); + + ResourceTrieBuilderThread() { + } + + void add(String resourceName, boolean isRecursive, T evaluator) throws InterruptedException { + workQueue.put(new WorkItem(resourceName, isRecursive, evaluator)); + } + + Map> getSubtrees() { return thisRoot.getChildren(); } + + @Override + public void run() { + if (LOG.isDebugEnabled()) { + LOG.debug("Running " + this); + } + + while (true) { + final WorkItem workItem; + + try { + workItem = workQueue.take(); + } catch (InterruptedException exception) { + LOG.error("Thread=" + this + " is interrupted", exception); + + break; + } + + if (workItem.evaluator != null) { + insert(thisRoot, workItem.resourceName, workItem.isRecursive, workItem.evaluator); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Received termination signal. " + workItem); + } + + break; + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Exiting " + this); + } + } + } + + static class TrieData { + int nodeCount; + int leafNodeCount; + int singleChildNodeCount; + int maxDepth; + int evaluatorListCount; + int wildcardEvaluatorListCount; + int evaluatorListRefCount; + int wildcardEvaluatorListRefCount; + } + + class TrieNode { + private String str; + private TrieNode parent; + private final Map> children = new HashMap<>(); + private Set evaluators; + private Set wildcardEvaluators; + private boolean isSharingParentWildcardEvaluators; + private volatile boolean isSetup = false; + + TrieNode(String str) { + this.str = str; + } + + String getStr() { + return str; + } + + void setStr(String str) { + this.str = str; + } + + TrieNode getParent() { + return parent; + } + + void setParent(TrieNode parent) { + this.parent = parent; + } + + Map> getChildren() { + return children; + } + + Set getEvaluators() { + return evaluators; + } + + Set getWildcardEvaluators() { + return wildcardEvaluators; + } + + TrieNode getChild(Character ch) { + return children.get(ch); + } + + void populateTrieData(TrieData trieData) { + trieData.nodeCount++; + + if (wildcardEvaluators != null) { + if (isSharingParentWildcardEvaluators) { + trieData.wildcardEvaluatorListRefCount++; + } else { + trieData.wildcardEvaluatorListCount++; + } + } + + if (evaluators != null) { + if (evaluators == wildcardEvaluators) { + trieData.evaluatorListRefCount++; + } else { + trieData.evaluatorListCount++; + } + } + + if (!children.isEmpty()) { + if (children.size() == 1) { + trieData.singleChildNodeCount++; + } + + for (Map.Entry> entry : children.entrySet()) { + TrieNode child = entry.getValue(); + + child.populateTrieData(trieData); + } + } else { + trieData.leafNodeCount++; + } + } + + int getMaxDepth() { + int ret = 0; + + for (Map.Entry> entry : children.entrySet()) { + TrieNode child = entry.getValue(); + + int maxChildDepth = child.getMaxDepth(); + + if (maxChildDepth > ret) { + ret = maxChildDepth; + } + } + + return ret + 1; + } + + TrieNode getOrCreateChild(String str) { + int len = str.length(); + TrieNode child = children.get(getLookupChar(str, 0)); + + if (child == null) { + child = new TrieNode<>(str); + + addChild(child); + } else { + final String childStr = child.getStr(); + final int childStrLen = childStr.length(); + final boolean isExactMatch = optIgnoreCase ? StringUtils.equalsIgnoreCase(childStr, str) : StringUtils.equals(childStr, str); + + if (!isExactMatch) { + final int numOfCharactersToMatch = Math.min(childStrLen, len); + int index = 1; + + for (; index < numOfCharactersToMatch; index++) { + if (getLookupChar(childStr, index) != getLookupChar(str, index)) { + break; + } + } + + if (index == numOfCharactersToMatch) { + // Matched all + if (childStrLen > len) { + // Existing node has longer string, need to break up this node + TrieNode newChild = new TrieNode<>(str); + + this.addChild(newChild); + child.setStr(childStr.substring(index)); + newChild.addChild(child); + + child = newChild; + } else { + // This is a longer string, build a child with leftover string + child = child.getOrCreateChild(str.substring(index)); + } + } else { + // Partial match for both; both have leftovers + String matchedPart = str.substring(0, index); + TrieNode newChild = new TrieNode<>(matchedPart); + + this.addChild(newChild); + child.setStr(childStr.substring(index)); + newChild.addChild(child); + + child = newChild.getOrCreateChild(str.substring(index)); + } + } + } + + return child; + } + + private void addChild(TrieNode child) { + children.put(getLookupChar(child.getStr(), 0), child); + child.setParent(this); + } + + void addEvaluator(U evaluator) { + if (evaluators == null) { + evaluators = new HashSet<>(); + } + + evaluators.add(evaluator); + } + + void addWildcardEvaluator(U evaluator) { + undoSetup(); + + if (wildcardEvaluators == null) { + wildcardEvaluators = new HashSet<>(); + } + + if (!wildcardEvaluators.contains(evaluator)) { + wildcardEvaluators.add(evaluator); + } + } + + void removeEvaluator(U evaluator) { + if (CollectionUtils.isNotEmpty(evaluators) && evaluators.contains(evaluator)) { + evaluators.remove(evaluator); + + if (CollectionUtils.isEmpty(evaluators)) { + evaluators = null; + } + } + } + + void removeWildcardEvaluator(U evaluator) { + if (CollectionUtils.isNotEmpty(wildcardEvaluators)) { + wildcardEvaluators.remove(evaluator); + + if (CollectionUtils.isEmpty(wildcardEvaluators)) { + wildcardEvaluators = null; + } + } + } + + void undoSetup() { + if (isSetup) { + for (TrieNode child : children.values()) { + child.undoSetup(); + } + + if (evaluators != null) { + if (evaluators == wildcardEvaluators) { + evaluators = null; + } else { + if (wildcardEvaluators != null) { + evaluators.removeAll(wildcardEvaluators); + + if (CollectionUtils.isEmpty(evaluators)) { + evaluators = null; + } + } + } + } + + if (wildcardEvaluators != null) { + if (isSharingParentWildcardEvaluators) { + wildcardEvaluators = null; + } else { + Set parentWildcardEvaluators = getParent() == null ? null : getParent().getWildcardEvaluators(); + + if (parentWildcardEvaluators != null) { + wildcardEvaluators.removeAll(parentWildcardEvaluators); + + if (CollectionUtils.isEmpty(wildcardEvaluators)) { + wildcardEvaluators = null; + } + } + } + } + + isSharingParentWildcardEvaluators = false; + isSetup = false; + } + } + + void removeSelfFromTrie() { + if (evaluators == null && wildcardEvaluators == null && children.size() == 0) { + TrieNode parent = getParent(); + if (parent != null) { + parent.children.remove(str.charAt(0)); + } + } + } + + void wrapUpUpdate() { + if (isOptimizedForRetrieval) { + RangerPerfTracer postSetupPerf = null; + + if (RangerPerfTracer.isPerfTraceEnabled(PERF_TRIE_INIT_LOG)) { + postSetupPerf = RangerPerfTracer.getPerfTracer(PERF_TRIE_INIT_LOG, "RangerResourceTrie.init(name=" + resourceDef.getName() + "-postSetup)"); + } + + postSetup(null); + + RangerPerfTracer.logAlways(postSetupPerf); + } + } + + void postSetup(Set parentWildcardEvaluators) { + setup(parentWildcardEvaluators); + + for (Map.Entry> entry : children.entrySet()) { + TrieNode child = entry.getValue(); + + child.postSetup(wildcardEvaluators); + } + } + + void setupIfNeeded(TrieNode parent) { + boolean setupNeeded = !isSetup; + + if (setupNeeded) { + synchronized (this.children) { + setupNeeded = !isSetup; + + if (setupNeeded) { + setup(parent == null ? null : parent.getWildcardEvaluators()); + + if (TRACE_LOG.isTraceEnabled()) { + StringBuilder sb = new StringBuilder(); + this.toString(sb); + TRACE_LOG.trace("Set up is completed for this TriNode as a part of access evaluation : [" + sb + "]"); + } + } + } + } + } + + void setup(Set parentWildcardEvaluators) { + if (!isSetup) { + // finalize wildcard-evaluators list by including parent's wildcard evaluators + if (parentWildcardEvaluators != null) { + if (CollectionUtils.isEmpty(this.wildcardEvaluators)) { + this.wildcardEvaluators = parentWildcardEvaluators; + } else { + for (U evaluator : parentWildcardEvaluators) { + addWildcardEvaluator(evaluator); + } + } + } + + this.isSharingParentWildcardEvaluators = wildcardEvaluators == parentWildcardEvaluators; + + // finalize evaluators list by including wildcard evaluators + if (wildcardEvaluators != null) { + if (CollectionUtils.isEmpty(this.evaluators)) { + this.evaluators = wildcardEvaluators; + } else { + for (U evaluator : wildcardEvaluators) { + addEvaluator(evaluator); + } + } + } + + isSetup = true; + } + } + + void collectChildEvaluators(Character sep, int startIdx, Set childEvaluators) { + setupIfNeeded(getParent()); + + final int sepPos = startIdx < str.length() ? str.indexOf(sep, startIdx) : -1; + + if (sepPos == -1) { // ex: startIdx=5, path(str)=/tmp/test, path(a child) could be: /tmp/test.txt, /tmp/test/, /tmp/test/a, /tmp/test/a/b + if (this.evaluators != null) { + childEvaluators.addAll(this.evaluators); + } + + children.values().stream().forEach(c -> c.collectChildEvaluators(sep, 0, childEvaluators)); + } else if (sepPos == (str.length() - 1)) { // ex: str=/tmp/test/, startIdx=5 + if (this.evaluators != null) { + childEvaluators.addAll(this.evaluators); + } + } + } + + private void removeEvaluatorFromSubtree(U evaluator) { + if (CollectionUtils.isNotEmpty(wildcardEvaluators) && wildcardEvaluators.contains(evaluator)) { + undoSetup(); + removeWildcardEvaluator(evaluator); + } else { + removeEvaluator(evaluator); + } + removeSelfFromTrie(); + } + + void toString(StringBuilder sb) { + String nodeValue = this.str; + + sb.append("nodeValue=").append(nodeValue); + sb.append("; isSetup=").append(isSetup); + sb.append("; isSharingParentWildcardEvaluators=").append(isSharingParentWildcardEvaluators); + sb.append("; childCount=").append(children.size()); + sb.append("; evaluators=[ "); + if (evaluators != null) { + for (U evaluator : evaluators) { + sb.append(evaluator.getId()).append(" "); + } + } + sb.append("]"); + + sb.append("; wildcardEvaluators=[ "); + if (wildcardEvaluators != null) { + for (U evaluator : wildcardEvaluators) { + sb.append(evaluator.getId()).append(" "); + } + } + sb.append("]"); + } + + void toString(String prefix, StringBuilder sb) { + String nodeValue = prefix + (str != null ? str : ""); + + sb.append(prefix); + toString(sb); + sb.append("]\n"); + + for (Map.Entry> entry : children.entrySet()) { + TrieNode child = entry.getValue(); + + child.toString(nodeValue, sb); + } + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerTagAccessRequest.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerTagAccessRequest.java new file mode 100644 index 00000000000..e3372110e86 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerTagAccessRequest.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + + +import org.apache.commons.lang.StringUtils; +import org.apache.atlas.plugin.contextenricher.RangerTagForEval; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; +import org.apache.atlas.plugin.util.RangerAccessRequestUtil; + +import java.util.Map; + +public class RangerTagAccessRequest extends RangerAccessRequestImpl { + private final RangerPolicyResourceMatcher.MatchType matchType; + public RangerTagAccessRequest(RangerTagForEval resourceTag, RangerServiceDef tagServiceDef, RangerAccessRequest request) { + matchType = resourceTag.getMatchType(); + super.setResource(new RangerTagResource(resourceTag.getType(), tagServiceDef)); + super.setUser(request.getUser()); + super.setUserGroups(request.getUserGroups()); + super.setUserRoles(request.getUserRoles()); + super.setAction(request.getAction()); + super.setAccessType(request.getAccessType()); + super.setAccessTime(request.getAccessTime()); + super.setRequestData(request.getRequestData()); + super.setAccessorsRequested(request.isAccessorsRequested()); + + Map requestContext = request.getContext(); + + RangerAccessRequestUtil.setCurrentTagInContext(request.getContext(), resourceTag); + RangerAccessRequestUtil.setCurrentResourceInContext(request.getContext(), request.getResource()); + RangerAccessRequestUtil.setCurrentUserInContext(request.getContext(), request.getUser()); + + String owner = request.getResource() != null ? request.getResource().getOwnerUser() : null; + + if (StringUtils.isNotEmpty(owner)) { + RangerAccessRequestUtil.setOwnerInContext(request.getContext(), owner); + } + super.setContext(requestContext); + + super.setClientType(request.getClientType()); + super.setClientIPAddress(request.getClientIPAddress()); + super.setRemoteIPAddress(request.getRemoteIPAddress()); + super.setForwardedAddresses(request.getForwardedAddresses()); + super.setSessionId(request.getSessionId()); + super.setResourceMatchingScope(request.getResourceMatchingScope()); + } + public RangerPolicyResourceMatcher.MatchType getMatchType() { + return matchType; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerTagResource.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerTagResource.java new file mode 100644 index 00000000000..7ce8a5d7473 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyengine/RangerTagResource.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyengine; + + +import org.apache.atlas.plugin.model.RangerServiceDef; + +public class RangerTagResource extends RangerAccessResourceImpl { + private static final String KEY_TAG = "tag"; + + + public RangerTagResource(String tagType, RangerServiceDef tagServiceDef) { + super.setValue(KEY_TAG, tagType); + super.setServiceDef(tagServiceDef); + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java new file mode 100644 index 00000000000..6db63f5f32e --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerAbstractPolicyEvaluator.java @@ -0,0 +1,207 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerResourceDef; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.atlas.plugin.policyengine.RangerPluginContext; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngineOptions; +import org.apache.atlas.plugin.util.ServiceDefUtil; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public abstract class RangerAbstractPolicyEvaluator implements RangerPolicyEvaluator { + private static final Log LOG = LogFactory.getLog(RangerAbstractPolicyEvaluator.class); + + private RangerPolicy policy; + private RangerServiceDef serviceDef; + private RangerResourceDef leafResourceDef; + private int evalOrder; + protected RangerPluginContext pluginContext = null; + + + public void setPluginContext(RangerPluginContext pluginContext) { this.pluginContext = pluginContext; } + + public RangerPluginContext getPluginContext() { return pluginContext; } + + @Override + public void init(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerAbstractPolicyEvaluator.init(" + policy + ", " + serviceDef + ")"); + } + + this.policy = getPrunedPolicy(policy); + this.serviceDef = serviceDef; + this.leafResourceDef = ServiceDefUtil.getLeafResourceDef(serviceDef, getPolicyResource()); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerAbstractPolicyEvaluator.init(" + this.policy + ", " + serviceDef + ")"); + } + } + + @Override + public long getId() { + return policy != null ? policy.getId() :-1; + } + + @Override + public String getGuid() { + return policy != null ? policy.getGuid() : "-1"; + } + + @Override + public Map getPolicyResource() { + return policy !=null ? policy.getResources() : null; + } + + @Override + public RangerPolicy getPolicy() { + return policy; + } + + @Override + public int getPolicyPriority() { + return policy != null && policy.getPolicyPriority() != null ? policy.getPolicyPriority() : RangerPolicy.POLICY_PRIORITY_NORMAL; + } + + @Override + public RangerServiceDef getServiceDef() { + return serviceDef; + } + + @Override + public boolean isAncestorOf(RangerResourceDef resourceDef) { + return ServiceDefUtil.isAncestorOf(serviceDef, leafResourceDef, resourceDef); + } + + public boolean hasAllow() { + return policy != null && CollectionUtils.isNotEmpty(policy.getPolicyItems()); + } + + protected boolean hasMatchablePolicyItem(RangerAccessRequest request) { + return hasAllow() || hasDeny(); + } + + public boolean hasDeny() { + return policy != null && (policy.getIsDenyAllElse() || CollectionUtils.isNotEmpty(policy.getDenyPolicyItems())); + } + + private RangerPolicy getPrunedPolicy(final RangerPolicy policy) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerAbstractPolicyEvaluator.getPrunedPolicy(" + policy + ")"); + } + + final RangerPolicy ret; + + final boolean isPruningNeeded; + final List prunedAllowItems; + final List prunedDenyItems; + final List prunedAllowExceptions; + final List prunedDenyExceptions; + + final RangerPluginContext pluginContext = getPluginContext(); + + if (pluginContext != null && pluginContext.getConfig().getPolicyEngineOptions().evaluateDelegateAdminOnly) { + prunedAllowItems = policy.getPolicyItems().stream().filter(RangerPolicy.RangerPolicyItem::getDelegateAdmin).collect(Collectors.toList()); + prunedDenyItems = policy.getDenyPolicyItems().stream().filter(RangerPolicy.RangerPolicyItem::getDelegateAdmin).collect(Collectors.toList()); + prunedAllowExceptions = policy.getAllowExceptions().stream().filter(RangerPolicy.RangerPolicyItem::getDelegateAdmin).collect(Collectors.toList()); + prunedDenyExceptions = policy.getDenyExceptions().stream().filter(RangerPolicy.RangerPolicyItem::getDelegateAdmin).collect(Collectors.toList()); + + isPruningNeeded = prunedAllowItems.size() != policy.getPolicyItems().size() + || prunedDenyItems.size() != policy.getDenyPolicyItems().size() + || prunedAllowExceptions.size() != policy.getAllowExceptions().size() + || prunedDenyExceptions.size() != policy.getDenyExceptions().size(); + } else { + prunedAllowItems = null; + prunedDenyItems = null; + prunedAllowExceptions = null; + prunedDenyExceptions = null; + isPruningNeeded = false; + } + + if (!isPruningNeeded) { + ret = policy; + } else { + ret = new RangerPolicy(); + ret.updateFrom(policy); + + ret.setId(policy.getId()); + ret.setGuid(policy.getGuid()); + ret.setVersion(policy.getVersion()); + ret.setServiceType(policy.getServiceType()); + + ret.setPolicyItems(prunedAllowItems); + ret.setDenyPolicyItems(prunedDenyItems); + ret.setAllowExceptions(prunedAllowExceptions); + ret.setDenyExceptions(prunedDenyExceptions); + } + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerAbstractPolicyEvaluator.getPrunedPolicy(isPruningNeeded=" + isPruningNeeded + ") : " + ret); + } + + return ret; + } + + @Override + public int getEvalOrder() { + return evalOrder; + } + @Override + public boolean isAuditEnabled() { + return policy != null && policy.getIsAuditEnabled(); + } + + public void setEvalOrder(int evalOrder) { + this.evalOrder = evalOrder; + } + + @Override + public PolicyACLSummary getPolicyACLSummary() { return null; } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerAbstractPolicyEvaluator={"); + + sb.append("policy={"); + if (policy != null) { + policy.toString(sb); + } + sb.append("} "); + + sb.append("}"); + + return sb; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java new file mode 100644 index 00000000000..86b58f59d1e --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerAbstractPolicyItemEvaluator.java @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + + +import org.apache.commons.collections.CollectionUtils; +import org.apache.atlas.plugin.conditionevaluator.RangerConditionEvaluator; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItem; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngine; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngineOptions; + +import java.util.Collections; +import java.util.List; + + +public abstract class RangerAbstractPolicyItemEvaluator implements RangerPolicyItemEvaluator { + + private static final int RANGER_POLICY_ITEM_EVAL_ORDER_DEFAULT = 1000; + + private static final int RANGER_POLICY_ITEM_EVAL_ORDER_MAX_DISCOUNT_USERSGROUPS = 100; + private static final int RANGER_POLICY_ITEM_EVAL_ORDER_MAX_DISCOUNT_ACCESS_TYPES = 25; + private static final int RANGER_POLICY_ITEM_EVAL_ORDER_MAX_DISCOUNT_CUSTOM_CONDITIONS = 25; + private static final int RANGER_POLICY_ITEM_EVAL_ORDER_CUSTOM_CONDITION_PENALTY = 5; + + final RangerPolicy policy; + final RangerPolicyEngineOptions options; + final RangerServiceDef serviceDef; + final RangerPolicyItem policyItem; + final int policyItemType; + final int policyItemIndex; + final long policyId; + final int evalOrder; + + List conditionEvaluators = Collections.emptyList(); + + RangerAbstractPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerPolicyItem policyItem, int policyItemType, int policyItemIndex, RangerPolicyEngineOptions options) { + this.serviceDef = serviceDef; + this.policyItem = policyItem; + this.policyItemType = policyItemType; + this.policyItemIndex = policyItemIndex; + this.options = options; + this.policyId = policy != null && policy.getId() != null ? policy.getId() : -1; + this.evalOrder = computeEvalOrder(); + this.policy = policy; + } + + @Override + public List getConditionEvaluators() { + return conditionEvaluators; + } + + @Override + public int getEvalOrder() { + return evalOrder; + } + + @Override + public RangerPolicyItem getPolicyItem() { + return policyItem; + } + + @Override + public int getPolicyItemType() { + return policyItemType; + } + + @Override + public int getPolicyItemIndex() { + return policyItemIndex; + } + + @Override + public String getComments() { + return null; + } + + protected String getServiceType() { + return serviceDef != null ? serviceDef.getName() : null; + } + + protected boolean getConditionsDisabledOption() { + return options != null && options.disableCustomConditions; + } + + private int computeEvalOrder() { + int evalOrder = RANGER_POLICY_ITEM_EVAL_ORDER_DEFAULT; + + if(policyItem != null) { + if((CollectionUtils.isNotEmpty(policyItem.getGroups()) && policyItem.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC)) + || (CollectionUtils.isNotEmpty(policyItem.getUsers()) && policyItem.getUsers().contains(RangerPolicyEngine.USER_CURRENT))) { + evalOrder -= RANGER_POLICY_ITEM_EVAL_ORDER_MAX_DISCOUNT_USERSGROUPS; + } else { + int userGroupCount = 0; + + if(! CollectionUtils.isEmpty(policyItem.getUsers())) { + userGroupCount += policyItem.getUsers().size(); + } + + if(! CollectionUtils.isEmpty(policyItem.getGroups())) { + userGroupCount += policyItem.getGroups().size(); + } + + evalOrder -= Math.min(RANGER_POLICY_ITEM_EVAL_ORDER_MAX_DISCOUNT_USERSGROUPS, userGroupCount); + } + + if(CollectionUtils.isNotEmpty(policyItem.getAccesses())) { + evalOrder -= Math.round(((float)RANGER_POLICY_ITEM_EVAL_ORDER_MAX_DISCOUNT_ACCESS_TYPES * policyItem.getAccesses().size()) / serviceDef.getAccessTypes().size()); + } + + int customConditionsPenalty = 0; + if(CollectionUtils.isNotEmpty(policyItem.getConditions())) { + customConditionsPenalty = RANGER_POLICY_ITEM_EVAL_ORDER_CUSTOM_CONDITION_PENALTY * policyItem.getConditions().size(); + } + int customConditionsDiscount = RANGER_POLICY_ITEM_EVAL_ORDER_MAX_DISCOUNT_CUSTOM_CONDITIONS - customConditionsPenalty; + if(customConditionsDiscount > 0) { + evalOrder -= customConditionsDiscount; + } + } + + return evalOrder; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerAuditPolicyEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerAuditPolicyEvaluator.java new file mode 100644 index 00000000000..aee66be1549 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerAuditPolicyEvaluator.java @@ -0,0 +1,405 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.model.AuditFilter; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItem; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemAccess; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerResourceDef; +import org.apache.atlas.plugin.policyengine.*; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; +import org.apache.atlas.plugin.util.RangerAccessRequestUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + + +public class RangerAuditPolicyEvaluator extends RangerDefaultPolicyEvaluator { + private static final Log LOG = LogFactory.getLog(RangerAuditPolicyEvaluator.class); + + private final RangerAuditPolicy auditPolicy; + private final boolean matchAnyResource; + private final List auditItemEvaluators = new ArrayList<>(); + + public RangerAuditPolicyEvaluator(AuditFilter auditFilter, int priority) { + this.auditPolicy = new RangerAuditPolicy(auditFilter, priority); + this.matchAnyResource = MapUtils.isEmpty(auditFilter.getResources()); + + if (LOG.isDebugEnabled()) { + LOG.debug("RangerAuditPolicyEvaluator(auditFilter=" + auditFilter + ", priority=" + priority + ", matchAnyResource=" + matchAnyResource + ")"); + } + } + + public RangerAuditPolicy getAuditPolicy() { return auditPolicy; } + + @Override + public void init(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerAuditPolicyEvaluator.init(" + auditPolicy.getId() + ")"); + } + + super.init(auditPolicy, serviceDef, options); + + int policyItemIndex = 1; + + for (RangerAuditPolicyItem policyItem : auditPolicy.getAuditPolicyItems()) { + RangerAuditPolicyItemEvaluator itemEvaluator = new RangerAuditPolicyItemEvaluator(serviceDef, auditPolicy, policyItem, policyItemIndex, options); + auditItemEvaluators.add(itemEvaluator); + policyItemIndex = policyItemIndex + 1; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerAuditPolicyEvaluator.init(" + auditPolicy.getId() + ")"); + } + } + + @Override + public boolean isAncestorOf(RangerResourceDef resourceDef) { + return matchAnyResource || super.isAncestorOf(resourceDef); + } + + @Override + public void evaluate(RangerAccessRequest request, RangerAccessResult result) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerAuditPolicyEvaluator.evaluate(" + auditPolicy.getId() + ", " + request + ", " + result + ")"); + } + + if (request != null && result != null) { + if (!result.getIsAuditedDetermined()) { + if (matchResource(request)) { + evaluatePolicyItems(request, result); + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerAuditPolicyEvaluator.evaluate(" + auditPolicy.getId() + ", " + request + ", " + result + ")"); + } + } + + @Override + protected void preprocessPolicy(RangerPolicy policy, RangerServiceDef serviceDef) { + super.preprocessPolicy(policy, serviceDef); + + Map> impliedAccessGrants = getImpliedAccessGrants(serviceDef); + + if (impliedAccessGrants == null || impliedAccessGrants.isEmpty()) { + return; + } + + preprocessPolicyItems(auditPolicy.getAuditPolicyItems(), impliedAccessGrants); + } + + private boolean matchResource(RangerAccessRequest request) { + final boolean ret; + + if (!matchAnyResource) { + RangerPolicyResourceMatcher.MatchType matchType; + + if (RangerTagAccessRequest.class.isInstance(request)) { + matchType = ((RangerTagAccessRequest) request).getMatchType(); + + if (matchType == RangerPolicyResourceMatcher.MatchType.ANCESTOR) { + matchType = RangerPolicyResourceMatcher.MatchType.SELF; + } + } else { + RangerPolicyResourceMatcher resourceMatcher = getPolicyResourceMatcher(); + + if (resourceMatcher != null) { + matchType = resourceMatcher.getMatchType(request.getResource(), request.getContext()); + } else { + matchType = RangerPolicyResourceMatcher.MatchType.NONE; + } + } + + if (request.isAccessTypeAny()) { + ret = matchType != RangerPolicyResourceMatcher.MatchType.NONE; + } else if (request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS) { + ret = matchType != RangerPolicyResourceMatcher.MatchType.NONE; + } else { + ret = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.SELF_AND_ALL_DESCENDANTS; + } + } else { + ret = true; + } + + return ret; + } + + private void evaluatePolicyItems(RangerAccessRequest request, RangerAccessResult result) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerAuditPolicyEvaluator.evaluatePolicyItems(" + auditPolicy.getId() + ", " + request + ", " + result + ")"); + } + + for (RangerAuditPolicyItemEvaluator itemEvaluator : auditItemEvaluators) { + if (itemEvaluator.isMatch(request, result)) { + Boolean isAudited = itemEvaluator.getIsAudited(); + + if (isAudited != null) { + result.setIsAudited(isAudited); + + break; + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerAuditPolicyEvaluator.evaluatePolicyItems(" + auditPolicy.getId() + ", " + request + ", " + result + ")"); + } + } + + @Override + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerAuditPolicyEvaluator={"); + + super.toString(sb); + + sb.append("auditPolicy={"); + auditPolicy.toString(sb); + sb.append("}"); + + sb.append(" matchAnyResource={").append(matchAnyResource).append("}"); + + sb.append("}"); + + return sb; + } + + + public static class RangerAuditPolicyItemEvaluator extends RangerDefaultPolicyItemEvaluator { + private final RangerAuditPolicyItem auditPolicyItem; + private final boolean matchAnyResult; + private final boolean matchAnyUser; + private final boolean matchAnyAction; + private final boolean hasResourceOwner; + + public RangerAuditPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerAuditPolicyItem policyItem, int policyItemIndex, RangerPolicyEngineOptions options) { + super(serviceDef, policy, policyItem, POLICY_ITEM_TYPE_ALLOW, policyItemIndex, options); + + this.auditPolicyItem = policyItem; + this.matchAnyResult = policyItem.getAccessResult() == null; + + List users = policyItem.getUsers(); + List groups = policyItem.getGroups(); + List roles = policyItem.getRoles(); + this.matchAnyUser = (CollectionUtils.isEmpty(users) && CollectionUtils.isEmpty(groups) && CollectionUtils.isEmpty(roles)) || + (CollectionUtils.isNotEmpty(groups) && groups.contains(RangerPolicyEngine.GROUP_PUBLIC)) || + (CollectionUtils.isNotEmpty(users) && users.contains(RangerPolicyEngine.USER_CURRENT)); + this.matchAnyAction = policyItem.getActions().isEmpty() && policyItem.getAccessTypes().isEmpty(); + this.hasResourceOwner = CollectionUtils.isNotEmpty(users) && users.contains(RangerPolicyEngine.RESOURCE_OWNER); + + if (LOG.isDebugEnabled()) { + LOG.debug("RangerAuditPolicyItemEvaluator(" + auditPolicyItem + ", matchAnyUser=" + matchAnyUser + ", matchAnyAction=" + matchAnyAction + ", hasResourceOwner=" + hasResourceOwner + ")"); + } + } + + public Boolean getIsAudited() { return auditPolicyItem.getIsAudited(); } + + public boolean isMatch(RangerAccessRequest request, RangerAccessResult result) { + boolean ret = matchAccessResult(result) && + matchUserGroupRole(request) && + matchAction(request); + + if (LOG.isDebugEnabled()) { + LOG.debug("RangerAuditPolicyItemEvaluator.isMatch(" + request + ", " + result + "): ret=" + ret); + } + + return ret; + } + + private boolean matchAccessResult(RangerAccessResult result) { + boolean ret = matchAnyResult; + + if (!ret) { + switch (auditPolicyItem.getAccessResult()) { + case DENIED: + ret = result.getIsAccessDetermined() && !result.getIsAllowed(); + break; + + case ALLOWED: + ret = result.getIsAccessDetermined() && result.getIsAllowed(); + break; + + case NOT_DETERMINED: + ret = !result.getIsAccessDetermined(); + break; + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("RangerAuditPolicyItemEvaluator.matchAccessResult(" + result + "): ret=" + ret); + } + + return ret; + } + + private boolean matchUserGroupRole(RangerAccessRequest request) { + boolean ret = matchAnyUser; + + if (!ret) { + + if (auditPolicyItem.getUsers() != null && request.getUser() != null) { + ret = auditPolicyItem.getUsers().contains(request.getUser()); + + if (!ret && hasResourceOwner) { + String owner = request.getResource() != null ? request.getResource().getOwnerUser() : null; + ret = request.getUser().equals(owner); + } + } + + if (!ret && auditPolicyItem.getGroups() != null && request.getUserGroups() != null) { + ret = CollectionUtils.containsAny(auditPolicyItem.getGroups(), request.getUserGroups()); + } + + if (!ret && auditPolicyItem.getRoles() != null) { + ret = CollectionUtils.containsAny(auditPolicyItem.getRoles(), RangerAccessRequestUtil.getCurrentUserRolesFromContext(request.getContext())); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("RangerAuditPolicyItemEvaluator.matchUserGroupRole(" + request + "): ret=" + ret); + } + + return ret; + } + + private boolean matchAction(RangerAccessRequest request) { + boolean ret = matchAnyAction; + + if (!ret) { + if (request.getAction() != null) { + ret = auditPolicyItem.getActions().contains(request.getAction()); + } + + if (!ret && request.getAccessType() != null) { + ret = auditPolicyItem.getAccessTypes().contains(request.getAccessType()); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("RangerAuditPolicyItemEvaluator.matchAction(" + request + "): ret=" + ret); + } + + return ret; + } + } + + public static class RangerAuditPolicy extends RangerPolicy { + private final List auditPolicyItems; + + public RangerAuditPolicy(AuditFilter auditFilter, int priority) { + setId((long)priority); + setResources(auditFilter.getResources()); + setPolicyType(POLICY_TYPE_AUDIT); + setPolicyPriority(priority); + + this.auditPolicyItems = Collections.singletonList(new RangerAuditPolicyItem(auditFilter)); + } + + public List getAuditPolicyItems() { return auditPolicyItems; } + } + + public static class RangerAuditPolicyItem extends RangerPolicyItem { + private final AuditFilter.AccessResult accessResult; + private final Set actions; + private final Set accessTypes; + private final Boolean isAudited; + + public RangerAuditPolicyItem(AuditFilter auditFilter) { + super(getPolicyItemAccesses(auditFilter.getAccessTypes()), auditFilter.getUsers(), auditFilter.getGroups(), auditFilter.getRoles(), null, null); + + this.accessResult = auditFilter.getAccessResult(); + this.actions = auditFilter.getActions() != null ? new HashSet<>(auditFilter.getActions()) : Collections.emptySet(); + this.accessTypes = auditFilter.getAccessTypes() != null ? new HashSet<>(auditFilter.getAccessTypes()) : Collections.emptySet(); + this.isAudited = auditFilter.getIsAudited(); + } + + public Set getActions() { return actions; } + + public Set getAccessTypes() { return accessTypes; } + + public AuditFilter.AccessResult getAccessResult() { return accessResult; } + + public Boolean getIsAudited() { return isAudited; } + + @Override + public StringBuilder toString(StringBuilder sb) { + if (sb == null) { + sb = new StringBuilder(); + } + + sb.append("RangerAuditPolicyItem={"); + super.toString(sb); + sb.append(" accessResult={").append(accessResult).append("}"); + + sb.append(" actions={"); + if (actions != null) { + for (String action : actions) { + if (action != null) { + sb.append(action).append(" "); + } + } + } + sb.append("}"); + + sb.append(" accessTypes={"); + if (accessTypes != null) { + for (String accessTypes : accessTypes) { + if (accessTypes != null) { + sb.append(accessTypes).append(" "); + } + } + } + sb.append("}"); + + sb.append(" isAudited={").append(isAudited).append("}"); + sb.append("}"); + + return sb; + } + + private static List getPolicyItemAccesses(List accessTypes) { + final List ret; + + if (accessTypes != null) { + ret = new ArrayList<>(accessTypes.size()); + + for (String accessType : accessTypes) { + ret.add(new RangerPolicyItemAccess(accessType)); + } + } else { + ret = Collections.emptyList(); + } + + return ret; + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerCachedPolicyEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerCachedPolicyEvaluator.java new file mode 100644 index 00000000000..03f6aef5f32 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerCachedPolicyEvaluator.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + +/* + * this class is deprecated, as the functionality is moved to base class RangerOptimizedPolicyEvaluator. + * Keeping the class simply for backward compatibility, in case this is used anywhere + */ +public class RangerCachedPolicyEvaluator extends RangerOptimizedPolicyEvaluator { +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerCustomConditionEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerCustomConditionEvaluator.java new file mode 100644 index 00000000000..5b77a06a0bc --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerCustomConditionEvaluator.java @@ -0,0 +1,202 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.conditionevaluator.RangerConditionEvaluator; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItem; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemCondition; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngineOptions; +import org.apache.atlas.plugin.util.RangerPerfTracer; + +import java.util.ArrayList; +import java.util.List; + + +public class RangerCustomConditionEvaluator { + + private static final Log LOG = LogFactory.getLog(RangerCustomConditionEvaluator.class); + private static final Log PERF_POLICY_INIT_LOG = RangerPerfTracer.getPerfLogger("policy.init"); + private static final Log PERF_POLICYITEM_INIT_LOG = RangerPerfTracer.getPerfLogger("policyitem.init"); + private static final Log PERF_POLICYCONDITION_INIT_LOG = RangerPerfTracer.getPerfLogger("policycondition.init"); + + public List getRangerPolicyConditionEvaluator(RangerPolicy policy, + RangerServiceDef serviceDef, + RangerPolicyEngineOptions options) { + List conditionEvaluators = new ArrayList<>(); + + if (!getConditionsDisabledOption(options) && CollectionUtils.isNotEmpty(policy.getConditions())) { + + RangerPerfTracer perf = null; + + String policyId = policy.getGuid(); + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_INIT_LOG, "RangerCustomConditionEvaluator.init(policyId=" + policyId + ")"); + } + + for (RangerPolicy.RangerPolicyItemCondition condition : policy.getConditions()) { + RangerServiceDef.RangerPolicyConditionDef conditionDef = getConditionDef(condition.getType(),serviceDef); + + if (conditionDef == null) { + LOG.error("RangerCustomConditionEvaluator.getRangerPolicyConditionEvaluator(policyId=" + policyId + "): conditionDef '" + condition.getType() + "' not found. Ignoring the condition"); + + continue; + } + + RangerConditionEvaluator conditionEvaluator = newConditionEvaluator(conditionDef.getEvaluator()); + + if (conditionEvaluator != null) { + conditionEvaluator.setServiceDef(serviceDef); + conditionEvaluator.setConditionDef(conditionDef); + conditionEvaluator.setPolicyItemCondition(condition); + + RangerPerfTracer perfConditionInit = null; + + if (RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYCONDITION_INIT_LOG)) { + perfConditionInit = RangerPerfTracer.getPerfTracer(PERF_POLICYCONDITION_INIT_LOG, "RangerConditionEvaluator.init(policyId=" + policyId + "policyConditionType=" + condition.getType() + ")"); + } + + conditionEvaluator.init(); + + RangerPerfTracer.log(perfConditionInit); + + conditionEvaluators.add(conditionEvaluator); + } else { + LOG.error("RangerCustomConditionEvaluator.getRangerPolicyConditionEvaluator(policyId=" + policyId + "): failed to init Policy ConditionEvaluator '" + condition.getType() + "'; evaluatorClassName='" + conditionDef.getEvaluator() + "'"); + } + } + + RangerPerfTracer.log(perf); + } + return conditionEvaluators; + } + + + public List getPolicyItemConditionEvaluator(RangerPolicy policy, + RangerPolicyItem policyItem, + RangerServiceDef serviceDef, + RangerPolicyEngineOptions options, + int policyItemIndex) { + + List conditionEvaluators = new ArrayList<>(); + + if (!getConditionsDisabledOption(options) && CollectionUtils.isNotEmpty(policyItem.getConditions())) { + + RangerPerfTracer perf = null; + + Long policyId = policy.getId(); + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYITEM_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYITEM_INIT_LOG, "RangerPolicyItemEvaluator.getRangerPolicyConditionEvaluator(policyId=" + policyId + ",policyItemIndex=" + policyItemIndex + ")"); + } + + for (RangerPolicyItemCondition condition : policyItem.getConditions()) { + RangerServiceDef.RangerPolicyConditionDef conditionDef = getConditionDef(condition.getType(), serviceDef); + + if (conditionDef == null) { + LOG.error("RangerCustomConditionEvaluator.getPolicyItemConditionEvaluator(policyId=" + policyId + "): conditionDef '" + condition.getType() + "' not found. Ignoring the condition"); + + continue; + } + + RangerConditionEvaluator conditionEvaluator = newConditionEvaluator(conditionDef.getEvaluator()); + + if (conditionEvaluator != null) { + conditionEvaluator.setServiceDef(serviceDef); + conditionEvaluator.setConditionDef(conditionDef); + conditionEvaluator.setPolicyItemCondition(condition); + + RangerPerfTracer perfConditionInit = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYCONDITION_INIT_LOG)) { + perfConditionInit = RangerPerfTracer.getPerfTracer(PERF_POLICYCONDITION_INIT_LOG, "RangerConditionEvaluator.init(policyId=" + policyId + ",policyItemIndex=" + policyItemIndex + ",policyConditionType=" + condition.getType() + ")"); + } + + conditionEvaluator.init(); + + RangerPerfTracer.log(perfConditionInit); + + conditionEvaluators.add(conditionEvaluator); + } else { + LOG.error("RangerCustomConditionEvaluator.getPolicyItemConditionEvaluator(policyId=" + policyId + "): failed to init PolicyItem ConditionEvaluator '" + condition.getType() + "'; evaluatorClassName='" + conditionDef.getEvaluator() + "'"); + } + } + RangerPerfTracer.log(perf); + } + return conditionEvaluators; + } + + private RangerServiceDef.RangerPolicyConditionDef getConditionDef(String conditionName, RangerServiceDef serviceDef) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerCustomConditionEvaluator.getConditionDef(" + conditionName + ")"); + } + + RangerServiceDef.RangerPolicyConditionDef ret = null; + + if (serviceDef != null && CollectionUtils.isNotEmpty(serviceDef.getPolicyConditions())) { + for(RangerServiceDef.RangerPolicyConditionDef conditionDef : serviceDef.getPolicyConditions()) { + if(StringUtils.equals(conditionName, conditionDef.getName())) { + ret = conditionDef; + break; + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerCustomConditionEvaluator.getConditionDef(" + conditionName + "): " + ret); + } + + return ret; + } + + + private RangerConditionEvaluator newConditionEvaluator(String className) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerCustomConditionEvaluator.newConditionEvaluator(" + className + ")"); + } + + RangerConditionEvaluator evaluator = null; + + try { + @SuppressWarnings("unchecked") + Class matcherClass = (Class)Class.forName(className); + + evaluator = matcherClass.newInstance(); + } catch(Throwable t) { + LOG.error("RangerCustomConditionEvaluator.newConditionEvaluator(" + className + "): error instantiating evaluator", t); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerCustomConditionEvaluator.newConditionEvaluator(" + className + "): " + evaluator); + } + + return evaluator; + } + + private boolean getConditionsDisabledOption(RangerPolicyEngineOptions options) { + return options != null && options.disableCustomConditions; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDataMaskPolicyItemEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDataMaskPolicyItemEvaluator.java new file mode 100644 index 00000000000..9ec0ebaeebd --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDataMaskPolicyItemEvaluator.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo; + + +public interface RangerDataMaskPolicyItemEvaluator extends RangerPolicyItemEvaluator { + void init(); + + RangerPolicyItemDataMaskInfo getDataMaskInfo(); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDefaultDataMaskPolicyItemEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDefaultDataMaskPolicyItemEvaluator.java new file mode 100644 index 00000000000..fb62a6f6c03 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDefaultDataMaskPolicyItemEvaluator.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicy.RangerDataMaskPolicyItem; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.policyengine.RangerAccessResult; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngineOptions; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; + + +public class RangerDefaultDataMaskPolicyItemEvaluator extends RangerDefaultPolicyItemEvaluator implements RangerDataMaskPolicyItemEvaluator { + final private RangerDataMaskPolicyItem dataMaskPolicyItem; + + public RangerDefaultDataMaskPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerDataMaskPolicyItem policyItem, int policyItemIndex, RangerPolicyEngineOptions options) { + super(serviceDef, policy, policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DATAMASK, policyItemIndex, options); + + dataMaskPolicyItem = policyItem; + } + + @Override + public RangerPolicyItemDataMaskInfo getDataMaskInfo() { + return dataMaskPolicyItem == null ? null : dataMaskPolicyItem.getDataMaskInfo(); + } + + @Override + public void updateAccessResult(RangerPolicyEvaluator policyEvaluator, RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType) { + RangerPolicyItemDataMaskInfo dataMaskInfo = getDataMaskInfo(); + + if (result.getMaskType() == null && dataMaskInfo != null) { + result.setMaskType(dataMaskInfo.getDataMaskType()); + result.setMaskCondition(dataMaskInfo.getConditionExpr()); + result.setMaskedValue(dataMaskInfo.getValueExpr()); + policyEvaluator.updateAccessResult(result, matchType, true, getComments()); + } + } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java new file mode 100644 index 00000000000..fa9b3bf3b31 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDefaultPolicyEvaluator.java @@ -0,0 +1,1432 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.conditionevaluator.RangerAbstractConditionEvaluator; +import org.apache.atlas.plugin.conditionevaluator.RangerConditionEvaluator; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicy.RangerDataMaskPolicyItem; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItem; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemAccess; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyResource; +import org.apache.atlas.plugin.model.RangerPolicy.RangerRowFilterPolicyItem; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerAccessTypeDef; +import org.apache.atlas.plugin.model.RangerValiditySchedule; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.atlas.plugin.policyengine.RangerAccessResource; +import org.apache.atlas.plugin.policyengine.RangerAccessResult; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngine; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngineOptions; +import org.apache.atlas.plugin.policyengine.RangerResourceAccessInfo; +import org.apache.atlas.plugin.policyengine.RangerTagAccessRequest; +import org.apache.atlas.plugin.policyresourcematcher.RangerDefaultPolicyResourceMatcher; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; +import org.apache.atlas.plugin.resourcematcher.RangerResourceMatcher; +import org.apache.atlas.plugin.util.RangerAccessRequestUtil; +import org.apache.atlas.plugin.util.RangerPerfTracer; +import org.apache.atlas.plugin.util.ServiceDefUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + + +public class RangerDefaultPolicyEvaluator extends RangerAbstractPolicyEvaluator { + private static final Log LOG = LogFactory.getLog(RangerDefaultPolicyEvaluator.class); + + private static final Log PERF_POLICY_INIT_LOG = RangerPerfTracer.getPerfLogger("policy.init"); + private static final Log PERF_POLICY_INIT_ACLSUMMARY_LOG = RangerPerfTracer.getPerfLogger("policy.init.ACLSummary"); + private static final Log PERF_POLICY_REQUEST_LOG = RangerPerfTracer.getPerfLogger("policy.request"); + private static final Log PERF_POLICYCONDITION_REQUEST_LOG = RangerPerfTracer.getPerfLogger("policycondition.request"); + + private RangerPolicyResourceMatcher resourceMatcher; + private List validityScheduleEvaluators; + private List allowEvaluators; + private List denyEvaluators; + private List allowExceptionEvaluators; + private List denyExceptionEvaluators; + private int customConditionsCount; + private List dataMaskEvaluators; + private List rowFilterEvaluators; + private List conditionEvaluators; + private String perfTag; + private PolicyACLSummary aclSummary = null; + private boolean useAclSummaryForEvaluation = false; + private boolean disableRoleResolution = true; + + protected boolean needsDynamicEval() { return resourceMatcher != null && resourceMatcher.getNeedsDynamicEval(); } + + @Override + public int getCustomConditionsCount() { + return customConditionsCount; + } + + @Override + public int getValidityScheduleEvaluatorsCount() { + return validityScheduleEvaluators.size(); + } + + @Override + public RangerPolicyResourceMatcher getPolicyResourceMatcher() { return resourceMatcher; } + + @Override + public RangerResourceMatcher getResourceMatcher(String resourceName) { + return resourceMatcher != null ? resourceMatcher.getResourceMatcher(resourceName) : null; + } + + @Override + public void init(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.init()"); + } + + StringBuilder perfTagBuffer = new StringBuilder(); + if (policy != null) { + perfTagBuffer.append("policyId=").append(policy.getId()).append(", policyName=").append(policy.getName()); + } + + perfTag = perfTagBuffer.toString(); + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_INIT_LOG, "RangerPolicyEvaluator.init(" + perfTag + ")"); + } + + super.init(policy, serviceDef, options); + + policy = getPolicy(); + + preprocessPolicy(policy, serviceDef); + + resourceMatcher = new RangerDefaultPolicyResourceMatcher(); + + resourceMatcher.setServiceDef(serviceDef); + resourceMatcher.setPolicy(policy); + resourceMatcher.setServiceDefHelper(options.getServiceDefHelper()); + resourceMatcher.init(); + + if(policy != null) { + validityScheduleEvaluators = createValidityScheduleEvaluators(policy); + + this.disableRoleResolution = options.disableRoleResolution; + + if (!options.disableAccessEvaluationWithPolicyACLSummary) { + aclSummary = createPolicyACLSummary(); + } + + useAclSummaryForEvaluation = aclSummary != null; + + if (useAclSummaryForEvaluation) { + allowEvaluators = Collections.emptyList(); + denyEvaluators = Collections.emptyList(); + allowExceptionEvaluators = Collections.emptyList(); + denyExceptionEvaluators = Collections.emptyList(); + } else { + allowEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW); + + if (ServiceDefUtil.getOption_enableDenyAndExceptionsInPolicies(serviceDef, pluginContext)) { + denyEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY); + allowExceptionEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS); + denyExceptionEvaluators = createPolicyItemEvaluators(policy, serviceDef, options, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS); + } else { + denyEvaluators = Collections.emptyList(); + allowExceptionEvaluators = Collections.emptyList(); + denyExceptionEvaluators = Collections.emptyList(); + } + } + + dataMaskEvaluators = createDataMaskPolicyItemEvaluators(policy, serviceDef, options, policy.getDataMaskPolicyItems()); + rowFilterEvaluators = createRowFilterPolicyItemEvaluators(policy, serviceDef, options, policy.getRowFilterPolicyItems()); + conditionEvaluators = createRangerPolicyConditionEvaluator(policy, serviceDef, options); + } else { + validityScheduleEvaluators = Collections.emptyList(); + allowEvaluators = Collections.emptyList(); + denyEvaluators = Collections.emptyList(); + allowExceptionEvaluators = Collections.emptyList(); + denyExceptionEvaluators = Collections.emptyList(); + dataMaskEvaluators = Collections.emptyList(); + rowFilterEvaluators = Collections.emptyList(); + conditionEvaluators = Collections.emptyList(); + } + + RangerPolicyItemEvaluator.EvalOrderComparator comparator = new RangerPolicyItemEvaluator.EvalOrderComparator(); + Collections.sort(allowEvaluators, comparator); + Collections.sort(denyEvaluators, comparator); + Collections.sort(allowExceptionEvaluators, comparator); + Collections.sort(denyExceptionEvaluators, comparator); + + /* dataMask, rowFilter policyItems must be evaulated in the order given in the policy; hence no sort + Collections.sort(dataMaskEvaluators); + Collections.sort(rowFilterEvaluators); + */ + + RangerPerfTracer.log(perf); + + if (useAclSummaryForEvaluation && (StringUtils.isEmpty(policy.getPolicyType()) || policy.getPolicyType().equals(RangerPolicy.POLICY_TYPE_ACCESS))) { + LOG.info("PolicyEvaluator for policy:[" + policy.getId() + "] is set up to use ACL Summary to evaluate access"); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.init()"); + } + } + + @Override + public boolean isApplicable(Date accessTime) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.isApplicable(" + accessTime + ")"); + } + + boolean ret = false; + + if (accessTime != null && CollectionUtils.isNotEmpty(validityScheduleEvaluators)) { + for (RangerValidityScheduleEvaluator evaluator : validityScheduleEvaluators) { + if (evaluator.isApplicable(accessTime.getTime())) { + ret = true; + break; + } + } + } else { + ret = true; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.isApplicable(" + accessTime + ") : " + ret); + } + + return ret; + } + + @Override + public void evaluate(RangerAccessRequest request, RangerAccessResult result) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.evaluate(policyId=" + getPolicy().getId() + ", " + request + ", " + result + ")"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_REQUEST_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_REQUEST_LOG, "RangerPolicyEvaluator.evaluate(requestHashCode=" + Integer.toHexString(System.identityHashCode(request)) + "," + + perfTag + ")"); + } + + if (request != null && result != null) { + + if (!result.getIsAccessDetermined() || !result.getIsAuditedDetermined() || request.isAccessorsRequested()) { + RangerPolicyResourceMatcher.MatchType matchType; + + if (RangerTagAccessRequest.class.isInstance(request)) { + matchType = ((RangerTagAccessRequest) request).getMatchType(); + if (matchType == RangerPolicyResourceMatcher.MatchType.ANCESTOR) { + matchType = RangerPolicyResourceMatcher.MatchType.SELF; + } + } else { + if (request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) { + request.getContext().put(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING, RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD); + } + matchType = resourceMatcher != null ? resourceMatcher.getMatchType(request.getResource(), request.getContext()) : RangerPolicyResourceMatcher.MatchType.NONE; + request.getContext().remove(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING); + } + + final boolean isMatched; + + if (request.isAccessTypeAny() || Boolean.TRUE.equals(RangerAccessRequestUtil.getIsAnyAccessInContext(request.getContext()))) { + isMatched = matchType != RangerPolicyResourceMatcher.MatchType.NONE; + } else if (request.getResourceMatchingScope() == RangerAccessRequest.ResourceMatchingScope.SELF_OR_DESCENDANTS) { + isMatched = matchType != RangerPolicyResourceMatcher.MatchType.NONE; + } else { + isMatched = matchType == RangerPolicyResourceMatcher.MatchType.SELF || matchType == RangerPolicyResourceMatcher.MatchType.SELF_AND_ALL_DESCENDANTS; + } + + if (isMatched) { + //Evaluate Policy Level Custom Conditions, if any and allowed then go ahead for policyItem level evaluation + if(matchPolicyCustomConditions(request)) { + if (!result.getIsAuditedDetermined()) { + if (isAuditEnabled()) { + result.setIsAudited(true); + result.setAuditPolicyId(getPolicy().getGuid()); + } + } + if (!result.getIsAccessDetermined() || request.isAccessorsRequested()) { + if (hasMatchablePolicyItem(request)) { + evaluatePolicyItems(request, matchType, result); + } + } + } + } + } + } + + RangerPerfTracer.log(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.evaluate(policyId=" + getPolicy().getId() + ", " + request + ", " + result + ")"); + } + } + + @Override + public boolean isMatch(RangerAccessResource resource, Map evalContext) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + resource + ", " + evalContext + ")"); + } + + boolean ret = false; + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_REQUEST_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_REQUEST_LOG, "RangerPolicyEvaluator.isMatch(resource=" + resource.getAsString() + "," + evalContext + "," + perfTag + ")"); + } + + if(resourceMatcher != null) { + ret = resourceMatcher.isMatch(resource, evalContext); + } + + RangerPerfTracer.log(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.isMatch(" + resource + ", " + evalContext + "): " + ret); + } + + return ret; + } + + @Override + public boolean isCompleteMatch(RangerAccessResource resource, Map evalContext) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.isCompleteMatch(" + resource + ", " + evalContext + ")"); + } + + boolean ret = resourceMatcher != null && resourceMatcher.isCompleteMatch(resource, evalContext); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.isCompleteMatch(" + resource + "): " + ret); + } + + return ret; + } + + @Override + public boolean isCompleteMatch(Map resources, Map evalContext) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.isCompleteMatch(" + resources + ", " + evalContext + ")"); + } + + boolean ret = resourceMatcher != null && resourceMatcher.isCompleteMatch(resources, evalContext); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.isCompleteMatch(" + resources + ", " + evalContext + "): " + ret); + } + + return ret; + } + + @Override + public Set getAllowedAccesses(RangerAccessResource resource, String user, Set userGroups, Set roles, Set accessTypes) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.getAllowedAccesses(" + resource + ", " + user + ", " + userGroups + ", " + roles + ", " + accessTypes + ")"); + } + + Set ret = null; + + if (isMatch(resource, null)) { + ret = new HashSet<>(); + for (String accessType : accessTypes) { + if (isAccessAllowed(user, userGroups, roles, resource.getOwnerUser(), accessType)) { + ret.add(accessType); + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.getAllowedAccesses(" + resource + ", " + user + ", " + userGroups + ", " + roles + ", " + accessTypes + "): " + ret); + } + + return ret; + } + + @Override + public Set getAllowedAccesses(Map resources, String user, Set userGroups, Set roles, Set accessTypes, Map evalContext) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.getAllowedAccesses(" + getPolicy().getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + accessTypes + ", " + evalContext + ")"); + } + + Set ret = null; + + if (isMatch(resources, evalContext)) { + if (CollectionUtils.isNotEmpty(accessTypes)) { + ret = new HashSet<>(); + for (String accessType : accessTypes) { + if (isAccessAllowed(user, userGroups, roles, null, accessType)) { + ret.add(accessType); + } + } + } else { + if (isAccessAllowed(user, userGroups, roles, null, null)) { + ret = new HashSet<>(); + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.getAllowedAccesses(" + getPolicy().getId() + ", " + user + ", " + userGroups + ", " + roles + ", " + accessTypes + ", " + evalContext + "): " + ret); + } + + return ret; + } + /* + * This is used only by test code + */ + + @Override + public boolean isAccessAllowed(Map resources, String user, Set userGroups, String accessType) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.isAccessAllowed(" + resources + ", " + user + ", " + userGroups + ", " + accessType + ")"); + } + + boolean ret = isAccessAllowed(user, userGroups, null, null, accessType) && isMatch(resources, null); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + resources + ", " + user + ", " + userGroups + ", " + accessType + "): " + ret); + } + + return ret; + } + + + @Override + public void getResourceAccessInfo(RangerAccessRequest request, RangerResourceAccessInfo result) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.getResourceAccessInfo(" + request + ", " + result + ")"); + } + RangerPolicyResourceMatcher.MatchType matchType; + if (RangerTagAccessRequest.class.isInstance(request)) { + matchType = ((RangerTagAccessRequest) request).getMatchType(); + } else { + matchType = resourceMatcher != null ? resourceMatcher.getMatchType(request.getResource(), request.getContext()) : RangerPolicyResourceMatcher.MatchType.NONE; + } + + final boolean isMatched = matchType != RangerPolicyResourceMatcher.MatchType.NONE; + + if (isMatched) { + + if (CollectionUtils.isNotEmpty(allowEvaluators)) { + Set users = new HashSet<>(); + Set groups = new HashSet<>(); + + getResourceAccessInfo(request, allowEvaluators, users, groups); + + if (CollectionUtils.isNotEmpty(allowExceptionEvaluators)) { + Set exceptionUsers = new HashSet<>(); + Set exceptionGroups = new HashSet<>(); + + getResourceAccessInfo(request, allowExceptionEvaluators, exceptionUsers, exceptionGroups); + + users.removeAll(exceptionUsers); + groups.removeAll(exceptionGroups); + } + + result.getAllowedUsers().addAll(users); + result.getAllowedGroups().addAll(groups); + } + if (matchType != RangerPolicyResourceMatcher.MatchType.DESCENDANT) { + if (CollectionUtils.isNotEmpty(denyEvaluators)) { + Set users = new HashSet(); + Set groups = new HashSet(); + + getResourceAccessInfo(request, denyEvaluators, users, groups); + + if (CollectionUtils.isNotEmpty(denyExceptionEvaluators)) { + Set exceptionUsers = new HashSet(); + Set exceptionGroups = new HashSet(); + + getResourceAccessInfo(request, denyExceptionEvaluators, exceptionUsers, exceptionGroups); + + users.removeAll(exceptionUsers); + groups.removeAll(exceptionGroups); + } + + result.getDeniedUsers().addAll(users); + result.getDeniedGroups().addAll(groups); + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.getResourceAccessInfo(" + request + ", " + result + ")"); + } + } + + /* + This API is called by policy-engine to support components which need to statically determine Ranger ACLs + for a given resource. It will always return a non-null object. The accesses that cannot be determined + statically will be marked as CONDITIONAL. + */ + + @Override + public PolicyACLSummary getPolicyACLSummary() { + if (aclSummary == null) { + boolean forceCreation = true; + aclSummary = createPolicyACLSummary(forceCreation); + } + + return aclSummary; + } + + @Override + public void updateAccessResult(RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType, boolean isAllowed, String reason) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.updateAccessResult(" + result + ", " + matchType +", " + isAllowed + ", " + reason + ", " + getId() + ")"); + } + if (!isAllowed) { + RangerAccessResource resource = result.getAccessRequest().getResource(); + if (resource != null && MapUtils.isNotEmpty(resource.getAsMap())) { + result.setIsAllowed(false); + result.setPolicyPriority(getPolicyPriority()); + result.setPolicyId(getGuid()); + result.setReason(reason); + result.setPolicyVersion(getPolicy().getVersion()); + } + } else { + if (!result.getIsAllowed()) { // if access is not yet allowed by another policy + if (matchType != RangerPolicyResourceMatcher.MatchType.ANCESTOR) { + result.setIsAllowed(true); + result.setPolicyPriority(getPolicyPriority()); + result.setPolicyId(getGuid()); + result.setReason(reason); + result.setPolicyVersion(getPolicy().getVersion()); + } + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.updateAccessResult(" + result + ", " + matchType +", " + isAllowed + ", " + reason + ", " + getId() + ")"); + } + } + + /* + This API is only called during initialization of Policy Evaluator if policy-engine is configured to use + PolicyACLSummary for access evaluation (that is, if disableAccessEvaluationWithPolicyACLSummary option + is set to false). It may return null object if all accesses for all user/groups cannot be determined statically. + */ + + private PolicyACLSummary createPolicyACLSummary() { + boolean forceCreation = false; + return createPolicyACLSummary(forceCreation); + } + + private PolicyACLSummary createPolicyACLSummary(boolean isCreationForced) { + PolicyACLSummary ret = null; + RangerPerfTracer perf = null; + + if (RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_INIT_ACLSUMMARY_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_INIT_ACLSUMMARY_LOG, "RangerPolicyEvaluator.init.ACLSummary(" + perfTag + ")"); + } + + RangerPolicy policy; + if (!disableRoleResolution && hasRoles(getPolicy())) { + policy = getPolicyWithRolesResolved(getPolicy()); + } else { + policy = getPolicy(); + } + + final boolean hasNonPublicGroupOrConditionsInAllowExceptions = hasNonPublicGroupOrConditions(policy.getAllowExceptions()); + final boolean hasNonPublicGroupOrConditionsInDenyExceptions = hasNonPublicGroupOrConditions(policy.getDenyExceptions()); + final boolean hasPublicGroupInAllowAndUsersInAllowExceptions = hasPublicGroupAndUserInException(policy.getPolicyItems(), policy.getAllowExceptions()); + final boolean hasPublicGroupInDenyAndUsersInDenyExceptions = hasPublicGroupAndUserInException(policy.getDenyPolicyItems(), policy.getDenyExceptions()); + final boolean hasContextSensitiveSpecification = hasContextSensitiveSpecification(); + final boolean hasRoles = hasRoles(policy); + final boolean isUsableForEvaluation = !hasNonPublicGroupOrConditionsInAllowExceptions + && !hasNonPublicGroupOrConditionsInDenyExceptions + && !hasPublicGroupInAllowAndUsersInAllowExceptions + && !hasPublicGroupInDenyAndUsersInDenyExceptions + && !hasContextSensitiveSpecification + && !hasRoles; + + if (isUsableForEvaluation || isCreationForced) { + ret = new PolicyACLSummary(); + + for (RangerPolicyItem policyItem : policy.getDenyPolicyItems()) { + ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY, hasNonPublicGroupOrConditionsInDenyExceptions || hasPublicGroupInDenyAndUsersInDenyExceptions); + } + + if (!hasNonPublicGroupOrConditionsInDenyExceptions && !hasPublicGroupInDenyAndUsersInDenyExceptions) { + for (RangerPolicyItem policyItem : policy.getDenyExceptions()) { + ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS, false); + } + } + + for (RangerPolicyItem policyItem : policy.getPolicyItems()) { + ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW, hasNonPublicGroupOrConditionsInAllowExceptions || hasPublicGroupInAllowAndUsersInAllowExceptions); + } + + if (!hasNonPublicGroupOrConditionsInAllowExceptions && !hasPublicGroupInAllowAndUsersInAllowExceptions) { + for (RangerPolicyItem policyItem : policy.getAllowExceptions()) { + ret.processPolicyItem(policyItem, RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS, false); + } + } + + for (RangerRowFilterPolicyItem policyItem : policy.getRowFilterPolicyItems()) { + ret.processRowFilterPolicyItem(policyItem); + } + + for (RangerDataMaskPolicyItem policyItem : policy.getDataMaskPolicyItems()) { + ret.processDataMaskPolicyItem(policyItem); + } + + final boolean isDenyAllElse = Boolean.TRUE.equals(policy.getIsDenyAllElse()); + + final Set allAccessTypeNames; + + if (isDenyAllElse) { + allAccessTypeNames = new HashSet<>(); + RangerServiceDef serviceDef = getServiceDef(); + for (RangerAccessTypeDef accessTypeDef :serviceDef.getAccessTypes()) { + if (!StringUtils.equalsIgnoreCase(accessTypeDef.getName(), "all")) { + allAccessTypeNames.add(accessTypeDef.getName()); + } + } + } else { + allAccessTypeNames = Collections.EMPTY_SET; + } + + ret.finalizeAcls(isDenyAllElse, allAccessTypeNames); + } + + RangerPerfTracer.logAlways(perf); + + return ret; + } + + private RangerPolicy getPolicyWithRolesResolved(final RangerPolicy policy) { + // Create new policy with no roles in it + // For each policyItem, expand roles into users and groups; and replace all policyItems with expanded roles - TBD + + RangerPolicy ret = new RangerPolicy(); + ret.updateFrom(policy); + ret.setId(policy.getId()); + ret.setGuid(policy.getGuid()); + ret.setVersion(policy.getVersion()); + + List policyItems = new ArrayList<>(); + List denyPolicyItems = new ArrayList<>(); + List allowExceptions = new ArrayList<>(); + List denyExceptions = new ArrayList<>(); + List dataMaskPolicyItems = new ArrayList<>(); + List rowFilterPolicyItems = new ArrayList<>(); + + for (RangerPolicyItem policyItem : policy.getPolicyItems()) { + RangerPolicyItem newPolicyItem = new RangerPolicyItem(policyItem.getAccesses(), policyItem.getUsers(), policyItem.getGroups(), policyItem.getRoles(), policyItem.getConditions(), policyItem.getDelegateAdmin()); + getPolicyItemWithRolesResolved(newPolicyItem, policyItem); + + policyItems.add(newPolicyItem); + } + ret.setPolicyItems(policyItems); + + for (RangerPolicyItem policyItem : policy.getDenyPolicyItems()) { + RangerPolicyItem newPolicyItem = new RangerPolicyItem(policyItem.getAccesses(), policyItem.getUsers(), policyItem.getGroups(), policyItem.getRoles(), policyItem.getConditions(), policyItem.getDelegateAdmin()); + getPolicyItemWithRolesResolved(newPolicyItem, policyItem); + + denyPolicyItems.add(newPolicyItem); + } + ret.setDenyPolicyItems(denyPolicyItems); + + for (RangerPolicyItem policyItem : policy.getAllowExceptions()) { + RangerPolicyItem newPolicyItem = new RangerPolicyItem(policyItem.getAccesses(), policyItem.getUsers(), policyItem.getGroups(), policyItem.getRoles(), policyItem.getConditions(), policyItem.getDelegateAdmin()); + getPolicyItemWithRolesResolved(newPolicyItem, policyItem); + + allowExceptions.add(newPolicyItem); + } + ret.setAllowExceptions(allowExceptions); + + for (RangerPolicyItem policyItem : policy.getDenyExceptions()) { + RangerPolicyItem newPolicyItem = new RangerPolicyItem(policyItem.getAccesses(), policyItem.getUsers(), policyItem.getGroups(), policyItem.getRoles(), policyItem.getConditions(), policyItem.getDelegateAdmin()); + getPolicyItemWithRolesResolved(newPolicyItem, policyItem); + + denyExceptions.add(newPolicyItem); + } + ret.setDenyExceptions(denyExceptions); + + for (RangerDataMaskPolicyItem policyItem : policy.getDataMaskPolicyItems()) { + RangerDataMaskPolicyItem newPolicyItem = new RangerDataMaskPolicyItem(policyItem.getAccesses(), policyItem.getDataMaskInfo(), policyItem.getUsers(), policyItem.getGroups(), policyItem.getRoles(), policyItem.getConditions(), policyItem.getDelegateAdmin()); + getPolicyItemWithRolesResolved(newPolicyItem, policyItem); + + dataMaskPolicyItems.add(newPolicyItem); + } + ret.setDataMaskPolicyItems(dataMaskPolicyItems); + + for (RangerRowFilterPolicyItem policyItem : policy.getRowFilterPolicyItems()) { + RangerRowFilterPolicyItem newPolicyItem = new RangerRowFilterPolicyItem(policyItem.getRowFilterInfo(), policyItem.getAccesses(), policyItem.getUsers(), policyItem.getGroups(), policyItem.getRoles(), policyItem.getConditions(), policyItem.getDelegateAdmin()); + getPolicyItemWithRolesResolved(newPolicyItem, policyItem); + + rowFilterPolicyItems.add(newPolicyItem); + } + ret.setRowFilterPolicyItems(rowFilterPolicyItems); + + return ret; + } + + private void getPolicyItemWithRolesResolved(RangerPolicyItem newPolicyItem, final RangerPolicyItem policyItem) { + Set usersFromRoles = new HashSet<>(); + Set groupsFromRoles = new HashSet<>(); + + List roles = policyItem.getRoles(); + + for (String role : roles) { + Set users = getPluginContext().getAuthContext().getRangerRolesUtil().getRoleToUserMapping().get(role); + Set groups = getPluginContext().getAuthContext().getRangerRolesUtil().getRoleToGroupMapping().get(role); + if (CollectionUtils.isNotEmpty(users)) { + usersFromRoles.addAll(users); + } + if (CollectionUtils.isNotEmpty(groups)) { + groupsFromRoles.addAll(groups); + } + if (CollectionUtils.isNotEmpty(usersFromRoles) || CollectionUtils.isNotEmpty(groupsFromRoles)) { + usersFromRoles.addAll(policyItem.getUsers()); + groupsFromRoles.addAll(policyItem.getGroups()); + + newPolicyItem.setUsers(new ArrayList<>(usersFromRoles)); + newPolicyItem.setGroups(new ArrayList<>(groupsFromRoles)); + newPolicyItem.setRoles(null); + } + } + } + + private boolean hasPublicGroupAndUserInException(List grants, List exceptionItems) { + boolean ret = false; + + if (CollectionUtils.isNotEmpty(exceptionItems)) { + boolean hasPublicGroupInGrant = false; + + for (RangerPolicyItem policyItem : grants) { + if (policyItem.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC) || policyItem.getUsers().contains(RangerPolicyEngine.USER_CURRENT)) { + hasPublicGroupInGrant = true; + break; + } + } + + if (hasPublicGroupInGrant) { + boolean hasPublicGroupInException = false; + + for (RangerPolicyItem policyItem : exceptionItems) { + if (policyItem.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC) || policyItem.getUsers().contains(RangerPolicyEngine.USER_CURRENT)) { + hasPublicGroupInException = true; + break; + } + } + + if (!hasPublicGroupInException) { + ret = true; + } + } + } + + return ret; + } + + protected void evaluatePolicyItems(RangerAccessRequest request, RangerPolicyResourceMatcher.MatchType matchType, RangerAccessResult result) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.evaluatePolicyItems(" + request + ", " + result + ", " + matchType + ")"); + } + + if (useAclSummaryForEvaluation && (StringUtils.isEmpty(getPolicy().getPolicyType()) || getPolicy().getPolicyType().equals(RangerPolicy.POLICY_TYPE_ACCESS))) { + if (LOG.isDebugEnabled()) { + LOG.debug("Using ACL Summary for access evaluation. PolicyId=[" + getId() + "]"); + } + Integer accessResult = lookupPolicyACLSummary(request.getUser(), request.getUserGroups(), request.getUserRoles(), request.isAccessTypeAny() || Boolean.TRUE.equals(RangerAccessRequestUtil.getIsAnyAccessInContext(request.getContext())) ? RangerPolicyEngine.ANY_ACCESS : request.getAccessType()); + if (accessResult != null) { + updateAccessResult(result, matchType, accessResult.equals(ACCESS_ALLOWED), null); + } else if (getPolicy().getIsDenyAllElse()) { + updateAccessResult(result, RangerPolicyResourceMatcher.MatchType.NONE, false, "matched deny-all-else policy"); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Using policyItemEvaluators for access evaluation. PolicyId=[" + getId() + "]"); + } + + RangerPolicyItemEvaluator matchedPolicyItem = getMatchingPolicyItem(request, result); + + if (matchedPolicyItem != null) { + matchedPolicyItem.updateAccessResult(this, result, matchType); + } else if (getPolicy().getIsDenyAllElse() && (StringUtils.isEmpty(getPolicy().getPolicyType()) || getPolicy().getPolicyType().equals(RangerPolicy.POLICY_TYPE_ACCESS))) { + updateAccessResult(result, RangerPolicyResourceMatcher.MatchType.NONE, false, "matched deny-all-else policy"); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.evaluatePolicyItems(" + request + ", " + result + ", " + matchType + ")"); + } + } + + private Integer lookupPolicyACLSummary(String user, Set userGroups, Set userRoles, String accessType) { + Integer accessResult = null; + + Map accesses = aclSummary.getUsersAccessInfo().get(user); + + accessResult = lookupAccess(user, accessType, accesses); + + if (accessResult == null) { + + Set groups = new HashSet<>(); + groups.add(RangerPolicyEngine.GROUP_PUBLIC); + groups.addAll(userGroups); + + for (String userGroup : groups) { + accesses = aclSummary.getGroupsAccessInfo().get(userGroup); + accessResult = lookupAccess(userGroup, accessType, accesses); + if (accessResult != null) { + break; + } + } + + if (userRoles !=null) { + for (String userRole : userRoles) { + accesses = aclSummary.getRolesAccessInfo().get(userRole); + accessResult = lookupAccess(userRole, accessType, accesses); + if (accessResult != null) { + break; + } + } + } + } + + return accessResult; + } + + private Integer lookupAccess(String userOrGroup, String accessType, Map accesses) { + Integer ret = null; + if (accesses != null) { + if (accessType.equals(RangerPolicyEngine.ANY_ACCESS)) { + ret = getAccessResultForAnyAccess(accesses); + } else { + PolicyACLSummary.AccessResult accessResult = accesses.get(accessType); + if (accessResult != null) { + if (accessResult.getResult() == ACCESS_CONDITIONAL) { + LOG.error("Access should not be conditional at this point! user=[" + userOrGroup + "], " + "accessType=[" + accessType + "]"); + } else { + ret = accessResult.getResult(); + } + } + } + } + return ret; + } + + private Integer getAccessResultForAnyAccess(Map accesses) { + final Integer ret; + + int allowedAccessCount = 0; + int deniedAccessCount = 0; + + for (Map.Entry entry : accesses.entrySet()) { + if (StringUtils.equals(entry.getKey(), RangerPolicyEngine.ADMIN_ACCESS)) { + // Don't count admin access if present + continue; + } + PolicyACLSummary.AccessResult accessResult = entry.getValue(); + if (accessResult.getResult() == ACCESS_ALLOWED) { + allowedAccessCount++; + break; + } else if (accessResult.getResult() == ACCESS_DENIED) { + deniedAccessCount++; + } + } + + if (allowedAccessCount > 0) { + // At least one access allowed + ret = ACCESS_ALLOWED; + } else if (deniedAccessCount == getServiceDef().getAccessTypes().size()) { + // All accesses explicitly denied + ret = ACCESS_DENIED; + } else { + ret = null; + } + + return ret; + } + + protected RangerPolicyItemEvaluator getDeterminingPolicyItem(String user, Set userGroups, Set roles, String owner, String accessType) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.getDeterminingPolicyItem(" + user + ", " + userGroups + ", " + roles + ", " + owner + ", " + accessType + ")"); + } + + RangerPolicyItemEvaluator ret = null; + + /* + * 1. if a deny matches without hitting any deny-exception, return that + * 2. if an allow matches without hitting any allow-exception, return that + */ + ret = getMatchingPolicyItem(user, userGroups, roles, owner, accessType, denyEvaluators, denyExceptionEvaluators); + + if(ret == null) { + ret = getMatchingPolicyItem(user, userGroups, roles, owner, accessType, allowEvaluators, allowExceptionEvaluators); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.getDeterminingPolicyItem(" + user + ", " + userGroups + ", " + roles + ", " + owner + ", " + accessType + "): " + ret); + } + + return ret; + } + + private void getResourceAccessInfo(RangerAccessRequest request, List policyItems, Set users, Set groups) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.getResourceAccessInfo(" + request + ", " + policyItems + ", " + users + ", " + groups + ")"); + } + + if (CollectionUtils.isNotEmpty(policyItems)) { + for (RangerPolicyItemEvaluator policyItemEvaluator : policyItems) { + if (policyItemEvaluator.matchAccessType(request.getAccessType()) && policyItemEvaluator.matchCustomConditions(request)) { + if (CollectionUtils.isNotEmpty(policyItemEvaluator.getPolicyItem().getUsers())) { + users.addAll(policyItemEvaluator.getPolicyItem().getUsers()); + } + + if (CollectionUtils.isNotEmpty(policyItemEvaluator.getPolicyItem().getGroups())) { + groups.addAll(policyItemEvaluator.getPolicyItem().getGroups()); + } + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.getResourceAccessInfo(" + request + ", " + policyItems + ", " + users + ", " + groups + ")"); + } + } + + protected boolean isMatch(RangerPolicy policy, Map evalContext) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + policy.getId() + ", " + evalContext + ")"); + } + + final boolean ret = isMatch(policy.getResources(), evalContext); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.isMatch(" + policy.getId() + ", " + evalContext + "): " + ret); + } + + return ret; + } + + protected boolean isMatch(Map resources, Map evalContext) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.isMatch(" + resources + ", " + evalContext + ")"); + } + + boolean ret = resourceMatcher != null && resourceMatcher.isMatch(resources, evalContext); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.isMatch(" + resources + ", " + evalContext + "): " + ret); + } + + return ret; + } + + protected boolean isAccessAllowed(String user, Set userGroups, Set roles, String owner, String accessType) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.isAccessAllowed(" + user + ", " + userGroups + ", " + roles + ", " + owner + ", " + accessType + ")"); + } + + boolean ret = false; + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_REQUEST_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_REQUEST_LOG, "RangerPolicyEvaluator.isAccessAllowed(hashCode=" + Integer.toHexString(System.identityHashCode(this)) + "," + perfTag + ")"); + } + + if (useAclSummaryForEvaluation && (StringUtils.isEmpty(getPolicy().getPolicyType()) || getPolicy().getPolicyType().equals(RangerPolicy.POLICY_TYPE_ACCESS))) { + if (LOG.isDebugEnabled()) { + LOG.debug("Using ACL Summary for checking if access is allowed. PolicyId=[" + getId() +"]"); + } + + Integer accessResult = StringUtils.isEmpty(accessType) ? null : lookupPolicyACLSummary(user, userGroups, roles, accessType); + if (accessResult != null && accessResult.equals(ACCESS_ALLOWED)) { + ret = true; + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Using policyItemEvaluators for checking if access is allowed. PolicyId=[" + getId() +"]"); + } + + RangerPolicyItemEvaluator item = this.getDeterminingPolicyItem(user, userGroups, roles, owner, accessType); + + if (item != null && item.getPolicyItemType() == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW) { + ret = true; + } + } + + RangerPerfTracer.log(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.isAccessAllowed(" + user + ", " + userGroups + ", " + roles + ", " + owner + ", " + accessType + "): " + ret); + } + + return ret; + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerDefaultPolicyEvaluator={"); + + super.toString(sb); + + sb.append("resourceMatcher={"); + if(resourceMatcher != null) { + resourceMatcher.toString(sb); + } + sb.append("} "); + + sb.append("}"); + + return sb; + } + + protected void preprocessPolicy(RangerPolicy policy, RangerServiceDef serviceDef) { + if(policy == null || (!hasAllow() && !hasDeny()) || serviceDef == null) { + return; + } + + Map> impliedAccessGrants = getImpliedAccessGrants(serviceDef); + + if(impliedAccessGrants == null || impliedAccessGrants.isEmpty()) { + return; + } + + preprocessPolicyItems(policy.getPolicyItems(), impliedAccessGrants); + preprocessPolicyItems(policy.getDenyPolicyItems(), impliedAccessGrants); + preprocessPolicyItems(policy.getAllowExceptions(), impliedAccessGrants); + preprocessPolicyItems(policy.getDenyExceptions(), impliedAccessGrants); + preprocessPolicyItems(policy.getDataMaskPolicyItems(), impliedAccessGrants); + preprocessPolicyItems(policy.getRowFilterPolicyItems(), impliedAccessGrants); + } + + protected void preprocessPolicyItems(List policyItems, Map> impliedAccessGrants) { + for(RangerPolicyItem policyItem : policyItems) { + if(CollectionUtils.isEmpty(policyItem.getAccesses())) { + continue; + } + + // Only one round of 'expansion' is done; multi-level impliedGrants (like shown below) are not handled for now + // multi-level impliedGrants: given admin=>write; write=>read: must imply admin=>read,write + for(Map.Entry> e : impliedAccessGrants.entrySet()) { + String accessType = e.getKey(); + Collection impliedGrants = e.getValue(); + + RangerPolicyItemAccess access = getAccess(policyItem, accessType); + + if(access == null) { + continue; + } + + for(String impliedGrant : impliedGrants) { + RangerPolicyItemAccess impliedAccess = getAccess(policyItem, impliedGrant); + + if(impliedAccess == null) { + impliedAccess = new RangerPolicyItemAccess(impliedGrant, access.getIsAllowed()); + + policyItem.getAccesses().add(impliedAccess); + } else { + if(! impliedAccess.getIsAllowed()) { + impliedAccess.setIsAllowed(access.getIsAllowed()); + } + } + } + } + } + } + + protected Map> getImpliedAccessGrants(RangerServiceDef serviceDef) { + Map> ret = null; + + if(serviceDef != null && !CollectionUtils.isEmpty(serviceDef.getAccessTypes())) { + for(RangerAccessTypeDef accessTypeDef : serviceDef.getAccessTypes()) { + if(!CollectionUtils.isEmpty(accessTypeDef.getImpliedGrants())) { + if(ret == null) { + ret = new HashMap<>(); + } + + Collection impliedAccessGrants = ret.get(accessTypeDef.getName()); + + if(impliedAccessGrants == null) { + impliedAccessGrants = new HashSet<>(); + + ret.put(accessTypeDef.getName(), impliedAccessGrants); + } + + impliedAccessGrants.addAll(accessTypeDef.getImpliedGrants()); + } + } + } + + return ret; + } + + private RangerPolicyItemAccess getAccess(RangerPolicyItem policyItem, String accessType) { + RangerPolicyItemAccess ret = null; + + if(policyItem != null && CollectionUtils.isNotEmpty(policyItem.getAccesses())) { + for(RangerPolicyItemAccess itemAccess : policyItem.getAccesses()) { + if(StringUtils.equalsIgnoreCase(itemAccess.getType(), accessType)) { + ret = itemAccess; + + break; + } + } + } + + return ret; + } + + private List createValidityScheduleEvaluators(RangerPolicy policy) { + List ret = null; + + if (CollectionUtils.isNotEmpty(policy.getValiditySchedules())) { + ret = new ArrayList<>(); + + for (RangerValiditySchedule schedule : policy.getValiditySchedules()) { + ret.add(new RangerValidityScheduleEvaluator(schedule)); + } + } else { + ret = Collections.emptyList(); + } + + return ret; + } + + private List createPolicyItemEvaluators(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options, int policyItemType) { + List ret = null; + List policyItems = null; + + if(isPolicyItemTypeEnabled(serviceDef, policyItemType)) { + if (policyItemType == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW) { + policyItems = policy.getPolicyItems(); + } else if (policyItemType == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY) { + policyItems = policy.getDenyPolicyItems(); + } else if (policyItemType == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS) { + policyItems = policy.getAllowExceptions(); + } else if (policyItemType == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS) { + policyItems = policy.getDenyExceptions(); + } + } + + if(CollectionUtils.isNotEmpty(policyItems)) { + ret = new ArrayList<>(); + + int policyItemCounter = 1; + + for(RangerPolicyItem policyItem : policyItems) { + RangerPolicyItemEvaluator itemEvaluator = new RangerDefaultPolicyItemEvaluator(serviceDef, policy, policyItem, policyItemType, policyItemCounter++, options); + + itemEvaluator.init(); + + ret.add(itemEvaluator); + + if(CollectionUtils.isNotEmpty(itemEvaluator.getConditionEvaluators())) { + customConditionsCount += itemEvaluator.getConditionEvaluators().size(); + } + } + } else { + ret = Collections.emptyList(); + } + + return ret; + } + + private List createDataMaskPolicyItemEvaluators(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options, List policyItems) { + List ret = null; + + if(CollectionUtils.isNotEmpty(policyItems)) { + ret = new ArrayList<>(); + + int policyItemCounter = 1; + + for(RangerDataMaskPolicyItem policyItem : policyItems) { + RangerDataMaskPolicyItemEvaluator itemEvaluator = new RangerDefaultDataMaskPolicyItemEvaluator(serviceDef, policy, policyItem, policyItemCounter++, options); + + itemEvaluator.init(); + + ret.add(itemEvaluator); + + if(CollectionUtils.isNotEmpty(itemEvaluator.getConditionEvaluators())) { + customConditionsCount += itemEvaluator.getConditionEvaluators().size(); + } + } + } else { + ret = Collections.emptyList(); + } + + return ret; + } + + private List createRowFilterPolicyItemEvaluators(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options, List policyItems) { + List ret = null; + + if(CollectionUtils.isNotEmpty(policyItems)) { + ret = new ArrayList<>(); + + int policyItemCounter = 1; + + for(RangerRowFilterPolicyItem policyItem : policyItems) { + RangerRowFilterPolicyItemEvaluator itemEvaluator = new RangerDefaultRowFilterPolicyItemEvaluator(serviceDef, policy, policyItem, policyItemCounter++, options); + + itemEvaluator.init(); + + ret.add(itemEvaluator); + + if(CollectionUtils.isNotEmpty(itemEvaluator.getConditionEvaluators())) { + customConditionsCount += itemEvaluator.getConditionEvaluators().size(); + } + } + } else { + ret = Collections.emptyList(); + } + + return ret; + } + + private boolean isPolicyItemTypeEnabled(RangerServiceDef serviceDef, int policyItemType) { + boolean ret = true; + + if(policyItemType == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY || + policyItemType == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS || + policyItemType == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS) { + ret = ServiceDefUtil.getOption_enableDenyAndExceptionsInPolicies(serviceDef, pluginContext); + } + + return ret; + } + + private static boolean hasNonPublicGroupOrConditions(List policyItems) { + boolean ret = false; + for (RangerPolicyItem policyItem : policyItems) { + if (CollectionUtils.isNotEmpty(policyItem.getConditions())) { + ret = true; + break; + } + List allGroups = policyItem.getGroups(); + if (CollectionUtils.isNotEmpty(allGroups) && !allGroups.contains(RangerPolicyEngine.GROUP_PUBLIC)) { + ret = true; + break; + } + } + return ret; + } + + protected RangerPolicyItemEvaluator getMatchingPolicyItem(RangerAccessRequest request, RangerAccessResult result) { + RangerPolicyItemEvaluator ret = null; + + String policyType = getPolicy().getPolicyType(); + if (StringUtils.isEmpty(policyType)) { + policyType = RangerPolicy.POLICY_TYPE_ACCESS; + } + + switch (policyType) { + case RangerPolicy.POLICY_TYPE_ACCESS: { + ret = getMatchingPolicyItemForAccessPolicyForSpecificAccess(request, result); + break; + } + case RangerPolicy.POLICY_TYPE_DATAMASK: { + ret = getMatchingPolicyItem(request, result, dataMaskEvaluators); + break; + } + case RangerPolicy.POLICY_TYPE_ROWFILTER: { + ret = getMatchingPolicyItem(request, result, rowFilterEvaluators); + break; + } + default: + break; + } + + return ret; + } + + protected RangerPolicyItemEvaluator getMatchingPolicyItemForAccessPolicyForSpecificAccess(RangerAccessRequest request, RangerAccessResult result) { + RangerPolicyItemEvaluator ret = getMatchingPolicyItem(request, result, denyEvaluators, denyExceptionEvaluators); + + if(request.isAccessorsRequested() || (ret == null && !result.getIsAccessDetermined())) { // a deny policy could have set isAllowed=true, but in such case it wouldn't set isAccessDetermined=true + ret = getMatchingPolicyItem(request, result, allowEvaluators, allowExceptionEvaluators); + } + + return ret; + } + + protected T getMatchingPolicyItem(RangerAccessRequest request, RangerAccessResult result, + List evaluators) { + T ret = getMatchingPolicyItem(request, result, evaluators, null); + + return ret; + } + + private T getMatchingPolicyItem(RangerAccessRequest request, RangerAccessResult result, + List evaluators, List exceptionEvaluators) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + request + ")"); + } + + T ret = null; + + if(CollectionUtils.isNotEmpty(evaluators)) { + for (T evaluator : evaluators) { + if(evaluator.isMatch(request)) { + ret = evaluator; + + if (!request.isAccessorsRequested()) { + break; + } + result.addMatchedItemEvaluator(evaluator); + } + } + } + + if(ret != null && CollectionUtils.isNotEmpty(exceptionEvaluators)) { + for (T exceptionEvaluator : exceptionEvaluators) { + if(exceptionEvaluator.isMatch(request)) { + if(LOG.isDebugEnabled()) { + LOG.debug("RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + request + "): found exception policyItem(" + exceptionEvaluator.getPolicyItem() + "); ignoring the matchedPolicyItem(" + ret.getPolicyItem() + ")"); + } + + ret = null; + + break; + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + request + "): " + ret); + } + + return ret; + } + + private T getMatchingPolicyItem(String user, Set userGroups, Set roles, String owner, String accessType, List evaluators, List exceptionEvaluators) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + user + ", " + userGroups + ", " + roles + ", " + owner + ", " + accessType + ")"); + } + + T ret = null; + + if(CollectionUtils.isNotEmpty(evaluators)) { + for (T evaluator : evaluators) { + if(evaluator.matchUserGroupAndOwner(user, userGroups, roles, owner) && evaluator.matchAccessType(accessType)) { + ret = evaluator; + + break; + } + } + } + + if(ret != null && CollectionUtils.isNotEmpty(exceptionEvaluators)) { + for (T exceptionEvaluator : exceptionEvaluators) { + if(exceptionEvaluator.matchUserGroupAndOwner(user, userGroups, roles, owner) && exceptionEvaluator.matchAccessType(accessType)) { + if(LOG.isDebugEnabled()) { + LOG.debug("RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + user + ", " + userGroups + ", " + accessType + "): found exception policyItem(" + exceptionEvaluator.getPolicyItem() + "); ignoring the matchedPolicyItem(" + ret.getPolicyItem() + ")"); + } + + ret = null; + + break; + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.getMatchingPolicyItem(" + user + ", " + userGroups + ", " + roles + ", " + owner + ", " + accessType + "): " + ret); + } + return ret; + } + + // Policy Level Condition evaluator + private boolean matchPolicyCustomConditions(RangerAccessRequest request) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyEvaluator.matchPolicyCustomConditions(" + request + ")"); + } + + boolean ret = true; + + if (CollectionUtils.isNotEmpty(conditionEvaluators)) { + if(LOG.isDebugEnabled()) { + LOG.debug("RangerDefaultPolicyEvaluator.matchPolicyCustomConditions(): conditionCount=" + conditionEvaluators.size()); + } + for(RangerConditionEvaluator conditionEvaluator : conditionEvaluators) { + if(LOG.isDebugEnabled()) { + LOG.debug("evaluating condition: " + conditionEvaluator); + } + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYCONDITION_REQUEST_LOG)) { + + String conditionType = null; + if (conditionEvaluator instanceof RangerAbstractConditionEvaluator) { + conditionType = ((RangerAbstractConditionEvaluator)conditionEvaluator).getPolicyItemCondition().getType(); + } + + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYCONDITION_REQUEST_LOG, "RangerConditionEvaluator.matchPolicyCustomConditions(policyId=" + getGuid() + ",policyConditionType=" + conditionType + ")"); + } + + boolean conditionEvalResult = conditionEvaluator.isMatched(request); + + RangerPerfTracer.log(perf); + + if (!conditionEvalResult) { + if(LOG.isDebugEnabled()) { + LOG.debug(conditionEvaluator + " returned false"); + } + ret = false; + break; + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyEvaluator.matchCustomConditions(" + request + "): " + ret); + } + + return ret; + } + + private List createRangerPolicyConditionEvaluator(RangerPolicy policy, + RangerServiceDef serviceDef, + RangerPolicyEngineOptions options) { + List rangerConditionEvaluators = null; + + RangerCustomConditionEvaluator rangerConditionEvaluator = new RangerCustomConditionEvaluator(); + + rangerConditionEvaluators = rangerConditionEvaluator.getRangerPolicyConditionEvaluator(policy,serviceDef,options); + + if (rangerConditionEvaluators != null) { + customConditionsCount += rangerConditionEvaluators.size(); + } + + return rangerConditionEvaluators; + } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java new file mode 100644 index 00000000000..d2e14ad2764 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDefaultPolicyItemEvaluator.java @@ -0,0 +1,335 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.conditionevaluator.RangerAbstractConditionEvaluator; +import org.apache.atlas.plugin.conditionevaluator.RangerConditionEvaluator; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItem; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemAccess; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerPolicyConditionDef; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.atlas.plugin.policyengine.RangerAccessResource; +import org.apache.atlas.plugin.policyengine.RangerAccessResult; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngine; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngineOptions; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; +import org.apache.atlas.plugin.util.RangerAccessRequestUtil; +import org.apache.atlas.plugin.util.RangerPerfTracer; + +import java.util.Collections; +import java.util.List; +import java.util.Set; + + +public class RangerDefaultPolicyItemEvaluator extends RangerAbstractPolicyItemEvaluator { + private static final Log LOG = LogFactory.getLog(RangerDefaultPolicyItemEvaluator.class); + + private static final Log PERF_POLICYITEM_REQUEST_LOG = RangerPerfTracer.getPerfLogger("policyitem.request"); + private static final Log PERF_POLICYCONDITION_REQUEST_LOG = RangerPerfTracer.getPerfLogger("policycondition.request"); + + private boolean hasCurrentUser; + private boolean hasResourceOwner; + + public RangerDefaultPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerPolicyItem policyItem, int policyItemType, int policyItemIndex, RangerPolicyEngineOptions options) { + super(serviceDef, policy, policyItem, policyItemType, policyItemIndex, options); + } + + public void init() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator(policyId=" + policyId + ", policyItem=" + policyItem + ", serviceType=" + getServiceType() + ", conditionsDisabled=" + getConditionsDisabledOption() + ")"); + } + + RangerCustomConditionEvaluator rangerCustomConditionEvaluator = new RangerCustomConditionEvaluator(); + + conditionEvaluators = rangerCustomConditionEvaluator.getPolicyItemConditionEvaluator(policy,policyItem,serviceDef,options,policyItemIndex); + + List users = policyItem.getUsers(); + this.hasCurrentUser = CollectionUtils.isNotEmpty(users) && users.contains(RangerPolicyEngine.USER_CURRENT); + this.hasResourceOwner = CollectionUtils.isNotEmpty(users) && users.contains(RangerPolicyEngine.RESOURCE_OWNER); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator(policyId=" + policyId + ", conditionsCount=" + getConditionEvaluators().size() + ")"); + } + } + + @Override + public boolean isMatch(RangerAccessRequest request) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator.isMatch(" + request + ")"); + } + + boolean ret = false; + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYITEM_REQUEST_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYITEM_REQUEST_LOG, "RangerPolicyItemEvaluator.isMatch(resource=" + request.getResource().getAsString() + ")"); + } + + if(policyItem != null) { + if(matchUserGroupAndOwner(request)) { + if (request.isAccessTypeDelegatedAdmin()) { // used only in grant/revoke scenario + if (policyItem.getDelegateAdmin()) { + ret = true; + } + } else if (CollectionUtils.isNotEmpty(policyItem.getAccesses())) { + boolean isAccessTypeMatched = false; + + for (RangerPolicy.RangerPolicyItemAccess access : policyItem.getAccesses()) { + if (access.getIsAllowed() && StringUtils.equalsIgnoreCase(access.getType(), request.getAccessType())) { + isAccessTypeMatched = true; + break; + } + } + + if(isAccessTypeMatched) { + if(matchCustomConditions(request)) { + ret = true; + } + } + } + } + } + + RangerPerfTracer.log(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator.isMatch(" + request + "): " + ret); + } + + return ret; + } + + @Override + public boolean matchUserGroupAndOwner(String user, Set userGroups, Set roles, String owner) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchUserGroup(" + policyItem + ", " + user + ", " + userGroups + ", " + roles + ", " + owner + ")"); + } + + boolean ret = false; + + if(policyItem != null) { + if(!ret && user != null && policyItem.getUsers() != null) { + ret = hasCurrentUser || policyItem.getUsers().contains(user); + } + if(!ret && userGroups != null && policyItem.getGroups() != null) { + ret = policyItem.getGroups().contains(RangerPolicyEngine.GROUP_PUBLIC) || + !Collections.disjoint(policyItem.getGroups(), userGroups); + } + if (!ret && CollectionUtils.isNotEmpty(roles) && CollectionUtils.isNotEmpty(policyItem.getRoles())) { + ret = !Collections.disjoint(policyItem.getRoles(), roles); + } + if (!ret && hasResourceOwner) { + ret = user != null && user.equals(owner); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchUserGroup(" + policyItem + ", " + user + ", " + userGroups + ", " + roles + ", " + owner + "): " + ret); + } + + return ret; + } + + private boolean matchUserGroupAndOwner(RangerAccessRequest request) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchUserGroupAndOwner(" + request + ")"); + } + + if (request.isAccessorsRequested()) { + //skip checking user/group/owner if policy item in case get accessors request + return true; + } + + boolean ret = false; + + String user = request.getUser(); + Set userGroups = request.getUserGroups(); + + RangerAccessResource accessedResource = request.getResource(); + String resourceOwner = accessedResource != null ? accessedResource.getOwnerUser() : null; + + if (!ret) { + Set roles = null; + if (CollectionUtils.isNotEmpty(policyItem.getRoles())) { + roles = RangerAccessRequestUtil.getCurrentUserRolesFromContext(request.getContext()); + } + ret = matchUserGroupAndOwner(user, userGroups, roles, resourceOwner); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchUserGroupAndOwner(" + request + "): " + ret); + } + + return ret; + } + @Override + public boolean matchAccessType(String accessType) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchAccessType(" + accessType + ")"); + } + + boolean ret = false; + + if(policyItem != null) { + boolean isAdminAccess = StringUtils.equals(accessType, RangerPolicyEngine.ADMIN_ACCESS); + + if(isAdminAccess) { + ret = policyItem.getDelegateAdmin(); + } else { + if(CollectionUtils.isNotEmpty(policyItem.getAccesses())) { + boolean isAnyAccess = StringUtils.equals(accessType, RangerPolicyEngine.ANY_ACCESS); + + for(RangerPolicyItemAccess itemAccess : policyItem.getAccesses()) { + if(! itemAccess.getIsAllowed()) { + continue; + } + + if(isAnyAccess) { + ret = true; + + break; + } else if(StringUtils.equalsIgnoreCase(itemAccess.getType(), accessType)) { + ret = true; + + break; + } + } + } else if (StringUtils.isEmpty(accessType)) { + ret = true; + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchAccessType(" + accessType + "): " + ret); + } + + return ret; + } + + @Override + public boolean matchCustomConditions(RangerAccessRequest request) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator.matchCustomConditions(" + request + ")"); + } + + boolean ret = true; + + if (CollectionUtils.isNotEmpty(conditionEvaluators)) { + if(LOG.isDebugEnabled()) { + LOG.debug("RangerDefaultPolicyItemEvaluator.matchCustomConditions(): conditionCount=" + conditionEvaluators.size()); + } + for(RangerConditionEvaluator conditionEvaluator : conditionEvaluators) { + if(LOG.isDebugEnabled()) { + LOG.debug("evaluating condition: " + conditionEvaluator); + } + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYCONDITION_REQUEST_LOG)) { + + String conditionType = null; + if (conditionEvaluator instanceof RangerAbstractConditionEvaluator) { + conditionType = ((RangerAbstractConditionEvaluator)conditionEvaluator).getPolicyItemCondition().getType(); + } + + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYCONDITION_REQUEST_LOG, "RangerConditionEvaluator.matchCondition(policyId=" + policyId + ",policyItemIndex=" + getPolicyItemIndex() + ",policyConditionType=" + conditionType + ")"); + } + + boolean conditionEvalResult = conditionEvaluator.isMatched(request); + + RangerPerfTracer.log(perf); + + if (!conditionEvalResult) { + if(LOG.isDebugEnabled()) { + LOG.debug(conditionEvaluator + " returned false"); + } + + ret = false; + + break; + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator.matchCustomConditions(" + request + "): " + ret); + } + + return ret; + } + + @Override + public void updateAccessResult(RangerPolicyEvaluator policyEvaluator, RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType) { + policyEvaluator.updateAccessResult(result, matchType, getPolicyItemType() != POLICY_ITEM_TYPE_DENY, getComments()); + } + + RangerPolicyConditionDef getConditionDef(String conditionName) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator.getConditionDef(" + conditionName + ")"); + } + + RangerPolicyConditionDef ret = null; + + if (serviceDef != null && CollectionUtils.isNotEmpty(serviceDef.getPolicyConditions())) { + for(RangerPolicyConditionDef conditionDef : serviceDef.getPolicyConditions()) { + if(StringUtils.equals(conditionName, conditionDef.getName())) { + ret = conditionDef; + + break; + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator.getConditionDef(" + conditionName + "): " + ret); + } + + return ret; + } + + RangerConditionEvaluator newConditionEvaluator(String className) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyItemEvaluator.newConditionEvaluator(" + className + ")"); + } + + RangerConditionEvaluator evaluator = null; + + try { + @SuppressWarnings("unchecked") + Class matcherClass = (Class)Class.forName(className); + + evaluator = matcherClass.newInstance(); + } catch(Throwable t) { + LOG.error("RangerDefaultPolicyItemEvaluator.newConditionEvaluator(" + className + "): error instantiating evaluator", t); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyItemEvaluator.newConditionEvaluator(" + className + "): " + evaluator); + } + + return evaluator; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDefaultRowFilterPolicyItemEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDefaultRowFilterPolicyItemEvaluator.java new file mode 100644 index 00000000000..72c26df9d4b --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerDefaultRowFilterPolicyItemEvaluator.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemRowFilterInfo; +import org.apache.atlas.plugin.model.RangerPolicy.RangerRowFilterPolicyItem; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.policyengine.RangerAccessResult; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngineOptions; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; + + +public class RangerDefaultRowFilterPolicyItemEvaluator extends RangerDefaultPolicyItemEvaluator implements RangerRowFilterPolicyItemEvaluator { + final private RangerRowFilterPolicyItem rowFilterPolicyItem; + + public RangerDefaultRowFilterPolicyItemEvaluator(RangerServiceDef serviceDef, RangerPolicy policy, RangerRowFilterPolicyItem policyItem, int policyItemIndex, RangerPolicyEngineOptions options) { + super(serviceDef, policy, policyItem, POLICY_ITEM_TYPE_DATAMASK, policyItemIndex, options); + + rowFilterPolicyItem = policyItem; + } + + @Override + public RangerPolicyItemRowFilterInfo getRowFilterInfo() { + return rowFilterPolicyItem == null ? null : rowFilterPolicyItem.getRowFilterInfo(); + } + + @Override + public void updateAccessResult(RangerPolicyEvaluator policyEvaluator, RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType) { + RangerPolicyItemRowFilterInfo rowFilterInfo = getRowFilterInfo(); + + if (result.getFilterExpr() == null && rowFilterInfo != null) { + result.setFilterExpr(rowFilterInfo.getFilterExpr()); + policyEvaluator.updateAccessResult(result, matchType, true, getComments()); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java new file mode 100644 index 00000000000..3b0f4c686de --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerOptimizedPolicyEvaluator.java @@ -0,0 +1,368 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.atlas.plugin.policyengine.RangerAccessResource; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngine; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngineOptions; +import org.apache.atlas.plugin.util.RangerAccessRequestUtil; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +public class RangerOptimizedPolicyEvaluator extends RangerDefaultPolicyEvaluator { + private static final Log LOG = LogFactory.getLog(RangerOptimizedPolicyEvaluator.class); + + private Set roles = new HashSet<>(); + private Set groups = new HashSet<>(); + private Set users = new HashSet<>(); + private Set accessPerms = new HashSet<>(); + private boolean delegateAdmin; + private boolean hasAllPerms; + private boolean hasPublicGroup; + private boolean hasCurrentUser; + private boolean hasResourceOwner; + + // For computation of priority + private static final String RANGER_POLICY_EVAL_MATCH_ANY_PATTERN_STRING = "*"; + private static final String RANGER_POLICY_EVAL_MATCH_ONE_CHARACTER_STRING = "?"; + + private static final int RANGER_POLICY_EVAL_SCORE_DEFAULT = 10000; + + private static final int RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_RESOURCE = 100; + private static final int RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_USERSGROUPS = 25; + private static final int RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_ACCESS_TYPES = 25; + private static final int RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_CUSTOM_CONDITIONS = 25; + + private static final int RANGER_POLICY_EVAL_SCORE_RESOURCE_DISCOUNT_MATCH_ANY_WILDCARD = 25; + private static final int RANGER_POLICY_EVAL_SCORE_RESOURCE_DISCOUNT_HAS_MATCH_ANY_WILDCARD = 10; + private static final int RANGER_POLICY_EVAL_SCORE_RESOURCE_DISCOUNT_HAS_MATCH_ONE_CHARACTER_WILDCARD = 5; + private static final int RANGER_POLICY_EVAL_SCORE_RESOURCE_DISCOUNT_IS_EXCLUDES = 5; + private static final int RANGER_POLICY_EVAL_SCORE_RESORUCE_DISCOUNT_IS_RECURSIVE = 5; + private static final int RANGER_POLICY_EVAL_SCORE_CUSTOM_CONDITION_PENALTY = 5; + private static final int RANGER_POLICY_EVAL_SCORE_DYNAMIC_RESOURCE_EVAL_PENALTY = 20; + + @Override + public void init(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerOptimizedPolicyEvaluator.init()"); + } + + super.init(policy, serviceDef, options); + + preprocessPolicyItems(policy.getPolicyItems()); + preprocessPolicyItems(policy.getDenyPolicyItems()); + preprocessPolicyItems(policy.getAllowExceptions()); + preprocessPolicyItems(policy.getDenyExceptions()); + preprocessPolicyItems(policy.getDataMaskPolicyItems()); + preprocessPolicyItems(policy.getRowFilterPolicyItems()); + + hasAllPerms = checkIfHasAllPerms(); + + for (String user : users) { + if (!hasCurrentUser && RangerPolicyEngine.USER_CURRENT.equalsIgnoreCase(user)) { + hasCurrentUser = true; + } + if (!hasResourceOwner && RangerPolicyEngine.RESOURCE_OWNER.equalsIgnoreCase(user)) { + hasResourceOwner = true; + } + if (hasCurrentUser && hasResourceOwner) { + break; + } + } + + if (policy.getIsDenyAllElse()) { + hasPublicGroup = true; + } else { + for (String group : groups) { + if (RangerPolicyEngine.GROUP_PUBLIC.equalsIgnoreCase(group)) { + hasPublicGroup = true; + break; + } + } + } + + setEvalOrder(computeEvalOrder()); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerOptimizedPolicyEvaluator.init()"); + } + } + + static class LevelResourceNames implements Comparable { + final int level; + final RangerPolicy.RangerPolicyResource policyResource; + + public LevelResourceNames(int level, RangerPolicy.RangerPolicyResource policyResource) { + this.level = level; + this.policyResource = policyResource; + } + + @Override + public int compareTo(LevelResourceNames other) { + // Sort in ascending order of level numbers + return Integer.compare(this.level, other.level); + } + + @Override + public boolean equals(Object other) { + boolean ret = false; + if (other != null && (other instanceof LevelResourceNames)) { + ret = this == other || compareTo((LevelResourceNames) other) == 0; + } + return ret; + } + + @Override + public int hashCode() { + return Objects.hashCode(this.level); + } + } + + public int computeEvalOrder() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerOptimizedPolicyEvaluator.computeEvalOrder()"); + } + + int evalOrder = RANGER_POLICY_EVAL_SCORE_DEFAULT; + + RangerServiceDef serviceDef = getServiceDef(); + List resourceDefs = serviceDef.getResources(); + RangerPolicy policy = getPolicy(); + List tmpList = new ArrayList<>(); + + for (Map.Entry kv : policy.getResources().entrySet()) { + String resourceName = kv.getKey(); + RangerPolicy.RangerPolicyResource policyResource = kv.getValue(); + List resourceValues = policyResource.getValues(); + + if(CollectionUtils.isNotEmpty(resourceValues)) { + for (RangerServiceDef.RangerResourceDef resourceDef : resourceDefs) { + if (resourceName.equals(resourceDef.getName())) { + tmpList.add(new LevelResourceNames(resourceDef.getLevel(), policyResource)); + break; + } + } + } + } + Collections.sort(tmpList); // Sort in ascending order of levels + + int resourceDiscount = 0; + for (LevelResourceNames item : tmpList) { + // Expect lowest level first + boolean foundStarWildcard = false; + boolean foundQuestionWildcard = false; + boolean foundMatchAny = false; + + for (String resourceName : item.policyResource.getValues()) { + if (resourceName.isEmpty() || RANGER_POLICY_EVAL_MATCH_ANY_PATTERN_STRING.equals(resourceName)) { + foundMatchAny = true; + break; + } else if (resourceName.contains(RANGER_POLICY_EVAL_MATCH_ANY_PATTERN_STRING)) { + foundStarWildcard = true; + } else if (resourceName.contains(RANGER_POLICY_EVAL_MATCH_ONE_CHARACTER_STRING)) { + foundQuestionWildcard = true; + } + } + if (foundMatchAny) { + resourceDiscount += RANGER_POLICY_EVAL_SCORE_RESOURCE_DISCOUNT_MATCH_ANY_WILDCARD; + } else { + if (foundStarWildcard) { + resourceDiscount += RANGER_POLICY_EVAL_SCORE_RESOURCE_DISCOUNT_HAS_MATCH_ANY_WILDCARD; + } else if (foundQuestionWildcard) { + resourceDiscount += RANGER_POLICY_EVAL_SCORE_RESOURCE_DISCOUNT_HAS_MATCH_ONE_CHARACTER_WILDCARD; + } + + RangerPolicy.RangerPolicyResource resource = item.policyResource; + + if (resource.getIsExcludes()) { + resourceDiscount += RANGER_POLICY_EVAL_SCORE_RESOURCE_DISCOUNT_IS_EXCLUDES; + } + + if (resource.getIsRecursive()) { + resourceDiscount += RANGER_POLICY_EVAL_SCORE_RESORUCE_DISCOUNT_IS_RECURSIVE; + } + } + } + if (needsDynamicEval()) { + evalOrder += RANGER_POLICY_EVAL_SCORE_DYNAMIC_RESOURCE_EVAL_PENALTY; + } + + evalOrder -= Math.min(RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_RESOURCE, resourceDiscount); + + if (hasPublicGroup || hasCurrentUser) { + evalOrder -= RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_USERSGROUPS; + } else { + evalOrder -= Math.min(groups.size() + users.size(), RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_USERSGROUPS); + } + + evalOrder -= Math.round(((float)RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_ACCESS_TYPES * accessPerms.size()) / serviceDef.getAccessTypes().size()); + + int customConditionsDiscount = RANGER_POLICY_EVAL_SCORE_MAX_DISCOUNT_CUSTOM_CONDITIONS - (RANGER_POLICY_EVAL_SCORE_CUSTOM_CONDITION_PENALTY * this.getCustomConditionsCount()); + if(customConditionsDiscount > 0) { + evalOrder -= customConditionsDiscount; + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerOptimizedPolicyEvaluator.computeEvalOrder(), policyName:" + policy.getName() + ", priority:" + evalOrder); + } + + return evalOrder; + } + + @Override + protected boolean isAccessAllowed(String user, Set userGroups, Set roles, String owner, String accessType) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerOptimizedPolicyEvaluator.isAccessAllowed(" + user + ", " + userGroups + ", " + roles + ", " + owner + ", " + accessType + ")"); + } + + boolean ret = hasMatchablePolicyItem(user, userGroups, roles, owner, accessType) && super.isAccessAllowed(user, userGroups, roles, owner, accessType); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerOptimizedPolicyEvaluator.isAccessAllowed(" + user + ", " + userGroups + ", " + roles + ", " + owner + ", " + accessType + "): " + ret); + } + + return ret; + } + + @Override + protected boolean hasMatchablePolicyItem(RangerAccessRequest request) { + boolean ret = false; + + if (request.isAccessorsRequested() || hasPublicGroup || hasCurrentUser || isOwnerMatch(request) || users.contains(request.getUser()) || CollectionUtils.containsAny(groups, request.getUserGroups()) || (CollectionUtils.isNotEmpty(roles) && CollectionUtils.containsAny(roles, RangerAccessRequestUtil.getCurrentUserRolesFromContext(request.getContext())))) { + if (hasAllPerms || request.isAccessTypeAny()) { + ret = true; + } else { + ret = accessPerms.contains(request.getAccessType()); + if (!ret) { + if (request.isAccessTypeDelegatedAdmin()) { + ret = delegateAdmin; + } + } + } + } + + return ret; + } + + private boolean isOwnerMatch(RangerAccessRequest request) { + boolean ret = false; + + if (hasResourceOwner) { + RangerAccessResource accessedResource = request.getResource(); + String resourceOwner = accessedResource != null ? accessedResource.getOwnerUser() : null; + String user = request.getUser(); + + if (user != null && resourceOwner != null && user.equals(resourceOwner)) { + ret = true; + } + } + + return ret; + } + + private boolean hasMatchablePolicyItem(String user, Set userGroups, Set rolesFromContext, String owner, String accessType) { + boolean ret = false; + + boolean hasRole = false; + if (CollectionUtils.isNotEmpty(roles)) { + if (CollectionUtils.isNotEmpty(rolesFromContext)) { + hasRole = CollectionUtils.containsAny(roles, rolesFromContext); + } + } + + if (hasPublicGroup || hasCurrentUser || users.contains(user) || CollectionUtils.containsAny(groups, userGroups) || hasRole || (hasResourceOwner && StringUtils.equals(user, owner))) { + if (hasAllPerms) { + ret = true; + } else { + boolean isAccessTypeAny = StringUtils.isEmpty(accessType) || StringUtils.equals(accessType, RangerPolicyEngine.ANY_ACCESS); + ret = isAccessTypeAny || accessPerms.contains(accessType); + + if (!ret) { + if (StringUtils.equals(accessType, RangerPolicyEngine.ADMIN_ACCESS)) { + ret = delegateAdmin; + } + } + } + } + + return ret; + } + + private void preprocessPolicyItems(List policyItems) { + if(CollectionUtils.isNotEmpty(policyItems)) { + for (RangerPolicy.RangerPolicyItem item : policyItems) { + delegateAdmin = delegateAdmin || item.getDelegateAdmin(); + + List policyItemAccesses = item.getAccesses(); + for(RangerPolicy.RangerPolicyItemAccess policyItemAccess : policyItemAccesses) { + + if (policyItemAccess.getIsAllowed()) { + String accessType = policyItemAccess.getType(); + accessPerms.add(accessType); + } + } + + roles.addAll(item.getRoles()); + groups.addAll(item.getGroups()); + users.addAll(item.getUsers()); + + } + } + } + + private boolean checkIfHasAllPerms() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerOptimizedPolicyEvaluator.checkIfHasAllPerms()"); + } + boolean result = true; + + if (getPolicy().getIsDenyAllElse()) { + hasAllPerms = true; + } else { + List serviceAccessTypes = getServiceDef().getAccessTypes(); + for (RangerServiceDef.RangerAccessTypeDef serviceAccessType : serviceAccessTypes) { + if (!accessPerms.contains(serviceAccessType.getName())) { + result = false; + break; + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerOptimizedPolicyEvaluator.checkIfHasAllPerms(), " + result); + } + + return result; + } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerPolicyEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerPolicyEvaluator.java new file mode 100644 index 00000000000..7c738fa40a3 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerPolicyEvaluator.java @@ -0,0 +1,618 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicy.RangerDataMaskPolicyItem; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItem; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemAccess; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyResource; +import org.apache.atlas.plugin.model.RangerPolicy.RangerRowFilterPolicyItem; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.atlas.plugin.policyengine.RangerAccessResource; +import org.apache.atlas.plugin.policyengine.RangerAccessResult; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngine; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngineOptions; +import org.apache.atlas.plugin.policyengine.RangerResourceACLs.DataMaskResult; +import org.apache.atlas.plugin.policyengine.RangerResourceACLs.RowFilterResult; +import org.apache.atlas.plugin.policyengine.RangerResourceAccessInfo; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceEvaluator; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.apache.atlas.plugin.policyevaluator.RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW; +import static org.apache.atlas.plugin.policyevaluator.RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS; +import static org.apache.atlas.plugin.policyevaluator.RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY; +import static org.apache.atlas.plugin.policyevaluator.RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY_EXCEPTIONS; + +public interface RangerPolicyEvaluator extends RangerPolicyResourceEvaluator { + Comparator EVAL_ORDER_COMPARATOR = new PolicyEvalOrderComparator(); + Comparator NAME_COMPARATOR = new PolicyNameComparator(); + + // computation of PolicyACLSummary rely on following specific values + Integer ACCESS_DENIED = -1; + Integer ACCESS_UNDETERMINED = 0; + Integer ACCESS_ALLOWED = 1; + Integer ACCESS_CONDITIONAL = 2; + + String EVALUATOR_TYPE_AUTO = "auto"; + String EVALUATOR_TYPE_OPTIMIZED = "optimized"; + String EVALUATOR_TYPE_CACHED = "cached"; + + void init(RangerPolicy policy, RangerServiceDef serviceDef, RangerPolicyEngineOptions options); + + RangerPolicy getPolicy(); + + RangerServiceDef getServiceDef(); + + boolean hasAllow(); + + boolean hasDeny(); + + int getPolicyPriority(); + + boolean isApplicable(Date accessTime); + + int getEvalOrder(); + + int getCustomConditionsCount(); + + int getValidityScheduleEvaluatorsCount(); + + boolean isAuditEnabled(); + + void evaluate(RangerAccessRequest request, RangerAccessResult result); + + boolean isMatch(RangerAccessResource resource, Map evalContext); + + boolean isCompleteMatch(RangerAccessResource resource, Map evalContext); + + boolean isCompleteMatch(Map resources, Map evalContext); + + boolean isAccessAllowed(Map resources, String user, Set userGroups, String accessType); + + void updateAccessResult(RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType, boolean isAllowed, String reason); + + void getResourceAccessInfo(RangerAccessRequest request, RangerResourceAccessInfo result); + + Set getAllowedAccesses(RangerAccessResource resource, String user, Set userGroups, Set roles, Set accessTypes); + + Set getAllowedAccesses(Map resources, String user, Set userGroups, Set roles, Set accessTypes, Map evalContext); + + PolicyACLSummary getPolicyACLSummary(); + + default boolean hasContextSensitiveSpecification() { + RangerPolicy policy = getPolicy(); + + for (RangerPolicyItem policyItem : policy.getPolicyItems()) { + if (hasContextSensitiveSpecification(policyItem)) { + return true; + } + } + for (RangerPolicyItem policyItem : policy.getDenyPolicyItems()) { + if (hasContextSensitiveSpecification(policyItem)) { + return true; + } + } + for (RangerPolicyItem policyItem : policy.getAllowExceptions()) { + if (hasContextSensitiveSpecification(policyItem)) { + return true; + } + } + for (RangerPolicyItem policyItem : policy.getDenyExceptions()) { + if (hasContextSensitiveSpecification(policyItem)) { + return true; + } + } + return false; + } + + default boolean hasRoles(final RangerPolicy policy) { + for (RangerPolicyItem policyItem : policy.getPolicyItems()) { + if (hasRoles(policyItem)) { + return true; + } + } + for (RangerPolicyItem policyItem : policy.getDenyPolicyItems()) { + if (hasRoles(policyItem)) { + return true; + } + } + for (RangerPolicyItem policyItem : policy.getAllowExceptions()) { + if (hasRoles(policyItem)) { + return true; + } + } + for (RangerPolicyItem policyItem : policy.getDenyExceptions()) { + if (hasRoles(policyItem)) { + return true; + } + } + for (RangerDataMaskPolicyItem policyItem : policy.getDataMaskPolicyItems()) { + if (hasRoles(policyItem)) { + return true; + } + } + for (RangerRowFilterPolicyItem policyItem : policy.getRowFilterPolicyItems()) { + if (hasRoles(policyItem)) { + return true; + } + } + return false; + } + + static boolean hasContextSensitiveSpecification(RangerPolicyItem policyItem) { + return CollectionUtils.isNotEmpty(policyItem.getConditions()) || policyItem.getUsers().contains(RangerPolicyEngine.RESOURCE_OWNER); /* || policyItem.getGroups().contains(RangerPolicyEngine.RESOURCE_GROUP_OWNER) */ + } + + static boolean hasRoles(RangerPolicyItem policyItem) { + return CollectionUtils.isNotEmpty(policyItem.getRoles()); + } + + class PolicyEvalOrderComparator implements Comparator, Serializable { + @Override + public int compare(RangerPolicyEvaluator me, RangerPolicyEvaluator other) { + int result = Integer.compare(other.getPolicyPriority(), me.getPolicyPriority()); + + return result == 0 ? compareNormal(me, other) : result; + } + + private int compareNormal(RangerPolicyEvaluator me, RangerPolicyEvaluator other) { + final int result; + + if (me.hasDeny() && !other.hasDeny()) { + result = -1; + } else if (!me.hasDeny() && other.hasDeny()) { + result = 1; + } else { + result = Integer.compare(me.getEvalOrder(), other.getEvalOrder()); + } + + return result; + } + } + + class PolicyNameComparator implements Comparator, Serializable { + @Override + public int compare(RangerPolicyEvaluator me, RangerPolicyEvaluator other) { + int result = Integer.compare(other.getPolicyPriority(), me.getPolicyPriority()); + + return result == 0 ? compareNormal(me, other) : result; + } + + private int compareNormal(RangerPolicyEvaluator me, RangerPolicyEvaluator other) { + final int result; + + if (me.hasDeny() && !other.hasDeny()) { + result = -1; + } else if (!me.hasDeny() && other.hasDeny()) { + result = 1; + } else { + result = me.getPolicy().getName().compareTo(other.getPolicy().getName()); + } + + return result; + } + } + + class PolicyACLSummary { + private final Map> usersAccessInfo = new HashMap<>(); + private final Map> groupsAccessInfo = new HashMap<>(); + private final Map> rolesAccessInfo = new HashMap<>(); + private final List rowFilters = new ArrayList<>(); + private final List dataMasks = new ArrayList<>(); + + private enum AccessorType { USER, GROUP, ROLE } + + public static class AccessResult { + private int result; + private final boolean hasSeenDeny; + + public AccessResult(int result) { + this(result, false); + } + + public AccessResult(int result, boolean hasSeenDeny) { + this.result = result; + this.hasSeenDeny = hasSeenDeny; + } + + public int getResult() { + return result; + } + + public void setResult(int result) { + this.result = result; + } + + public boolean getHasSeenDeny() { + return hasSeenDeny; + } + + @Override + public String toString() { + if (result == RangerPolicyEvaluator.ACCESS_ALLOWED) + return "ALLOWED, hasSeenDeny=" + hasSeenDeny; + if (result == RangerPolicyEvaluator.ACCESS_DENIED) + return "NOT_ALLOWED, hasSeenDeny=" + hasSeenDeny; + if (result == RangerPolicyEvaluator.ACCESS_CONDITIONAL) + return "CONDITIONAL_ALLOWED, hasSeenDeny=" + hasSeenDeny; + return "NOT_DETERMINED, hasSeenDeny=" + hasSeenDeny; + } + } + + PolicyACLSummary() { + } + + public Map> getUsersAccessInfo() { + return usersAccessInfo; + } + + public Map> getGroupsAccessInfo() { + return groupsAccessInfo; + } + + public Map> getRolesAccessInfo() { + return rolesAccessInfo; + } + + public List getRowFilters() { return rowFilters; } + + public List getDataMasks() { return dataMasks; } + + void processPolicyItem(RangerPolicyItem policyItem, int policyItemType, boolean isConditional) { + final Integer result; + final boolean hasContextSensitiveSpecification = CollectionUtils.isNotEmpty(policyItem.getConditions()); + + switch (policyItemType) { + case POLICY_ITEM_TYPE_ALLOW: + result = (hasContextSensitiveSpecification || isConditional) ? ACCESS_CONDITIONAL : ACCESS_ALLOWED; + break; + + case POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS: + result = (hasContextSensitiveSpecification || isConditional) ? null : ACCESS_DENIED; + break; + + case POLICY_ITEM_TYPE_DENY: + result = (hasContextSensitiveSpecification || isConditional) ? ACCESS_CONDITIONAL : ACCESS_DENIED; + break; + + case POLICY_ITEM_TYPE_DENY_EXCEPTIONS: + result = (hasContextSensitiveSpecification || isConditional) ? null : ACCESS_ALLOWED; + break; + + default: + result = null; + break; + } + + if (result != null) { + final List accesses; + + if (policyItem.getDelegateAdmin()) { + accesses = new ArrayList<>(); + + accesses.add(new RangerPolicyItemAccess(RangerPolicyEngine.ADMIN_ACCESS, policyItem.getDelegateAdmin())); + accesses.addAll(policyItem.getAccesses()); + } else { + accesses = policyItem.getAccesses(); + } + + final List groups = policyItem.getGroups(); + final List users = policyItem.getUsers(); + final List roles = policyItem.getRoles(); + boolean hasPublicGroup = false; + + for (RangerPolicyItemAccess access : accesses) { + for (String user : users) { + if (StringUtils.equals(user, RangerPolicyEngine.USER_CURRENT)) { + hasPublicGroup = true; + continue; + } else if (StringUtils.isBlank(user)) { + continue; + } + + addAccess(user, AccessorType.USER, access.getType(), result, policyItemType); + } + + for (String group : groups) { + if (StringUtils.equals(group, RangerPolicyEngine.GROUP_PUBLIC)) { + hasPublicGroup = true; + continue; + } + + addAccess(group, AccessorType.GROUP, access.getType(), result, policyItemType); + } + + if (hasPublicGroup) { + addAccess(RangerPolicyEngine.GROUP_PUBLIC, AccessorType.GROUP, access.getType(), result, policyItemType); + } + + for (String role : roles) { + addAccess(role, AccessorType.ROLE, access.getType(), result, policyItemType); + } + } + } + } + + void processRowFilterPolicyItem(RangerRowFilterPolicyItem policyItem) { + Set users = new HashSet<>(policyItem.getUsers()); + Set groups = new HashSet<>(policyItem.getGroups()); + Set roles = new HashSet<>(policyItem.getRoles()); + Set accessTypes = new HashSet<>(); + + policyItem.getAccesses().forEach(accessType -> accessTypes.add(accessType.getType())); + + if (users.contains(RangerPolicyEngine.USER_CURRENT)) { // replace with public group + users.remove(RangerPolicyEngine.USER_CURRENT); + + groups.add(RangerPolicyEngine.GROUP_PUBLIC); + } + + RowFilterResult filterResult = new RowFilterResult(users, groups, roles, accessTypes, policyItem.getRowFilterInfo()); + + if (RangerPolicyEvaluator.hasContextSensitiveSpecification(policyItem)) { + filterResult.setIsConditional(true); + } + + rowFilters.add(filterResult); + } + + void processDataMaskPolicyItem(RangerDataMaskPolicyItem policyItem) { + Set users = new HashSet<>(policyItem.getUsers()); + Set groups = new HashSet<>(policyItem.getGroups()); + Set roles = new HashSet<>(policyItem.getRoles()); + Set accessTypes = new HashSet<>(); + + policyItem.getAccesses().forEach(accessType -> accessTypes.add(accessType.getType())); + + if (users.contains(RangerPolicyEngine.USER_CURRENT)) { // replace with public group + users.remove(RangerPolicyEngine.USER_CURRENT); + + groups.add(RangerPolicyEngine.GROUP_PUBLIC); + } + + DataMaskResult dataMaskResult = new DataMaskResult(users, groups, roles, accessTypes, policyItem.getDataMaskInfo()); + + if (RangerPolicyEvaluator.hasContextSensitiveSpecification(policyItem)) { + dataMaskResult.setIsConditional(true); + } + + dataMasks.add(dataMaskResult); + } + + void finalizeAcls(final boolean isDenyAllElse, final Set allAccessTypeNames) { + Map publicGroupAccessInfo = groupsAccessInfo.get(RangerPolicyEngine.GROUP_PUBLIC); + + if (publicGroupAccessInfo != null) { + + // For each accessType in public, retrieve access + for (Map.Entry entry : publicGroupAccessInfo.entrySet()) { + final String accessType = entry.getKey(); + final AccessResult accessResult = entry.getValue(); + final int access = accessResult.getResult(); + + if (access == ACCESS_DENIED || access == ACCESS_ALLOWED) { + List keysToRemove = null; + + for (Map.Entry> mapEntry : usersAccessInfo.entrySet()) { + Map mapValue = mapEntry.getValue(); + + mapValue.remove(accessType); + + if (mapValue.isEmpty()) { + if (keysToRemove == null) { + keysToRemove = new ArrayList<>(); + } + + keysToRemove.add(mapEntry.getKey()); + } + } + + if (keysToRemove != null) { + for (String keyToRemove : keysToRemove) { + usersAccessInfo.remove(keyToRemove); + } + + keysToRemove.clear(); + } + + for (Map.Entry> mapEntry : groupsAccessInfo.entrySet()) { + if (!StringUtils.equals(mapEntry.getKey(), RangerPolicyEngine.GROUP_PUBLIC)) { + Map mapValue = mapEntry.getValue(); + + mapValue.remove(accessType); + + if (mapValue.isEmpty()) { + if (keysToRemove == null) { + keysToRemove = new ArrayList<>(); + } + + keysToRemove.add(mapEntry.getKey()); + } + } + } + + + if (keysToRemove != null) { + for (String keyToRemove : keysToRemove) { + groupsAccessInfo.remove(keyToRemove); + } + + keysToRemove.clear(); + } + } + } + } + + if (isDenyAllElse) { + // Go through all usersAccessInfo and groupsAccessInfo and mark ACCESS_UNDETERMINED to ACCESS_DENIED + for (Map.Entry> mapEntry : usersAccessInfo.entrySet()) { + for (Map.Entry accessEntry : mapEntry.getValue().entrySet()) { + AccessResult result = accessEntry.getValue(); + if (result.getResult() == ACCESS_UNDETERMINED) { + result.setResult(ACCESS_DENIED); + } + } + } + + for (Map.Entry> mapEntry : groupsAccessInfo.entrySet()) { + for (Map.Entry accessEntry : mapEntry.getValue().entrySet()) { + AccessResult result = accessEntry.getValue(); + if (result.getResult() == ACCESS_UNDETERMINED) { + result.setResult(ACCESS_DENIED); + } + } + } + + // Mark all unseen accessTypeNames are having no permission + for (Map.Entry> mapEntry : usersAccessInfo.entrySet()) { + for (String accessTypeName : allAccessTypeNames) { + if (!mapEntry.getValue().keySet().contains(accessTypeName)) { + mapEntry.getValue().put(accessTypeName, new AccessResult(ACCESS_DENIED, true)); + } + } + } + + for (Map.Entry> mapEntry : groupsAccessInfo.entrySet()) { + for (String accessTypeName : allAccessTypeNames) { + if (!mapEntry.getValue().keySet().contains(accessTypeName)) { + mapEntry.getValue().put(accessTypeName, new AccessResult(ACCESS_DENIED, true)); + } + } + } + + publicGroupAccessInfo = groupsAccessInfo.computeIfAbsent(RangerPolicyEngine.GROUP_PUBLIC, k -> new HashMap<>()); + + Set accessTypeNamesInPublicGroup = publicGroupAccessInfo.keySet(); + + for (String accessTypeName : allAccessTypeNames) { + if (!accessTypeNamesInPublicGroup.contains(accessTypeName)) { + boolean isDenyAccess = true; + for (Map.Entry> mapEntry : usersAccessInfo.entrySet()) { + AccessResult result = mapEntry.getValue().get(accessTypeName); + if (result == null || result.getResult() != ACCESS_DENIED) { + isDenyAccess = false; + break; + } + } + if (isDenyAccess) { + for (Map.Entry> mapEntry : groupsAccessInfo.entrySet()) { + if (!StringUtils.equals(mapEntry.getKey(), RangerPolicyEngine.GROUP_PUBLIC)) { + AccessResult result = mapEntry.getValue().get(accessTypeName); + if (result == null || result.getResult() != ACCESS_DENIED) { + isDenyAccess = false; + break; + } + } + } + } + publicGroupAccessInfo.put(accessTypeName, new AccessResult(isDenyAccess ? ACCESS_DENIED : ACCESS_CONDITIONAL, true)); + } + } + } + } + + private void addAccess(String accessorName, AccessorType accessorType, String accessType, Integer access, int policyItemType) { + final Map> accessorsAccessInfo; + + switch (accessorType) { + case USER: + accessorsAccessInfo = usersAccessInfo; + break; + + case GROUP: + accessorsAccessInfo = groupsAccessInfo; + break; + + case ROLE: + accessorsAccessInfo = rolesAccessInfo; + break; + + default: + return; + } + + final Map accessorAccessInfo = accessorsAccessInfo.computeIfAbsent(accessorName, k -> new HashMap<>()); + final AccessResult currentAccess = accessorAccessInfo.get(accessType); + + if (currentAccess == null) { + if (policyItemType == POLICY_ITEM_TYPE_ALLOW || policyItemType == POLICY_ITEM_TYPE_DENY) { + accessorAccessInfo.put(accessType, new AccessResult(access, policyItemType == POLICY_ITEM_TYPE_DENY)); + } + } else { + if (access.equals(RangerPolicyEvaluator.ACCESS_DENIED)) { + if (currentAccess.getResult() == ACCESS_CONDITIONAL) { + currentAccess.setResult(access); + } else { + int updatedAccessValue = currentAccess.getResult() + access; + + if (policyItemType == POLICY_ITEM_TYPE_DENY) { + updatedAccessValue = (updatedAccessValue < ACCESS_DENIED) ? ACCESS_DENIED : updatedAccessValue; + } else { + updatedAccessValue = (updatedAccessValue < ACCESS_UNDETERMINED) ? ACCESS_UNDETERMINED : updatedAccessValue; + } + + currentAccess.setResult(updatedAccessValue); + } + } else if (access.equals(RangerPolicyEvaluator.ACCESS_ALLOWED)) { + if (currentAccess.getResult() == ACCESS_CONDITIONAL) { + if (policyItemType == POLICY_ITEM_TYPE_ALLOW) { + currentAccess.setResult(access); + } + } else { + int updatedAccessValue = currentAccess.getResult() + access; + boolean replaceValue = false; + + if (policyItemType == POLICY_ITEM_TYPE_ALLOW) { + updatedAccessValue = (updatedAccessValue > ACCESS_ALLOWED) ? ACCESS_ALLOWED : updatedAccessValue; + replaceValue = true; // Forget earlier stashed hasSeenDeny + } else { + updatedAccessValue = (updatedAccessValue > ACCESS_UNDETERMINED) ? ACCESS_UNDETERMINED : updatedAccessValue; + } + + if (replaceValue) { + accessorAccessInfo.put(accessType, new AccessResult(updatedAccessValue)); + } else { + currentAccess.setResult(updatedAccessValue); + } + } + } else { + if (currentAccess.getResult() == ACCESS_UNDETERMINED) { + currentAccess.setResult(access); + } + } + } + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerPolicyItemEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerPolicyItemEvaluator.java new file mode 100644 index 00000000000..333b90ec51c --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerPolicyItemEvaluator.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + +import org.apache.atlas.plugin.conditionevaluator.RangerConditionEvaluator; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItem; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.atlas.plugin.policyengine.RangerAccessResult; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; + +import java.io.Serializable; +import java.util.Comparator; +import java.util.List; +import java.util.Set; + +public interface RangerPolicyItemEvaluator { + int POLICY_ITEM_TYPE_ALLOW = 0; + int POLICY_ITEM_TYPE_DENY = 1; + int POLICY_ITEM_TYPE_ALLOW_EXCEPTIONS = 2; + int POLICY_ITEM_TYPE_DENY_EXCEPTIONS = 3; + int POLICY_ITEM_TYPE_DATAMASK = 4; + int POLICY_ITEM_TYPE_ROWFILTER = 5; + + void init(); + + RangerPolicyItem getPolicyItem(); + + int getPolicyItemType(); + + int getPolicyItemIndex(); + + String getComments(); + + List getConditionEvaluators(); + + int getEvalOrder(); + + boolean isMatch(RangerAccessRequest request); + + boolean matchUserGroupAndOwner(String user, Set userGroups, Set roles, String owner); + + boolean matchAccessType(String accessType); + + boolean matchCustomConditions(RangerAccessRequest request); + + class EvalOrderComparator implements Comparator, Serializable { + @Override + public int compare(RangerPolicyItemEvaluator me, RangerPolicyItemEvaluator other) { + return Integer.compare(me.getEvalOrder(), other.getEvalOrder()); + } + } + void updateAccessResult(RangerPolicyEvaluator policyEvaluator, RangerAccessResult result, RangerPolicyResourceMatcher.MatchType matchType); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerRowFilterPolicyItemEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerRowFilterPolicyItemEvaluator.java new file mode 100644 index 00000000000..0e19b01c548 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerRowFilterPolicyItemEvaluator.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemRowFilterInfo; + + +public interface RangerRowFilterPolicyItemEvaluator extends RangerPolicyItemEvaluator { + void init(); + + RangerPolicyItemRowFilterInfo getRowFilterInfo(); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerValidityScheduleEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerValidityScheduleEvaluator.java new file mode 100644 index 00000000000..7c5f26d5dbc --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyevaluator/RangerValidityScheduleEvaluator.java @@ -0,0 +1,588 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyevaluator; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.model.RangerValidityRecurrence; +import org.apache.atlas.plugin.model.RangerValiditySchedule; +import org.apache.atlas.plugin.resourcematcher.ScheduledTimeAlwaysMatcher; +import org.apache.atlas.plugin.resourcematcher.ScheduledTimeExactMatcher; +import org.apache.atlas.plugin.resourcematcher.ScheduledTimeMatcher; +import org.apache.atlas.plugin.resourcematcher.ScheduledTimeRangeMatcher; +import org.apache.atlas.plugin.util.RangerPerfTracer; + +import javax.annotation.Nonnull; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.GregorianCalendar; +import java.util.List; +import java.util.TimeZone; + +public class RangerValidityScheduleEvaluator { + private static final Log LOG = LogFactory.getLog(RangerValidityScheduleEvaluator.class); + private static final Log PERF_LOG = LogFactory.getLog("test.perf.RangerValidityScheduleEvaluator"); + + private final static TimeZone defaultTZ = TimeZone.getDefault(); + + private static final ThreadLocal DATE_FORMATTER = new ThreadLocal() { + @Override + protected DateFormat initialValue() { + return new SimpleDateFormat(RangerValiditySchedule.VALIDITY_SCHEDULE_DATE_STRING_SPECIFICATION); + } + }; + + private final Date startTime; + private final Date endTime; + private final String timeZone; + private final List recurrenceEvaluators = new ArrayList<>(); + + public RangerValidityScheduleEvaluator(@Nonnull RangerValiditySchedule validitySchedule) { + this(validitySchedule.getStartTime(), validitySchedule.getEndTime(), validitySchedule.getTimeZone(), validitySchedule.getRecurrences()); + } + + public RangerValidityScheduleEvaluator(String startTimeStr, String endTimeStr, String timeZone, List recurrences) { + Date startTime = null; + Date endTime = null; + + if (StringUtils.isNotEmpty(startTimeStr)) { + try { + startTime = DATE_FORMATTER.get().parse(startTimeStr); + } catch (ParseException exception) { + LOG.error("Error parsing startTime:[" + startTimeStr + "]", exception); + } + } + + if (StringUtils.isNotEmpty(endTimeStr)) { + try { + endTime = DATE_FORMATTER.get().parse(endTimeStr); + } catch (ParseException exception) { + LOG.error("Error parsing endTime:[" + endTimeStr + "]", exception); + } + } + + this.startTime = startTime; + this.endTime = endTime; + this.timeZone = timeZone; + + if (CollectionUtils.isNotEmpty(recurrences)) { + for (RangerValidityRecurrence recurrence : recurrences) { + recurrenceEvaluators.add(new RangerRecurrenceEvaluator(recurrence)); + } + } + } + + public boolean isApplicable(long accessTime) { + if (LOG.isDebugEnabled()) { + LOG.debug("===> isApplicable(accessTime=" + accessTime + ")"); + } + + boolean ret = false; + RangerPerfTracer perf = null; + + if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "RangerValidityScheduleEvaluator.isApplicable(accessTime=" + accessTime + ")"); + } + + long startTimeInMSs = startTime == null ? 0 : startTime.getTime(); + long endTimeInMSs = endTime == null ? 0 : endTime.getTime(); + + if (StringUtils.isNotBlank(timeZone)) { + TimeZone targetTZ = TimeZone.getTimeZone(timeZone); + + if (startTimeInMSs > 0) { + startTimeInMSs = getAdjustedTime(startTimeInMSs, targetTZ); + } + + if (endTimeInMSs > 0) { + endTimeInMSs = getAdjustedTime(endTimeInMSs, targetTZ); + } + } + + if ((startTimeInMSs == 0 || accessTime >= startTimeInMSs) && (endTimeInMSs == 0 || accessTime <= endTimeInMSs)) { + if (CollectionUtils.isEmpty(recurrenceEvaluators)) { + ret = true; + } else { + Calendar now = new GregorianCalendar(); + now.setTime(new Date(accessTime)); + + for (RangerRecurrenceEvaluator recurrenceEvaluator : recurrenceEvaluators) { + ret = recurrenceEvaluator.isApplicable(now); + + if (ret) { + break; + } + } + } + } + + RangerPerfTracer.log(perf); + + if (LOG.isDebugEnabled()) { + LOG.debug("<=== isApplicable(accessTime=" + accessTime + ") :" + ret); + } + return ret; + } + + public static long getAdjustedTime(long localTime, TimeZone timeZone) { + long ret = localTime; + + if (LOG.isDebugEnabled()) { + LOG.debug("Input:[" + new Date(localTime) + ", target-timezone" + timeZone + "], default-timezone:[" + defaultTZ + "]"); + } + + if (!defaultTZ.equals(timeZone)) { + int targetOffset = timeZone.getOffset(localTime); + int defaultOffset = defaultTZ.getOffset(localTime); + int diff = defaultOffset - targetOffset; + + if (LOG.isDebugEnabled()) { + LOG.debug("Offset of target-timezone from UTC :[" + targetOffset + "]"); + LOG.debug("Offset of default-timezone from UTC :[" + defaultOffset + "]"); + LOG.debug("Difference between default-timezone and target-timezone :[" + diff + "]"); + } + + ret += diff; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Output:[" + new Date(ret) + "]"); + } + + return ret; + } + + static class RangerRecurrenceEvaluator { + private final List minutes = new ArrayList<>(); + private final List hours = new ArrayList<>(); + private final List daysOfMonth = new ArrayList<>(); + private final List daysOfWeek = new ArrayList<>(); + private final List months = new ArrayList<>(); + private final List years = new ArrayList<>(); + private final RangerValidityRecurrence recurrence; + private int intervalInMinutes = 0; + + + public RangerRecurrenceEvaluator(RangerValidityRecurrence recurrence) { + this.recurrence = recurrence; + + if (recurrence != null) { + intervalInMinutes = RangerValidityRecurrence.ValidityInterval.getValidityIntervalInMinutes(recurrence.getInterval()); + + if (intervalInMinutes > 0) { + addScheduledTime(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute, minutes); + addScheduledTime(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour, hours); + addScheduledTime(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth, daysOfMonth); + addScheduledTime(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek, daysOfWeek); + addScheduledTime(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month, months); + addScheduledTime(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.year, years); + } + } + } + + public boolean isApplicable(Calendar now) { + boolean ret = false; + + RangerPerfTracer perf = null; + + if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "RangerRecurrenceEvaluator.isApplicable(accessTime=" + now.getTime().getTime() + ")"); + } + + if (recurrence != null && intervalInMinutes > 0) { // recurring schedule + + if (LOG.isDebugEnabled()) { + LOG.debug("Access-Time:[" + now.getTime() + "]"); + } + + Calendar startOfInterval = getClosestPastEpoch(now); + + if (startOfInterval != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Start-of-Interval:[" + startOfInterval.getTime() + "]"); + } + + Calendar endOfInterval = (Calendar) startOfInterval.clone(); + endOfInterval.add(Calendar.MINUTE, recurrence.getInterval().getMinutes()); + endOfInterval.add(Calendar.HOUR, recurrence.getInterval().getHours()); + endOfInterval.add(Calendar.DAY_OF_MONTH, recurrence.getInterval().getDays()); + + endOfInterval.getTime(); // for recomputation + now.getTime(); + + if (LOG.isDebugEnabled()) { + LOG.debug("End-of-Interval:[" + endOfInterval.getTime() + "]"); + } + + ret = startOfInterval.compareTo(now) <= 0 && endOfInterval.compareTo(now) >= 0; + } + + } else { + ret = true; + } + + RangerPerfTracer.log(perf); + return ret; + } + + private void addScheduledTime(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec fieldSpec, List list) { + final String str = recurrence.getSchedule().getFieldValue(fieldSpec); + final boolean isMonth = fieldSpec == RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month; + + if (StringUtils.isNotBlank(str)) { + String[] specs = str.split(","); + + for (String spec : specs) { + String[] range = spec.split("-"); + + if (range.length == 1) { + if (StringUtils.equals(range[0], RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) { + list.clear(); + list.add(new ScheduledTimeAlwaysMatcher()); + + break; + } else { + list.add(new ScheduledTimeExactMatcher(Integer.valueOf(range[0]) - (isMonth ? 1 : 0))); + } + } else { + if (StringUtils.equals(range[0], RangerValidityRecurrence.RecurrenceSchedule.WILDCARD) || StringUtils.equals(range[1], RangerValidityRecurrence.RecurrenceSchedule.WILDCARD)) { + list.clear(); + list.add(new ScheduledTimeAlwaysMatcher()); + + break; + } else { + list.add(new ScheduledTimeRangeMatcher(Integer.valueOf(range[0]) - (isMonth ? 1 : 0), Integer.valueOf(range[1]) - (isMonth ? 1 : 0))); + } + } + } + + Collections.reverse(list); + } + + } + + /* + Given a Calendar object, get the closest, earlier Calendar object based on configured validity schedules. + Returns - a valid Calendar object. Throws exception if any errors during processing or no suitable Calendar object is found. + Description - Typically, a caller will call this with Calendar constructed with current time, and use returned object + along with specified interval to ensure that next schedule time is after the input Calendar. + Algorithm - This involves doing a Calendar arithmetic (subtraction) with borrow. The tricky parts are ensuring that + Calendar arithmetic yields a valid Calendar object. + - Start with minutes, and then hours. + - Must make sure that the later of the two Calendars - one computed with dayOfMonth, another computed with + dayOfWeek - is picked + - For dayOfMonth calculation, consider that months have different number of days + */ + + private static class ValueWithBorrow { + int value; + boolean borrow; + + ValueWithBorrow() { + } + + ValueWithBorrow(int value) { + this(value, false); + } + + ValueWithBorrow(int value, boolean borrow) { + this.value = value; + this.borrow = borrow; + } + + void setValue(int value) { + this.value = value; + } + + void setBorrow(boolean borrow) { + this.borrow = borrow; + } + + int getValue() { + return value; + } + + boolean getBorrow() { + return borrow; + } + + @Override + public String toString() { + return "value=" + value + ", borrow=" + borrow; + } + } + + private Calendar getClosestPastEpoch(Calendar current) { + Calendar ret = null; + + try { + ValueWithBorrow input = new ValueWithBorrow(); + + input.setValue(current.get(Calendar.MINUTE)); + input.setBorrow(false); + ValueWithBorrow closestMinute = getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.minute, minutes, input); + + input.setValue(current.get(Calendar.HOUR_OF_DAY)); + input.setBorrow(closestMinute.borrow); + ValueWithBorrow closestHour = getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.hour, hours, input); + + Calendar dayOfMonthCalendar = getClosestDayOfMonth(current, closestMinute, closestHour); + + Calendar dayOfWeekCalendar = getClosestDayOfWeek(current, closestMinute, closestHour); + + ret = getEarlierCalendar(dayOfMonthCalendar, dayOfWeekCalendar); + + if (LOG.isDebugEnabled()) { + LOG.debug("ClosestPastEpoch:[" + (ret != null ? ret.getTime() : null) + "]"); + } + + } catch (Exception e) { + LOG.error("Could not find ClosestPastEpoch, Exception=", e); + } + return ret; + } + + private Calendar getClosestDayOfMonth(Calendar current, ValueWithBorrow closestMinute, ValueWithBorrow closestHour) throws Exception { + Calendar ret = null; + if (StringUtils.isNotBlank(recurrence.getSchedule().getDayOfMonth())) { + int initialDayOfMonth = current.get(Calendar.DAY_OF_MONTH); + + int currentDayOfMonth = initialDayOfMonth, currentMonth = current.get(Calendar.MONTH), currentYear = current.get(Calendar.YEAR); + int maximumDaysInPreviousMonth = getMaximumValForPreviousMonth(current); + + if (closestHour.borrow) { + initialDayOfMonth--; + Calendar dayOfMonthCalc = (GregorianCalendar) current.clone(); + dayOfMonthCalc.add(Calendar.DAY_OF_MONTH, -1); + dayOfMonthCalc.getTime(); + int previousDayOfMonth = dayOfMonthCalc.get(Calendar.DAY_OF_MONTH); + if (initialDayOfMonth < previousDayOfMonth) { + if (LOG.isDebugEnabled()) { + LOG.debug("Need to borrow from previous month, initialDayOfMonth:[" + initialDayOfMonth + "], previousDayOfMonth:[" + previousDayOfMonth + "], dayOfMonthCalc:[" + dayOfMonthCalc.getTime() + "]"); + } + currentDayOfMonth = previousDayOfMonth; + currentMonth = dayOfMonthCalc.get(Calendar.MONTH); + currentYear = dayOfMonthCalc.get(Calendar.YEAR); + maximumDaysInPreviousMonth = getMaximumValForPreviousMonth(dayOfMonthCalc); + } else if (initialDayOfMonth == previousDayOfMonth) { + if (LOG.isDebugEnabled()) { + LOG.debug("No need to borrow from previous month, initialDayOfMonth:[" + initialDayOfMonth + "], previousDayOfMonth:[" + previousDayOfMonth + "]"); + } + } else { + LOG.error("Should not get here, initialDayOfMonth:[" + initialDayOfMonth + "], previousDayOfMonth:[" + previousDayOfMonth + "]"); + throw new Exception("Should not get here, initialDayOfMonth:[" + initialDayOfMonth + "], previousDayOfMonth:[" + previousDayOfMonth + "]"); + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("currentDayOfMonth:[" + currentDayOfMonth + "], maximumDaysInPreviourMonth:[" + maximumDaysInPreviousMonth + "]"); + } + ValueWithBorrow input = new ValueWithBorrow(); + input.setValue(currentDayOfMonth); + input.setBorrow(false); + ValueWithBorrow closestDayOfMonth = null; + do { + int i = 0; + try { + closestDayOfMonth = getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfMonth, daysOfMonth, input, maximumDaysInPreviousMonth); + } catch (Exception e) { + i++; + Calendar c = (GregorianCalendar) current.clone(); + c.set(Calendar.YEAR, currentYear); + c.set(Calendar.MONTH, currentMonth); + c.set(Calendar.DAY_OF_MONTH, currentDayOfMonth); + c.add(Calendar.MONTH, -i); + c.getTime(); + currentMonth = c.get(Calendar.MONTH); + currentYear = c.get(Calendar.YEAR); + currentDayOfMonth = c.get(Calendar.DAY_OF_MONTH); + maximumDaysInPreviousMonth = getMaximumValForPreviousMonth(c); + input.setValue(currentDayOfMonth); + input.setBorrow(false); + } + } while (closestDayOfMonth == null); + + // Build calendar for dayOfMonth + ret = new GregorianCalendar(); + ret.set(Calendar.DAY_OF_MONTH, closestDayOfMonth.value); + ret.set(Calendar.HOUR_OF_DAY, closestHour.value); + ret.set(Calendar.MINUTE, closestMinute.value); + ret.set(Calendar.SECOND, 0); + ret.set(Calendar.MILLISECOND, 0); + + ret.set(Calendar.YEAR, currentYear); + + if (closestDayOfMonth.borrow) { + ret.set(Calendar.MONTH, currentMonth - 1); + } else { + ret.set(Calendar.MONTH, currentMonth); + } + ret.getTime(); // For recomputation + + if (LOG.isDebugEnabled()) { + LOG.debug("Best guess using DAY_OF_MONTH:[" + ret.getTime() + "]"); + } + } + return ret; + } + + private Calendar getClosestDayOfWeek(Calendar current, ValueWithBorrow closestMinute, ValueWithBorrow closestHour) throws Exception { + Calendar ret = null; + if (StringUtils.isNotBlank(recurrence.getSchedule().getDayOfWeek())) { + ValueWithBorrow input = new ValueWithBorrow(); + + input.setValue(current.get(Calendar.DAY_OF_WEEK)); + input.setBorrow(closestHour.borrow); + + + ValueWithBorrow closestDayOfWeek = getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek, daysOfWeek, input); + + int daysToGoback = closestHour.borrow ? 1 : 0; + int range = RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek.maximum - RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.dayOfWeek.minimum + 1; + + if (closestDayOfWeek.borrow) { + if (input.value - closestDayOfWeek.value != daysToGoback) { + daysToGoback = range + input.value - closestDayOfWeek.value; + } + } else { + daysToGoback = input.value - closestDayOfWeek.value; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Need to go back [" + daysToGoback + "] days to match dayOfWeek"); + } + + ret = (GregorianCalendar) current.clone(); + ret.set(Calendar.MINUTE, closestMinute.value); + ret.set(Calendar.HOUR_OF_DAY, closestHour.value); + ret.add(Calendar.DAY_OF_MONTH, (0 - daysToGoback)); + ret.set(Calendar.SECOND, 0); + ret.set(Calendar.MILLISECOND, 0); + + ret.getTime(); + + if (LOG.isDebugEnabled()) { + LOG.debug("Best guess using DAY_OF_WEEK:[" + ret.getTime() + "]"); + } + } + return ret; + + } + + private int getMaximumValForPreviousMonth(Calendar current) { + Calendar cal = (Calendar) current.clone(); + cal.add(Calendar.MONTH, -1); + cal.getTime(); // For recomputation + + return cal.getActualMaximum(Calendar.DAY_OF_MONTH); + } + + private Calendar getEarlierCalendar(Calendar dayOfMonthCalendar, Calendar dayOfWeekCalendar) throws Exception { + + Calendar withDayOfMonth = fillOutCalendar(dayOfMonthCalendar); + if (LOG.isDebugEnabled()) { + LOG.debug("dayOfMonthCalendar:[" + (withDayOfMonth != null ? withDayOfMonth.getTime() : null) + "]"); + } + + Calendar withDayOfWeek = fillOutCalendar(dayOfWeekCalendar); + if (LOG.isDebugEnabled()) { + LOG.debug("dayOfWeekCalendar:[" + (withDayOfWeek != null ? withDayOfWeek.getTime() : null) + "]"); + } + + if (withDayOfMonth != null && withDayOfWeek != null) { + return withDayOfMonth.after(withDayOfWeek) ? withDayOfMonth : withDayOfWeek; + } else if (withDayOfMonth == null) { + return withDayOfWeek; + } else { + return withDayOfMonth; + } + } + + private Calendar fillOutCalendar(Calendar calendar) throws Exception { + Calendar ret = null; + + if (calendar != null) { + ValueWithBorrow input = new ValueWithBorrow(calendar.get(Calendar.MONTH)); + ValueWithBorrow closestMonth = getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.month, months, input); + + input.setValue(calendar.get(Calendar.YEAR)); + input.setBorrow(closestMonth.borrow); + ValueWithBorrow closestYear = getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec.year, years, input); + + // Build calendar + ret = (Calendar) calendar.clone(); + ret.set(Calendar.YEAR, closestYear.value); + ret.set(Calendar.MONTH, closestMonth.value); + ret.set(Calendar.SECOND, 0); + + ret.getTime(); // for recomputation + if (LOG.isDebugEnabled()) { + LOG.debug("Filled-out-Calendar:[" + ret.getTime() + "]"); + } + } + return ret; + } + + private ValueWithBorrow getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec fieldSpec, List searchList, ValueWithBorrow input) throws Exception { + return getPastFieldValueWithBorrow(fieldSpec, searchList, input, fieldSpec.maximum); + } + + private ValueWithBorrow getPastFieldValueWithBorrow(RangerValidityRecurrence.RecurrenceSchedule.ScheduleFieldSpec fieldSpec, List searchList, ValueWithBorrow input, int maximum) throws Exception { + + ValueWithBorrow ret; + boolean borrow = false; + + int value = input.value - (input.borrow ? 1 : 0); + + if (CollectionUtils.isNotEmpty(searchList)) { + int range = fieldSpec.maximum - fieldSpec.minimum + 1; + + for (int i = 0; i < range; i++, value--) { + if (value < fieldSpec.minimum) { + value = maximum; + borrow = true; + } + for (ScheduledTimeMatcher time : searchList) { + if (time.isMatch(value)) { + if (LOG.isDebugEnabled()) { + LOG.debug("Found match in field:[" + fieldSpec + "], value:[" + value + "], borrow:[" + borrow + "], maximum:[" + maximum + "]"); + } + return new ValueWithBorrow(value, borrow); + } + } + } + // Not found + throw new Exception("No match found in field:[" + fieldSpec + "] for [input=" + input + "]"); + } else { + if (value < fieldSpec.minimum) { + value = maximum; + } + ret = new ValueWithBorrow(value, false); + } + return ret; + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java new file mode 100644 index 00000000000..9cba4849e38 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyresourcematcher/RangerDefaultPolicyResourceMatcher.java @@ -0,0 +1,798 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyresourcematcher; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyResource; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerResourceDef; +import org.apache.atlas.plugin.model.validation.RangerServiceDefHelper; +import org.apache.atlas.plugin.policyengine.RangerAccessResource; +import org.apache.atlas.plugin.policyengine.RangerAccessResourceImpl; +import org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher; +import org.apache.atlas.plugin.resourcematcher.RangerResourceMatcher; +import org.apache.atlas.plugin.util.RangerPerfTracer; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class RangerDefaultPolicyResourceMatcher implements RangerPolicyResourceMatcher { + private static final Log LOG = LogFactory.getLog(RangerDefaultPolicyResourceMatcher.class); + + private static final Log PERF_POLICY_RESOURCE_MATCHER_INIT_LOG = RangerPerfTracer.getPerfLogger("policyresourcematcher.init"); + private static final Log PERF_POLICY_RESOURCE_MATCHER_MATCH_LOG = RangerPerfTracer.getPerfLogger("policyresourcematcher.match"); + + protected RangerServiceDef serviceDef; + protected String policyType; + protected Map policyResources; + + private Map allMatchers; + private boolean needsDynamicEval = false; + private List validResourceHierarchy; + private boolean isInitialized = false; + private RangerServiceDefHelper serviceDefHelper; + + @Override + public void setServiceDef(RangerServiceDef serviceDef) { + if (isInitialized) { + LOG.warn("RangerDefaultPolicyResourceMatcher is already initialized. init() must be done again after updating serviceDef"); + } + + this.serviceDef = serviceDef; + } + + @Override + public void setPolicy(RangerPolicy policy) { + if (isInitialized) { + LOG.warn("RangerDefaultPolicyResourceMatcher is already initialized. init() must be done again after updating policy"); + } + + if (policy == null) { + setPolicyResources(null, RangerPolicy.POLICY_TYPE_ACCESS); + } else { + setPolicyResources(policy.getResources(), StringUtils.isEmpty(policy.getPolicyType()) ? RangerPolicy.POLICY_TYPE_ACCESS : policy.getPolicyType()); + } + } + + @Override + public void setPolicyResources(Map policyResources) { + if (isInitialized) { + LOG.warn("RangerDefaultPolicyResourceMatcher is already initialized. init() must be done again after updating policy-resources"); + } + + setPolicyResources(policyResources, RangerPolicy.POLICY_TYPE_ACCESS); + } + + @Override + public void setPolicyResources(Map policyResources, String policyType) { + this.policyResources = policyResources; + this.policyType = policyType; + } + + @Override + public void setServiceDefHelper(RangerServiceDefHelper serviceDefHelper) { + this.serviceDefHelper = serviceDefHelper; + } + + @Override + public RangerServiceDef getServiceDef() { + return serviceDef; + } + + @Override + public RangerResourceMatcher getResourceMatcher(String resourceName) { + return allMatchers != null ? allMatchers.get(resourceName) : null; + } + + @Override + public boolean getNeedsDynamicEval() { return needsDynamicEval; } + + @Override + public void init() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyResourceMatcher.init()"); + } + + allMatchers = null; + needsDynamicEval = false; + validResourceHierarchy = null; + isInitialized = false; + + String errorText = ""; + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_RESOURCE_MATCHER_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_RESOURCE_MATCHER_INIT_LOG, "RangerDefaultPolicyResourceMatcher.init()"); + } + + if (policyResources != null && !policyResources.isEmpty() && serviceDef != null) { + serviceDefHelper = serviceDefHelper == null ? new RangerServiceDefHelper(serviceDef, false) : serviceDefHelper; + + Set> resourceHierarchies = serviceDefHelper.getResourceHierarchies(policyType, policyResources.keySet()); + int validHierarchiesCount = 0; + + for (List resourceHierarchy : resourceHierarchies) { + + if (isHierarchyValidForResources(resourceHierarchy, policyResources)) { + validHierarchiesCount++; + + if (validHierarchiesCount == 1) { + validResourceHierarchy = resourceHierarchy; + } else { + validResourceHierarchy = null; + } + } else { + LOG.warn("RangerDefaultPolicyResourceMatcher.init(): gaps found in policyResources, skipping hierarchy"); + } + } + + if (validHierarchiesCount > 0) { + allMatchers = new HashMap<>(); + + for (List resourceHierarchy : resourceHierarchies) { + for (RangerResourceDef resourceDef : resourceHierarchy) { + String resourceName = resourceDef.getName(); + + if (allMatchers.containsKey(resourceName)) { + continue; + } + + RangerPolicyResource policyResource = policyResources.get(resourceName); + + if (policyResource == null) { + if (LOG.isDebugEnabled()) { + LOG.debug("RangerDefaultPolicyResourceMatcher.init(): no matcher created for " + resourceName + ". Continuing ..."); + } + + continue; + } + + RangerResourceMatcher matcher = createResourceMatcher(resourceDef, policyResource); + + if (matcher != null) { + if (!needsDynamicEval && matcher.getNeedsDynamicEval()) { + needsDynamicEval = true; + } + + allMatchers.put(resourceName, matcher); + } else { + LOG.error("RangerDefaultPolicyResourceMatcher.init(): failed to find matcher for resource " + resourceName); + + allMatchers = null; + errorText = "no matcher found for resource " + resourceName; + + break; + } + } + + if (allMatchers == null) { + break; + } + } + } else { + errorText = "policyResources elements are not part of any valid resourcedef hierarchy."; + } + } else { + errorText = "policyResources is null or empty, or serviceDef is null."; + } + + if (allMatchers == null && !RangerPolicy.POLICY_TYPE_AUDIT.equals(policyType)) { + serviceDefHelper = null; + validResourceHierarchy = null; + + Set policyResourceKeys = policyResources == null ? null : policyResources.keySet(); + String serviceDefName = serviceDef == null ? "" : serviceDef.getName(); + StringBuilder keysString = new StringBuilder(); + + if (CollectionUtils.isNotEmpty(policyResourceKeys)) { + for (String policyResourceKeyName : policyResourceKeys) { + keysString.append(policyResourceKeyName).append(" "); + } + } + + LOG.error("RangerDefaultPolicyResourceMatcher.init() failed: " + errorText + " (serviceDef=" + serviceDefName + ", policyResourceKeys=" + keysString.toString()); + } else { + isInitialized = true; + } + + RangerPerfTracer.log(perf); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyResourceMatcher.init(): ret=" + isInitialized); + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + return toString(sb).toString(); + } + + @Override + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerDefaultPolicyResourceMatcher={"); + + sb.append("isInitialized=").append(isInitialized).append(", "); + + sb.append("matchers={"); + if(allMatchers != null) { + for(RangerResourceMatcher matcher : allMatchers.values()) { + sb.append("{").append(matcher).append("} "); + } + } + sb.append("} "); + + sb.append("}"); + + return sb; + } + + @Override + public boolean isCompleteMatch(RangerAccessResource resource, Map evalContext) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resource + ", " + evalContext + ")"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_RESOURCE_MATCHER_MATCH_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_RESOURCE_MATCHER_MATCH_LOG, "RangerDefaultPolicyResourceMatcher.grantRevokeMatch()"); + } + + boolean ret = false; + Collection resourceKeys = resource == null ? null : resource.getKeys(); + Collection policyKeys = policyResources == null ? null : policyResources.keySet(); + boolean keysMatch = resourceKeys != null && policyKeys != null && CollectionUtils.isEqualCollection(resourceKeys, policyKeys); + + if (keysMatch) { + for (RangerResourceDef resourceDef : serviceDef.getResources()) { + String resourceName = resourceDef.getName(); + Object resourceValue = resource.getValue(resourceName); + RangerResourceMatcher matcher = getResourceMatcher(resourceName); + + if (resourceValue == null) { + ret = matcher == null || matcher.isCompleteMatch(null, evalContext); + } else if (resourceValue instanceof String) { + String strValue = (String) resourceValue; + + if (StringUtils.isEmpty(strValue)) { + ret = matcher == null || matcher.isCompleteMatch(strValue, evalContext); + } else { + ret = matcher != null && matcher.isCompleteMatch(strValue, evalContext); + } + } else { // return false for any other type of resourceValue + ret = false; + } + + if (!ret) { + break; + } + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("isCompleteMatch(): keysMatch=false. resourceKeys=" + resourceKeys + "; policyKeys=" + policyKeys); + } + } + + RangerPerfTracer.log(perf); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resource + ", " + evalContext + "): " + ret); + } + + return ret; + } + + @Override + public boolean isCompleteMatch(Map resources, Map evalContext) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resources + ", " + evalContext + ")"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_RESOURCE_MATCHER_MATCH_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_RESOURCE_MATCHER_MATCH_LOG, "RangerDefaultPolicyResourceMatcher.applyPolicyMatch()"); + } + + boolean ret = false; + Collection resourceKeys = resources == null ? null : resources.keySet(); + Collection policyKeys = policyResources == null ? null : policyResources.keySet(); + boolean keysMatch = resourceKeys != null && policyKeys != null && CollectionUtils.isEqualCollection(resourceKeys, policyKeys); + + if (keysMatch) { + for (RangerResourceDef resourceDef : serviceDef.getResources()) { + String resourceName = resourceDef.getName(); + RangerPolicyResource resourceValues = resources.get(resourceName); + RangerPolicyResource policyValues = policyResources == null ? null : policyResources.get(resourceName); + + if (resourceValues == null || CollectionUtils.isEmpty(resourceValues.getValues())) { + ret = (policyValues == null || CollectionUtils.isEmpty(policyValues.getValues())); + } else if (policyValues != null && CollectionUtils.isNotEmpty(policyValues.getValues())) { + ret = CollectionUtils.isEqualCollection(resourceValues.getValues(), policyValues.getValues()); + } + + if (!ret) { + break; + } + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("isCompleteMatch(): keysMatch=false. resourceKeys=" + resourceKeys + "; policyKeys=" + policyKeys); + } + } + + RangerPerfTracer.log(perf); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyResourceMatcher.isCompleteMatch(" + resources + ", " + evalContext + "): " + ret); + } + + return ret; + } + + @Override + public boolean isMatch(RangerPolicy policy, MatchScope scope, Map evalContext) { + boolean ret = false; + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_RESOURCE_MATCHER_MATCH_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_RESOURCE_MATCHER_MATCH_LOG, "RangerDefaultPolicyResourceMatcher.getPoliciesNonLegacy()"); + } + + Map resources = policy.getResources(); + + if (policy.getPolicyType().equals(policyType) && MapUtils.isNotEmpty(resources)) { + List hierarchy = getMatchingHierarchy(resources.keySet()); + + if (CollectionUtils.isNotEmpty(hierarchy)) { + MatchType matchType = MatchType.NONE; + RangerAccessResourceImpl accessResource = new RangerAccessResourceImpl(); + + accessResource.setServiceDef(serviceDef); + + // Build up accessResource resourceDef by resourceDef. + // For each resourceDef, + // examine policy-values one by one. + // The first value that is acceptable, that is, + // value matches in any way, is used for that resourceDef, and + // next resourceDef is processed. + // If none of the values matches, the policy as a whole definitely will not match, + // therefore, the match is failed + // After all resourceDefs are processed, and some match is achieved at every + // level, the final matchType (which is for the entire policy) is checked against + // requested scope to determine the match-result. + + // Unit tests in TestDefaultPolicyResourceForPolicy.java, TestDefaultPolicyResourceMatcher.java + // test_defaultpolicyresourcematcher_for_hdfs_policy.json, and + // test_defaultpolicyresourcematcher_for_hive_policy.json, and + // test_defaultPolicyResourceMatcher.json + + boolean skipped = false; + + for (RangerResourceDef resourceDef : hierarchy) { + String name = resourceDef.getName(); + RangerPolicyResource policyResource = resources.get(name); + + if (policyResource != null && CollectionUtils.isNotEmpty(policyResource.getValues())) { + ret = false; + matchType = MatchType.NONE; + + if (!skipped) { + for (String value : policyResource.getValues()) { + accessResource.setValue(name, value); + + matchType = getMatchType(accessResource, evalContext); + + if (matchType != MatchType.NONE) { // One value for this resourceDef matched + ret = true; + break; + } + } + } else { + break; + } + } else { + skipped = true; + } + + if (!ret) { // None of the values specified for this resourceDef matched, no point in continuing with next resourceDef + break; + } + } + + ret = ret && isMatch(scope, matchType); + } + } + + RangerPerfTracer.log(perf); + + return ret; + } + + @Override + public boolean isMatch(RangerAccessResource resource, Map evalContext) { + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_RESOURCE_MATCHER_MATCH_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_RESOURCE_MATCHER_MATCH_LOG, "RangerDefaultPolicyResourceMatcher.grantRevokeMatch()"); + } + + /* + * There is already API to get the delegateAdmin permissions for a map of policyResources. + * That implementation should be reused for figuring out delegateAdmin permissions for a resource as well. + */ + + Map policyResources = null; + + for (RangerResourceDef resourceDef : serviceDef.getResources()) { + String resourceName = resourceDef.getName(); + Object resourceValue = resource.getValue(resourceName); + if (resourceValue instanceof String) { + String strValue = (String) resourceValue; + + if (policyResources == null) { + policyResources = new HashMap<>(); + } + policyResources.put(resourceName, new RangerPolicyResource(strValue)); + } else if (resourceValue != null) { // return false for any other type of resourceValue + policyResources = null; + + break; + } + } + final boolean ret = MapUtils.isNotEmpty(policyResources) && isMatch(policyResources, evalContext); + + RangerPerfTracer.log(perf); + + return ret; + } + + @Override + public boolean isMatch(Map resources, Map evalContext) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyResourceMatcher.isMatch(" + resources + ", " + evalContext + ")"); + } + + boolean ret = false; + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_RESOURCE_MATCHER_MATCH_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_RESOURCE_MATCHER_MATCH_LOG, "RangerDefaultPolicyResourceMatcher.delegateAdminMatch()"); + } + + if(serviceDef != null && serviceDef.getResources() != null) { + Collection resourceKeys = resources == null ? null : resources.keySet(); + Collection policyKeys = policyResources == null ? null : policyResources.keySet(); + + boolean keysMatch = CollectionUtils.isEmpty(resourceKeys) || (policyKeys != null && policyKeys.containsAll(resourceKeys)); + + if(keysMatch) { + for(RangerResourceDef resourceDef : serviceDef.getResources()) { + String resourceName = resourceDef.getName(); + RangerPolicyResource resourceValues = resources == null ? null : resources.get(resourceName); + List values = resourceValues == null ? null : resourceValues.getValues(); + RangerResourceMatcher matcher = allMatchers == null ? null : allMatchers.get(resourceName); + + if (matcher != null) { + if (CollectionUtils.isNotEmpty(values)) { + for (String value : values) { + ret = matcher.isMatch(value, evalContext); + if (!ret) { + break; + } + } + } else { + ret = matcher.isMatchAny(); + } + } else { + ret = CollectionUtils.isEmpty(values); + } + + if(! ret) { + break; + } + } + } else { + if(LOG.isDebugEnabled()) { + LOG.debug("isMatch(): keysMatch=false. resourceKeys=" + resourceKeys + "; policyKeys=" + policyKeys); + } + } + } + + RangerPerfTracer.log(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyResourceMatcher.isMatch(" + resources + ", " + evalContext + "): " + ret); + } + + return ret; + } + + @Override + public boolean isMatch(RangerAccessResource resource, MatchScope scope, Map evalContext) { + MatchType matchType = getMatchType(resource, evalContext); + return isMatch(scope, matchType); + } + + @Override + public MatchType getMatchType(RangerAccessResource resource, Map evalContext) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyResourceMatcher.getMatchType(" + resource + evalContext + ")"); + } + MatchType ret = MatchType.NONE; + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICY_RESOURCE_MATCHER_MATCH_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICY_RESOURCE_MATCHER_MATCH_LOG, "RangerDefaultPolicyResourceMatcher.getMatchType()"); + } + + if (resource != null && policyResources != null) { + int resourceKeysSize = resource.getKeys() == null ? 0 : resource.getKeys().size(); + + if (policyResources.size() == 0 && resourceKeysSize == 0) { + ret = MatchType.SELF; + } else { + List hierarchy = getMatchingHierarchy(resource); + if (CollectionUtils.isNotEmpty(hierarchy)) { + + int lastNonAnyMatcherIndex = -1; + int matchersSize = 0; + + for (RangerResourceDef resourceDef : hierarchy) { + RangerResourceMatcher matcher = getResourceMatcher(resourceDef.getName()); + if (matcher != null) { + if (!matcher.isMatchAny()) { + lastNonAnyMatcherIndex = matchersSize; + } + matchersSize++; + } else { + break; + } + } + + if (resourceKeysSize == 0) { + ret = MatchType.SELF; + } + + for (RangerResourceDef resourceDef : hierarchy) { + + RangerResourceMatcher matcher = getResourceMatcher(resourceDef.getName()); + Object resourceValue = resource.getValue(resourceDef.getName()); + + if (matcher != null) { + if (resourceValue != null || matcher.isMatchAny()) { + if (matcher.isMatch(resourceValue, evalContext)) { + ret = MatchType.SELF; + } else { + ret = MatchType.NONE; + break; + } + } + } else { + if (resourceValue != null) { + // More resource-values than matchers + ret = MatchType.ANCESTOR; + } + break; + } + } + + if (ret == MatchType.SELF && resourceKeysSize < policyResources.size()) { + // More matchers than resource-values + if (resourceKeysSize > lastNonAnyMatcherIndex) { + // all remaining matchers which matched resource value of null are of type Any + ret = MatchType.SELF_AND_ALL_DESCENDANTS; + } else { + ret = MatchType.DESCENDANT; + } + } + } + } + } + + RangerPerfTracer.log(perf); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyResourceMatcher.getMatchType(" + resource + evalContext + "): " + ret); + } + + return ret; + } + + public static boolean isHierarchyValidForResources(List hierarchy, Map resources) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> isHierarchyValidForResources(" + StringUtils.join(hierarchy, ",") + ")"); + } + boolean ret = true; + + if (hierarchy != null) { + boolean skipped = false; + + for (RangerResourceDef resourceDef : hierarchy) { + String resourceName = resourceDef.getName(); + Object resourceValue = resources.get(resourceName); + + if (resourceValue == null) { + if (!skipped) { + skipped = true; + } + } else { + if (skipped) { + ret = false; + break; + } + } + } + } else { + ret = false; + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== isHierarchyValidForResources(" + StringUtils.join(hierarchy, ",") + ") : " + ret); + } + return ret; + } + + private List getMatchingHierarchy(Set resourceKeys) { + List ret = null; + + if (CollectionUtils.isNotEmpty(resourceKeys) && serviceDefHelper != null) { + Set> resourceHierarchies = serviceDefHelper.getResourceHierarchies(policyType, resourceKeys); + + // pick the shortest hierarchy + for (List resourceHierarchy : resourceHierarchies) { + if (ret == null) { + ret = resourceHierarchy; + } else { + if (resourceHierarchy.size() < ret.size()) { + ret = resourceHierarchy; + if (ret.size() == resourceKeys.size()) { + break; + } + } + } + } + } + + return ret; + } + + private List getMatchingHierarchy(RangerAccessResource resource) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyResourceMatcher.getMatchingHierarchy(" + resource + ")"); + } + + final List ret; + + Set policyResourcesKeySet = policyResources.keySet(); + Set resourceKeySet = resource.getKeys(); + + if (CollectionUtils.isNotEmpty(resourceKeySet)) { + List aValidHierarchy = null; + + if (validResourceHierarchy != null && serviceDefHelper != null) { + if (serviceDefHelper.hierarchyHasAllResources(validResourceHierarchy, resourceKeySet)) { + aValidHierarchy = validResourceHierarchy; + } + } else { + if (policyResourcesKeySet.containsAll(resourceKeySet)) { + aValidHierarchy = getMatchingHierarchy(policyResourcesKeySet); + } else if (resourceKeySet.containsAll(policyResourcesKeySet)) { + aValidHierarchy = getMatchingHierarchy(resourceKeySet); + } + } + ret = isHierarchyValidForResources(aValidHierarchy, resource.getAsMap()) ? aValidHierarchy : null; + } else { + ret = validResourceHierarchy != null ? validResourceHierarchy : getMatchingHierarchy(policyResourcesKeySet); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyResourceMatcher.getMatchingHierarchy(" + resource + "): " + ret); + } + + return ret; + } + + private boolean isMatch(final MatchScope scope, final MatchType matchType) { + final boolean ret; + switch (scope) { + case SELF: { + ret = matchType == MatchType.SELF || matchType == MatchType.SELF_AND_ALL_DESCENDANTS; + break; + } + case ANCESTOR: { + ret = matchType == MatchType.ANCESTOR; + break; + } + case DESCENDANT: { + ret = matchType == MatchType.DESCENDANT; + break; + } + case SELF_OR_ANCESTOR: { + ret = matchType == MatchType.SELF || matchType == MatchType.SELF_AND_ALL_DESCENDANTS || matchType == MatchType.ANCESTOR; + break; + } + case SELF_OR_DESCENDANT: { + ret = matchType == MatchType.SELF || matchType == MatchType.SELF_AND_ALL_DESCENDANTS || matchType == MatchType.DESCENDANT; + break; + } + default: { + ret = matchType != MatchType.NONE; + break; + } + } + return ret; + } + + private static RangerResourceMatcher createResourceMatcher(RangerResourceDef resourceDef, RangerPolicyResource resource) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultPolicyResourceMatcher.createResourceMatcher(" + resourceDef + ", " + resource + ")"); + } + + RangerResourceMatcher ret = null; + + if (resourceDef != null) { + String resName = resourceDef.getName(); + String clsName = resourceDef.getMatcher(); + + if (!StringUtils.isEmpty(clsName)) { + try { + @SuppressWarnings("unchecked") + Class matcherClass = (Class) Class.forName(clsName); + + ret = matcherClass.newInstance(); + } catch (Exception excp) { + LOG.error("failed to instantiate resource matcher '" + clsName + "' for '" + resName + "'. Default resource matcher will be used", excp); + } + } + + + if (ret == null) { + ret = new RangerDefaultResourceMatcher(); + } + + ret.setResourceDef(resourceDef); + ret.setPolicyResource(resource); + ret.init(); + } else { + LOG.error("RangerDefaultPolicyResourceMatcher: RangerResourceDef is null"); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultPolicyResourceMatcher.createResourceMatcher(" + resourceDef + ", " + resource + "): " + ret); + } + + return ret; + } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyresourcematcher/RangerPolicyResourceEvaluator.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyresourcematcher/RangerPolicyResourceEvaluator.java new file mode 100644 index 00000000000..029bd62a95d --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyresourcematcher/RangerPolicyResourceEvaluator.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyresourcematcher; + + +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.resourcematcher.RangerResourceMatcher; + +import java.util.Map; + +public interface RangerPolicyResourceEvaluator { + long getId(); + + String getGuid(); + + RangerPolicyResourceMatcher getPolicyResourceMatcher(); + + Map getPolicyResource(); + + RangerResourceMatcher getResourceMatcher(String resourceName); + + boolean isAncestorOf(RangerServiceDef.RangerResourceDef resourceDef); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java new file mode 100644 index 00000000000..34a64f38041 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/policyresourcematcher/RangerPolicyResourceMatcher.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.policyresourcematcher; + +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyResource; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.validation.RangerServiceDefHelper; +import org.apache.atlas.plugin.policyengine.RangerAccessResource; +import org.apache.atlas.plugin.resourcematcher.RangerResourceMatcher; + +import java.util.Map; + +public interface RangerPolicyResourceMatcher { + enum MatchScope { SELF, SELF_OR_DESCENDANT, SELF_OR_ANCESTOR, DESCENDANT, ANCESTOR, ANY, SELF_AND_ALL_DESCENDANTS} + enum MatchType { NONE, SELF, DESCENDANT, ANCESTOR, SELF_AND_ALL_DESCENDANTS} + + void setServiceDef(RangerServiceDef serviceDef); + + void setPolicy(RangerPolicy policy); + + void setPolicyResources(Map policyResources); + + void setPolicyResources(Map policyResources, String policyType); + + void setServiceDefHelper(RangerServiceDefHelper serviceDefHelper); + + void init(); + + RangerServiceDef getServiceDef(); + + RangerResourceMatcher getResourceMatcher(String resourceName); + + boolean isMatch(RangerAccessResource resource, Map evalContext); + + boolean isMatch(Map resources, Map evalContext); + + boolean isMatch(RangerAccessResource resource, MatchScope scope, Map evalContext); + + boolean isMatch(RangerPolicy policy, MatchScope scope, Map evalContext); + + MatchType getMatchType(RangerAccessResource resource, Map evalContext); + + boolean isCompleteMatch(RangerAccessResource resource, Map evalContext); + + boolean isCompleteMatch(Map resources, Map evalContext); + + boolean getNeedsDynamicEval(); + + StringBuilder toString(StringBuilder sb); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerAbstractResourceMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerAbstractResourceMatcher.java new file mode 100644 index 00000000000..f0b2ff325fa --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerAbstractResourceMatcher.java @@ -0,0 +1,582 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.resourcematcher; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOCase; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyResource; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerResourceDef; +import org.apache.atlas.plugin.util.ServiceDefUtil; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + + +public abstract class RangerAbstractResourceMatcher implements RangerResourceMatcher { + private static final Log LOG = LogFactory.getLog(RangerAbstractResourceMatcher.class); + + public final static String WILDCARD_ASTERISK = "*"; + + public final static String OPTION_IGNORE_CASE = "ignoreCase"; + public final static String OPTION_QUOTED_CASE_SENSITIVE = "quotedCaseSensitive"; + public final static String OPTION_QUOTE_CHARS = "quoteChars"; + public final static String OPTION_WILD_CARD = "wildCard"; + public final static String OPTION_REPLACE_TOKENS = "replaceTokens"; + public final static String OPTION_TOKEN_DELIMITER_START = "tokenDelimiterStart"; + public final static String OPTION_TOKEN_DELIMITER_END = "tokenDelimiterEnd"; + public final static String OPTION_TOKEN_DELIMITER_ESCAPE = "tokenDelimiterEscape"; + public final static String OPTION_TOKEN_DELIMITER_PREFIX = "tokenDelimiterPrefix"; + + protected RangerResourceDef resourceDef; + protected RangerPolicyResource policyResource; + + protected boolean optIgnoreCase; + protected boolean optQuotedCaseSensitive; + protected String optQuoteChars = "\""; + protected boolean optWildCard; + + protected List policyValues; + protected boolean policyIsExcludes; + protected boolean isMatchAny; + protected ResourceMatcherWrapper resourceMatchers; + + protected boolean optReplaceTokens; + protected char startDelimiterChar = '{'; + protected char endDelimiterChar = '}'; + protected char escapeChar = '\\'; + protected String tokenPrefix = ""; + + @Override + public void setResourceDef(RangerResourceDef resourceDef) { + this.resourceDef = resourceDef; + } + + @Override + public void setPolicyResource(RangerPolicyResource policyResource) { + this.policyResource = policyResource; + } + + @Override + public void init() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerAbstractResourceMatcher.init()"); + } + + Map options = resourceDef != null ? resourceDef.getMatcherOptions() : null; + + optIgnoreCase = getOptionIgnoreCase(options); + optQuotedCaseSensitive = getOptionQuotedCaseSensitive(options); + optQuoteChars = getOptionQuoteChars(options); + optWildCard = getOptionWildCard(options); + + policyValues = new ArrayList<>(); + policyIsExcludes = policyResource != null && policyResource.getIsExcludes(); + + if (policyResource != null && policyResource.getValues() != null) { + for (String policyValue : policyResource.getValues()) { + if (StringUtils.isEmpty(policyValue)) { + continue; + } + policyValues.add(policyValue); + } + } + + optReplaceTokens = getOptionReplaceTokens(options); + + if(optReplaceTokens) { + startDelimiterChar = getOptionDelimiterStart(options); + endDelimiterChar = getOptionDelimiterEnd(options); + escapeChar = getOptionDelimiterEscape(options); + tokenPrefix = getOptionDelimiterPrefix(options); + + if(escapeChar == startDelimiterChar || escapeChar == endDelimiterChar || + tokenPrefix.indexOf(escapeChar) != -1 || tokenPrefix.indexOf(startDelimiterChar) != -1 || + tokenPrefix.indexOf(endDelimiterChar) != -1) { + String resouceName = resourceDef == null ? "" : resourceDef.getName(); + + String msg = "Invalid token-replacement parameters for resource '" + resouceName + "': { "; + msg += (OPTION_TOKEN_DELIMITER_START + "='" + startDelimiterChar + "'; "); + msg += (OPTION_TOKEN_DELIMITER_END + "='" + endDelimiterChar + "'; "); + msg += (OPTION_TOKEN_DELIMITER_ESCAPE + "='" + escapeChar + "'; "); + msg += (OPTION_TOKEN_DELIMITER_PREFIX + "='" + tokenPrefix + "' }. "); + msg += "Token replacement disabled"; + + LOG.error(msg); + + optReplaceTokens = false; + } + } + + resourceMatchers = buildResourceMatchers(); + isMatchAny = resourceMatchers == null || CollectionUtils.isEmpty(resourceMatchers.getResourceMatchers()); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerAbstractResourceMatcher.init()"); + } + } + + @Override + public boolean isMatchAny() { return isMatchAny; } + + public boolean getNeedsDynamicEval() { + return resourceMatchers != null && resourceMatchers.getNeedsDynamicEval(); + } + + public static boolean getOptionIgnoreCase(Map options) { + return ServiceDefUtil.getBooleanOption(options, OPTION_IGNORE_CASE, true); + } + + public static boolean getOptionQuotedCaseSensitive(Map options) { + return ServiceDefUtil.getBooleanOption(options, OPTION_QUOTED_CASE_SENSITIVE, false); + } + + public static String getOptionQuoteChars(Map options) { + return ServiceDefUtil.getOption(options, OPTION_QUOTE_CHARS, "\""); + } + + public static boolean getOptionWildCard(Map options) { + return ServiceDefUtil.getBooleanOption(options, OPTION_WILD_CARD, true); + } + + public static boolean getOptionReplaceTokens(Map options) { + return ServiceDefUtil.getBooleanOption(options, OPTION_REPLACE_TOKENS, true); + } + + public static char getOptionDelimiterStart(Map options) { + return ServiceDefUtil.getCharOption(options, OPTION_TOKEN_DELIMITER_START, '{'); + } + + public static char getOptionDelimiterEnd(Map options) { + return ServiceDefUtil.getCharOption(options, OPTION_TOKEN_DELIMITER_END, '}'); + } + + public static char getOptionDelimiterEscape(Map options) { + return ServiceDefUtil.getCharOption(options, OPTION_TOKEN_DELIMITER_ESCAPE, '\\'); + } + + public static String getOptionDelimiterPrefix(Map options) { + return ServiceDefUtil.getOption(options, OPTION_TOKEN_DELIMITER_PREFIX, ""); + } + + protected ResourceMatcherWrapper buildResourceMatchers() { + List resourceMatchers = new ArrayList<>(); + boolean needsDynamicEval = false; + + for (String policyValue : policyValues) { + ResourceMatcher matcher = getMatcher(policyValue); + + if (matcher != null) { + if (matcher.isMatchAny()) { + resourceMatchers.clear(); + break; + } + if (!needsDynamicEval && matcher.getNeedsDynamicEval()) { + needsDynamicEval = true; + } + resourceMatchers.add(matcher); + } + } + + Collections.sort(resourceMatchers, new ResourceMatcher.PriorityComparator()); + + return CollectionUtils.isNotEmpty(resourceMatchers) ? + new ResourceMatcherWrapper(needsDynamicEval, resourceMatchers) : null; + } + + @Override + public boolean isCompleteMatch(String resource, Map evalContext) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerAbstractResourceMatcher.isCompleteMatch(" + resource + ", " + evalContext + ")"); + } + + boolean ret = false; + + if(CollectionUtils.isEmpty(policyValues)) { + ret = StringUtils.isEmpty(resource); + } else if(policyValues.size() == 1) { + String policyValue = policyValues.get(0); + + if(isMatchAny) { + ret = StringUtils.isEmpty(resource) || StringUtils.containsOnly(resource, WILDCARD_ASTERISK); + } else { + ret = optIgnoreCase && !(optQuotedCaseSensitive && ResourceMatcher.startsWithAnyChar(resource, optQuoteChars)) ? StringUtils.equalsIgnoreCase(resource, policyValue) : StringUtils.equals(resource, policyValue); + } + + if(policyIsExcludes) { + ret = !ret; + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerAbstractResourceMatcher.isCompleteMatch(" + resource + ", " + evalContext + "): " + ret); + } + + return ret; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerAbstractResourceMatcher={"); + + sb.append("resourceDef={"); + if(resourceDef != null) { + resourceDef.toString(sb); + } + sb.append("} "); + sb.append("policyResource={"); + if(policyResource != null) { + policyResource.toString(sb); + } + sb.append("} "); + sb.append("optIgnoreCase={").append(optIgnoreCase).append("} "); + sb.append("optQuotedCaseSensitive={").append(optQuotedCaseSensitive).append("} "); + sb.append("optQuoteChars={").append(optQuoteChars).append("} "); + sb.append("optWildCard={").append(optWildCard).append("} "); + + sb.append("policyValues={"); + if(policyValues != null) { + for(String value : policyValues) { + sb.append(value).append(","); + } + } + sb.append("} "); + + sb.append("policyIsExcludes={").append(policyIsExcludes).append("} "); + sb.append("isMatchAny={").append(isMatchAny).append("} "); + + sb.append("options={"); + if(resourceDef != null && resourceDef.getMatcherOptions() != null) { + for(Map.Entry e : resourceDef.getMatcherOptions().entrySet()) { + sb.append(e.getKey()).append("=").append(e.getValue()).append(';'); + } + } + sb.append("} "); + + sb.append("}"); + + return sb; + } + + boolean isAllValuesRequested(Object resource) { + final boolean result; + + if (resource == null) { + result = true; + } else if (resource instanceof String) { + result = StringUtils.isEmpty((String) resource) || WILDCARD_ASTERISK.equals(resource); + } else { // return false for any other type of resourceValue + result = false; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("isAllValuesRequested(" + resource + "): " + result); + } + return result; + } + + /** + * The only case where excludes flag does NOT change the result is the following: + * - Resource denotes all possible values (i.e. resource in (null, "", "*") + * - where as policy does not allow all possible values (i.e. policy.values().contains("*") + * + */ + public boolean applyExcludes(boolean allValuesRequested, boolean resultWithoutExcludes) { + if (!policyIsExcludes) return resultWithoutExcludes; // not an excludes policy! + if (allValuesRequested && !isMatchAny) return resultWithoutExcludes; // one case where excludes has no effect + return !resultWithoutExcludes; // all other cases flip it + } + + ResourceMatcher getMatcher(String policyValue) { + final int len = policyValue != null ? policyValue.length() : 0; + + if (len == 0) { + return null; + } + + final ResourceMatcher ret; + + int wildcardStartIdx = -1; + int wildcardEndIdx = -1; + boolean needWildcardMatch = false; + + // If optWildcard is true + // If ('?' found or non-contiguous '*'s found in policyValue) + // needWildcardMatch = true + // End + // + // wildcardStartIdx is set to index of first '*' in policyValue or -1 if '*' is not found in policyValue, and + // wildcardEndIdx is set to index of last '*' in policyValue or -1 if '*' is not found in policyValue + // Else + // needWildcardMatch is set to false + // End + if (optWildCard) { + for (int i = 0; i < len; i++) { + final char c = policyValue.charAt(i); + + if (c == '?') { + needWildcardMatch = true; + break; + } else if (c == '*') { + if (wildcardEndIdx == -1 || wildcardEndIdx == (i - 1)) { + wildcardEndIdx = i; + if (wildcardStartIdx == -1) { + wildcardStartIdx = i; + } + } else { + needWildcardMatch = true; + break; + } + } + } + } + + if (needWildcardMatch) { // test?, test*a*, test*a*b, *test*a + ret = optIgnoreCase ? (optQuotedCaseSensitive ? new QuotedCaseSensitiveWildcardMatcher(policyValue, optQuoteChars) : new CaseInsensitiveWildcardMatcher(policyValue)) : new CaseSensitiveWildcardMatcher(policyValue); + } else if (wildcardStartIdx == -1) { // test, testa, testab + ret = optIgnoreCase ? (optQuotedCaseSensitive ? new QuotedCaseSensitiveStringMatcher(policyValue, optQuoteChars) : new CaseInsensitiveStringMatcher(policyValue)) : new CaseSensitiveStringMatcher(policyValue); + } else if (wildcardStartIdx == 0) { // *test, **test, *testa, *testab + String matchStr = policyValue.substring(wildcardEndIdx + 1); + ret = optIgnoreCase ? (optQuotedCaseSensitive ? new QuotedCaseSensitiveEndsWithMatcher(matchStr, optQuoteChars) : new CaseInsensitiveEndsWithMatcher(matchStr)) : new CaseSensitiveEndsWithMatcher(matchStr); + } else if (wildcardEndIdx != (len - 1)) { // test*a, test*ab + ret = optIgnoreCase ? (optQuotedCaseSensitive ? new QuotedCaseSensitiveWildcardMatcher(policyValue, optQuoteChars) : new CaseInsensitiveWildcardMatcher(policyValue)) : new CaseSensitiveWildcardMatcher(policyValue); + } else { // test*, test**, testa*, testab* + String matchStr = policyValue.substring(0, wildcardStartIdx); + ret = optIgnoreCase ? (optQuotedCaseSensitive ? new QuotedCaseSensitiveStartsWithMatcher(matchStr, optQuoteChars) : new CaseInsensitiveStartsWithMatcher(matchStr)) : new CaseSensitiveStartsWithMatcher(matchStr); + } + + if(optReplaceTokens) { + ret.setDelimiters(startDelimiterChar, endDelimiterChar, escapeChar, tokenPrefix); + } + + return ret; + } +} + +final class CaseSensitiveStringMatcher extends ResourceMatcher { + CaseSensitiveStringMatcher(String value) { + super(value); + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + return StringUtils.equals(resourceValue, getExpandedValue(evalContext)); + } + int getPriority() { return 1 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);} +} + +final class CaseInsensitiveStringMatcher extends ResourceMatcher { + CaseInsensitiveStringMatcher(String value) { super(value); } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + return StringUtils.equalsIgnoreCase(resourceValue, getExpandedValue(evalContext)); + } + int getPriority() {return 2 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); } +} + +final class QuotedCaseSensitiveStringMatcher extends ResourceMatcher { + private final String quoteChars; + + QuotedCaseSensitiveStringMatcher(String value, String quoteChars) { + super(value); + + this.quoteChars = quoteChars; + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + if (startsWithAnyChar(resourceValue, quoteChars)) { + return StringUtils.equals(resourceValue, getExpandedValue(evalContext)); + } else { + return StringUtils.equalsIgnoreCase(resourceValue, getExpandedValue(evalContext)); + } + } + + int getPriority() {return 2 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); } +} + +final class CaseSensitiveStartsWithMatcher extends ResourceMatcher { + CaseSensitiveStartsWithMatcher(String value) { + super(value); + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + return StringUtils.startsWith(resourceValue, getExpandedValue(evalContext)); + } + int getPriority() { return 3 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);} +} + +final class CaseInsensitiveStartsWithMatcher extends ResourceMatcher { + CaseInsensitiveStartsWithMatcher(String value) { super(value); } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + return StringUtils.startsWithIgnoreCase(resourceValue, getExpandedValue(evalContext)); + } + int getPriority() { return 4 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); } +} + +final class QuotedCaseSensitiveStartsWithMatcher extends ResourceMatcher { + private final String quoteChars; + + QuotedCaseSensitiveStartsWithMatcher(String value, String quoteChars) { + super(value); + + this.quoteChars = quoteChars; + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + if (startsWithAnyChar(resourceValue, quoteChars)) { + return StringUtils.startsWith(resourceValue, getExpandedValue(evalContext)); + } else { + return StringUtils.startsWithIgnoreCase(resourceValue, getExpandedValue(evalContext)); + } + } + + int getPriority() { return 4 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); } +} + +final class CaseSensitiveEndsWithMatcher extends ResourceMatcher { + CaseSensitiveEndsWithMatcher(String value) { + super(value); + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + return StringUtils.endsWith(resourceValue, getExpandedValue(evalContext)); + } + int getPriority() { return 3 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); } +} + +final class CaseInsensitiveEndsWithMatcher extends ResourceMatcher { + CaseInsensitiveEndsWithMatcher(String value) { + super(value); + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + return StringUtils.endsWithIgnoreCase(resourceValue, getExpandedValue(evalContext)); + } + int getPriority() { return 4 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); } +} + +final class QuotedCaseSensitiveEndsWithMatcher extends ResourceMatcher { + private final String quoteChars; + + QuotedCaseSensitiveEndsWithMatcher(String value, String quoteChars) { + super(value); + + this.quoteChars = quoteChars; + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + if (startsWithAnyChar(resourceValue, quoteChars)) { + return StringUtils.endsWith(resourceValue, getExpandedValue(evalContext)); + } else { + return StringUtils.endsWithIgnoreCase(resourceValue, getExpandedValue(evalContext)); + } + } + + int getPriority() { return 4 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); } +} + +final class CaseSensitiveWildcardMatcher extends ResourceMatcher { + CaseSensitiveWildcardMatcher(String value) { + super(value); + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + return FilenameUtils.wildcardMatch(resourceValue, getExpandedValue(evalContext), IOCase.SENSITIVE); + } + int getPriority() { return 5 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); } +} + + +final class CaseInsensitiveWildcardMatcher extends ResourceMatcher { + CaseInsensitiveWildcardMatcher(String value) { + super(value); + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + return FilenameUtils.wildcardMatch(resourceValue, getExpandedValue(evalContext), IOCase.INSENSITIVE); + } + int getPriority() {return 6 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); } +} + +final class QuotedCaseSensitiveWildcardMatcher extends ResourceMatcher { + private final String quoteChars; + + QuotedCaseSensitiveWildcardMatcher(String value, String quoteChars) { + super(value); + + this.quoteChars = quoteChars; + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + IOCase caseSensitivity = startsWithAnyChar(resourceValue, quoteChars) ? IOCase.SENSITIVE : IOCase.INSENSITIVE; + + return FilenameUtils.wildcardMatch(resourceValue, getExpandedValue(evalContext), caseSensitivity); + } + + int getPriority() {return 6 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); } +} + +final class ResourceMatcherWrapper { + private final boolean needsDynamicEval; + private final List resourceMatchers; + + ResourceMatcherWrapper() { + this(false, null); + } + + ResourceMatcherWrapper(boolean needsDynamicEval, List resourceMatchers) { + this.needsDynamicEval = needsDynamicEval; + this.resourceMatchers = resourceMatchers; + } + + boolean getNeedsDynamicEval() { + return needsDynamicEval; + } + + List getResourceMatchers() { + return resourceMatchers; + } +} + diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerDefaultResourceMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerDefaultResourceMatcher.java new file mode 100644 index 00000000000..a9be0dc6612 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerDefaultResourceMatcher.java @@ -0,0 +1,100 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.resourcematcher; + + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.Collection; +import java.util.Map; + + +public class RangerDefaultResourceMatcher extends RangerAbstractResourceMatcher { + private static final Log LOG = LogFactory.getLog(RangerDefaultResourceMatcher.class); + + @Override + public boolean isMatch(Object resource, Map evalContext) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerDefaultResourceMatcher.isMatch(" + resource + ", " + evalContext + ")"); + } + + boolean ret = false; + boolean allValuesRequested = isAllValuesRequested(resource); + + if(allValuesRequested || isMatchAny) { + ret = isMatchAny; + } else { + if (resource instanceof String) { + String strValue = (String) resource; + + for (ResourceMatcher resourceMatcher : resourceMatchers.getResourceMatchers()) { + ret = resourceMatcher.isMatch(strValue, evalContext); + if (ret) { + break; + } + } + } else if (resource instanceof Collection) { + @SuppressWarnings("unchecked") + Collection collValue = (Collection) resource; + + for (ResourceMatcher resourceMatcher : resourceMatchers.getResourceMatchers()) { + ret = resourceMatcher.isMatchAny(collValue, evalContext); + if (ret) { + break; + } + } + } + + } + + ret = applyExcludes(allValuesRequested, ret); + + if (ret == false) { + if(LOG.isDebugEnabled()) { + StringBuilder sb = new StringBuilder(); + sb.append("["); + for (String policyValue: policyValues) { + sb.append(policyValue); + sb.append(" "); + } + sb.append("]"); + + LOG.debug("RangerDefaultResourceMatcher.isMatch returns FALSE, (resource=" + resource + ", policyValues=" + sb.toString() + ")"); + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerDefaultResourceMatcher.isMatch(" + resource + ", " + evalContext + "): " + ret); + } + + return ret; + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerDefaultResourceMatcher={"); + + super.toString(sb); + + sb.append("}"); + + return sb; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerPathResourceMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerPathResourceMatcher.java new file mode 100644 index 00000000000..1c2fd8b2d31 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerPathResourceMatcher.java @@ -0,0 +1,450 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.resourcematcher; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOCase; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.atlas.plugin.util.ServiceDefUtil; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.function.BiFunction; + + +public class RangerPathResourceMatcher extends RangerDefaultResourceMatcher { + private static final Log LOG = LogFactory.getLog(RangerPathResourceMatcher.class); + + public static final String OPTION_PATH_SEPARATOR = "pathSeparatorChar"; + public static final char DEFAULT_PATH_SEPARATOR_CHAR = org.apache.hadoop.fs.Path.SEPARATOR_CHAR; + + private boolean policyIsRecursive; + private Character pathSeparatorChar = '/'; + + @Override + public void init() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerPathResourceMatcher.init()"); + } + + Map options = resourceDef == null ? null : resourceDef.getMatcherOptions(); + + policyIsRecursive = policyResource != null && policyResource.getIsRecursive(); + pathSeparatorChar = ServiceDefUtil.getCharOption(options, OPTION_PATH_SEPARATOR, DEFAULT_PATH_SEPARATOR_CHAR); + + super.init(); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerPathResourceMatcher.init()"); + } + } + + @Override + + protected ResourceMatcherWrapper buildResourceMatchers() { + List resourceMatchers = new ArrayList<>(); + boolean needsDynamicEval = false; + + for (String policyValue : policyValues) { + if (optWildCard && policyIsRecursive) { + if (policyValue.charAt(policyValue.length() - 1) == pathSeparatorChar) { + policyValue += WILDCARD_ASTERISK; + } + } + + ResourceMatcher matcher = getMatcher(policyValue); + + if (matcher != null) { + if (matcher.isMatchAny()) { + resourceMatchers.clear(); + break; + } + if (!needsDynamicEval && matcher.getNeedsDynamicEval()) { + needsDynamicEval = true; + } + resourceMatchers.add(matcher); + } + } + + Collections.sort(resourceMatchers, new ResourceMatcher.PriorityComparator()); + + return CollectionUtils.isNotEmpty(resourceMatchers) ? + new ResourceMatcherWrapper(needsDynamicEval, resourceMatchers) : null; + } + + @Override + ResourceMatcher getMatcher(String policyValue) { + if (!policyIsRecursive) { + return getPathMatcher(policyValue); + } + + final int len = policyValue != null ? policyValue.length() : 0; + + if (len == 0) { + return null; + } + + // To ensure that when policyValue is single '*', ResourceMatcher created here returns true for isMatchAny() + if (optWildCard && WILDCARD_ASTERISK.equals(policyValue)) { + return new CaseInsensitiveStringMatcher(""); + } + + boolean isWildcardPresent = false; + + if (optWildCard) { + for (int i = 0; i < len; i++) { + final char c = policyValue.charAt(i); + + if (c == '?' || c == '*') { + isWildcardPresent = true; + break; + } + } + } + + final ResourceMatcher ret; + + if (isWildcardPresent) { + ret = new RecursiveWildcardResourceMatcher(policyValue, pathSeparatorChar, optIgnoreCase, RangerPathResourceMatcher::isRecursiveWildCardMatch, optIgnoreCase ? 8 : 7); + } else { + ret = new RecursivePathResourceMatcher(policyValue, pathSeparatorChar, optIgnoreCase ? StringUtils::equalsIgnoreCase : StringUtils::equals, optIgnoreCase ? StringUtils::startsWithIgnoreCase : StringUtils::startsWith, optIgnoreCase ? 8 : 7); + } + + if (optReplaceTokens) { + ret.setDelimiters(startDelimiterChar, endDelimiterChar, escapeChar, tokenPrefix); + } + + return ret; + } + + static boolean isRecursiveWildCardMatch(String pathToCheck, String wildcardPath, Character pathSeparatorChar, IOCase caseSensitivity) { + + boolean ret = false; + + if (! StringUtils.isEmpty(pathToCheck)) { + String[] pathElements = StringUtils.split(pathToCheck, pathSeparatorChar); + + if(! ArrayUtils.isEmpty(pathElements)) { + StringBuilder sb = new StringBuilder(); + + if(pathToCheck.charAt(0) == pathSeparatorChar) { + sb.append(pathSeparatorChar); // preserve the initial pathSeparatorChar + } + + for(String p : pathElements) { + sb.append(p); + + ret = FilenameUtils.wildcardMatch(sb.toString(), wildcardPath, caseSensitivity); + + if (ret) { + break; + } + + sb.append(pathSeparatorChar); + } + + sb = null; + } else { // pathToCheck consists of only pathSeparatorChar + ret = FilenameUtils.wildcardMatch(pathToCheck, wildcardPath, caseSensitivity); + } + } + return ret; + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerPathResourceMatcher={"); + + super.toString(sb); + + sb.append("policyIsRecursive={").append(policyIsRecursive).append("} "); + + sb.append("}"); + + return sb; + } + + private ResourceMatcher getPathMatcher(String policyValue) { + final int len = policyValue != null ? policyValue.length() : 0; + + if (len == 0) { + return null; + } + + final ResourceMatcher ret; + + int wildcardStartIdx = -1; + int wildcardEndIdx = -1; + boolean needWildcardMatch = false; + + // If optWildcard is true + // If ('?' found or non-contiguous '*'s found in policyValue) + // needWildcardMatch = true + // End + // + // wildcardStartIdx is set to index of first '*' in policyValue or -1 if '*' is not found in policyValue, and + // wildcardEndIdx is set to index of last '*' in policyValue or -1 if '*' is not found in policyValue + // Else + // needWildcardMatch is set to false + // End + if (optWildCard) { + for (int i = 0; i < len; i++) { + final char c = policyValue.charAt(i); + + if (c == '?') { + needWildcardMatch = true; + break; + } else if (c == '*') { + if (wildcardEndIdx == -1 || wildcardEndIdx == (i - 1)) { + wildcardEndIdx = i; + if (wildcardStartIdx == -1) { + wildcardStartIdx = i; + } + } else { + needWildcardMatch = true; + break; + } + } + } + } + + if (needWildcardMatch) { // test?, test*a*, test*a*b, *test*a + ret = new WildcardResourceMatcher(policyValue, pathSeparatorChar, optIgnoreCase, FilenameUtils::wildcardMatch, 6); + } else if (wildcardStartIdx == -1) { // test, testa, testab + ret = new StringResourceMatcher(policyValue, pathSeparatorChar, optIgnoreCase ? StringUtils::equalsIgnoreCase : StringUtils::equals, optIgnoreCase ? 2 : 1); + } else if (wildcardStartIdx == 0) { // *test, **test, *testa, *testab + String matchStr = policyValue.substring(wildcardEndIdx + 1); + ret = new StringResourceMatcher(matchStr, pathSeparatorChar, optIgnoreCase ? StringUtils::endsWithIgnoreCase : StringUtils::endsWith, optIgnoreCase ? 4 : 3); + } else if (wildcardEndIdx != (len - 1)) { // test*a, test*ab + ret = new WildcardResourceMatcher(policyValue, pathSeparatorChar, optIgnoreCase, FilenameUtils::wildcardMatch, 6); + } else { // test*, test**, testa*, testab* + String matchStr = policyValue.substring(0, wildcardStartIdx); + ret = new StringResourceMatcher(matchStr, pathSeparatorChar, optIgnoreCase ? StringUtils::startsWithIgnoreCase : StringUtils::startsWith, optIgnoreCase ? 4 : 3); + } + + if (optReplaceTokens) { + ret.setDelimiters(startDelimiterChar, endDelimiterChar, escapeChar, tokenPrefix); + } + + return ret; + } + + interface TriFunction { + R apply(T t, U u, V v); + } + + interface QuadFunction { + R apply(T t, U u, V v, W w); + } + + static abstract class PathResourceMatcher extends ResourceMatcher { + final char pathSeparatorChar; + final int priority; + + PathResourceMatcher(String value, char pathSeparatorChar, int priority) { + super(value); + this.pathSeparatorChar = pathSeparatorChar; + this.priority = priority; + } + int getPriority() { + return priority + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0); + } + } + + static class StringResourceMatcher extends PathResourceMatcher { + final BiFunction function; + StringResourceMatcher(String value, char pathSeparatorChar, BiFunction function, int priority) { + super(value, pathSeparatorChar, priority); + this.function = function; + } + @Override + boolean isMatch(String resourceValue, Map evalContext) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> StringResourceMatcher.isMatch(resourceValue=" + resourceValue + ", evalContext=" + evalContext + ")"); + } + String expandedValue = getExpandedValue(evalContext); + boolean ret = function.apply(resourceValue, expandedValue); + if (!ret) { + RangerAccessRequest.ResourceMatchingScope scope = MapUtils.isNotEmpty(evalContext) ? (RangerAccessRequest.ResourceMatchingScope) evalContext.get(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING) : null; + if (scope == RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) { + int lastLevelSeparatorIndex = expandedValue.lastIndexOf(pathSeparatorChar); + if (lastLevelSeparatorIndex != -1) { + String shorterExpandedValue = expandedValue.substring(0, lastLevelSeparatorIndex); + if (resourceValue.charAt(resourceValue.length()-1) == pathSeparatorChar) { + resourceValue = resourceValue.substring(0, resourceValue.length()-1); + } + ret = function.apply(resourceValue, shorterExpandedValue); + } + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== StringResourceMatcher.isMatch(resourceValue=" + resourceValue + ", expandedValue=" + expandedValue + ") : result:[" + ret + "]"); + } + return ret; + } + + } + + static class WildcardResourceMatcher extends PathResourceMatcher { + final TriFunction function; + final IOCase ioCase; + + WildcardResourceMatcher(String value, char pathSeparatorChar, boolean optIgnoreCase, TriFunction function, int priority) { + super(value, pathSeparatorChar, priority); + this.function = function; + this.ioCase = optIgnoreCase ? IOCase.INSENSITIVE : IOCase.SENSITIVE; + } + @Override + boolean isMatch(String resourceValue, Map evalContext) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> WildcardResourceMatcher.isMatch(resourceValue=" + resourceValue + ", evalContext=" + evalContext + ")"); + } + String expandedValue = getExpandedValue(evalContext); + boolean ret = function.apply(resourceValue, expandedValue, ioCase); + if (!ret) { + RangerAccessRequest.ResourceMatchingScope scope = MapUtils.isNotEmpty(evalContext) ? (RangerAccessRequest.ResourceMatchingScope) evalContext.get(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING) : null; + if (scope == RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) { + int lastLevelSeparatorIndex = expandedValue.lastIndexOf(pathSeparatorChar); + if (lastLevelSeparatorIndex != -1) { + String shorterExpandedValue = expandedValue.substring(0, lastLevelSeparatorIndex); + if (resourceValue.charAt(resourceValue.length()-1) == pathSeparatorChar) { + resourceValue = resourceValue.substring(0, resourceValue.length()-1); + } + ret = function.apply(resourceValue, shorterExpandedValue, ioCase); + } + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== WildcardResourceMatcher.isMatch(resourceValue=" + resourceValue + ", expandedValue=" + expandedValue + ") : result:[" + ret + "]"); + } + return ret; + } + } + + static class RecursiveWildcardResourceMatcher extends PathResourceMatcher { + final QuadFunction function; + final IOCase ioCase; + + RecursiveWildcardResourceMatcher(String value, char pathSeparatorChar, boolean optIgnoreCase, QuadFunction function, int priority) { + super(value, pathSeparatorChar, priority); + this.function = function; + this.ioCase = optIgnoreCase ? IOCase.INSENSITIVE : IOCase.SENSITIVE; + } + @Override + boolean isMatch(String resourceValue, Map evalContext) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RecursiveWildcardResourceMatcher.isMatch(resourceValue=" + resourceValue + ", evalContext=" + evalContext + ")"); + } + String expandedValue = getExpandedValue(evalContext); + boolean ret = function.apply(resourceValue, expandedValue, pathSeparatorChar, ioCase); + if (!ret) { + RangerAccessRequest.ResourceMatchingScope scope = MapUtils.isNotEmpty(evalContext) ? (RangerAccessRequest.ResourceMatchingScope) evalContext.get(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING) : null; + if (scope == RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) { + int lastLevelSeparatorIndex = expandedValue.lastIndexOf(pathSeparatorChar); + if (lastLevelSeparatorIndex != -1) { + String shorterExpandedValue = expandedValue.substring(0, lastLevelSeparatorIndex); + if (resourceValue.charAt(resourceValue.length()-1) == pathSeparatorChar) { + resourceValue = resourceValue.substring(0, resourceValue.length()-1); + } + ret = function.apply(resourceValue, shorterExpandedValue, pathSeparatorChar, ioCase); + } + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== RecursiveWildcardResourceMatcher.isMatch(resourceValue=" + resourceValue + ", expandedValue=" + expandedValue + ") : result:[" + ret + "]"); + } + return ret; + } + } + + static class RecursivePathResourceMatcher extends PathResourceMatcher { + String valueWithoutSeparator; + String valueWithSeparator; + + final BiFunction primaryFunction; + final BiFunction fallbackFunction; + + RecursivePathResourceMatcher(String value, char pathSeparatorChar, BiFunction primaryFunction, BiFunction fallbackFunction, int priority) { + super(value, pathSeparatorChar, priority); + this.primaryFunction = primaryFunction; + this.fallbackFunction = fallbackFunction; + } + + String getStringToCompare(String policyValue) { + if (StringUtils.isEmpty(policyValue)) { + return policyValue; + } + return (policyValue.lastIndexOf(pathSeparatorChar) == policyValue.length() - 1) ? + policyValue.substring(0, policyValue.length() - 1) : policyValue; + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RecursivePathResourceMatcher.isMatch(resourceValue=" + resourceValue + ", evalContext=" + evalContext + ")"); + } + final String noSeparator; + if (getNeedsDynamicEval()) { + String expandedPolicyValue = getExpandedValue(evalContext); + noSeparator = expandedPolicyValue != null ? getStringToCompare(expandedPolicyValue) : null; + } else { + if (valueWithoutSeparator == null && value != null) { + valueWithoutSeparator = getStringToCompare(value); + valueWithSeparator = valueWithoutSeparator + pathSeparatorChar; + } + noSeparator = valueWithoutSeparator; + } + + boolean ret = primaryFunction.apply(resourceValue, noSeparator); + + if (!ret && noSeparator != null) { + final String withSeparator = getNeedsDynamicEval() ? noSeparator + pathSeparatorChar : valueWithSeparator; + ret = fallbackFunction.apply(resourceValue, withSeparator); + + if (!ret) { + RangerAccessRequest.ResourceMatchingScope scope = MapUtils.isNotEmpty(evalContext) ? (RangerAccessRequest.ResourceMatchingScope) evalContext.get(RangerAccessRequest.RANGER_ACCESS_REQUEST_SCOPE_STRING) : null; + if (scope == RangerAccessRequest.ResourceMatchingScope.SELF_OR_CHILD) { + final int lastLevelSeparatorIndex = noSeparator.lastIndexOf(pathSeparatorChar); + if (lastLevelSeparatorIndex != -1) { + final String shorterExpandedValue = noSeparator.substring(0, lastLevelSeparatorIndex); + if (resourceValue.charAt(resourceValue.length() - 1) == pathSeparatorChar) { + resourceValue = resourceValue.substring(0, resourceValue.length() - 1); + } + ret = primaryFunction.apply(resourceValue, shorterExpandedValue); + } + } + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== RecursivePathResourceMatcher.isMatch(resourceValue=" + resourceValue + ", expandedValueWithoutTrailingSeparatorChar=" + noSeparator + ") : result:[" + ret + "]"); + } + + return ret; + } + } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerResourceMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerResourceMatcher.java new file mode 100644 index 00000000000..9562bdf0fb6 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerResourceMatcher.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.resourcematcher; + +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyResource; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerResourceDef; + +import java.util.Map; + +public interface RangerResourceMatcher { + void setResourceDef(RangerResourceDef resourceDef); + + void setPolicyResource(RangerPolicyResource policyResource); + + void init(); + + boolean isMatchAny(); + + boolean isMatch(Object resource, Map evalContext); + + boolean isCompleteMatch(String resource, Map evalContext); + + boolean getNeedsDynamicEval(); + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerURLResourceMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerURLResourceMatcher.java new file mode 100644 index 00000000000..ddfda29667a --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/RangerURLResourceMatcher.java @@ -0,0 +1,335 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.resourcematcher; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOCase; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.util.ServiceDefUtil; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +public class RangerURLResourceMatcher extends RangerDefaultResourceMatcher { + private static final Log LOG = LogFactory.getLog(RangerURLResourceMatcher.class); + + public static final String OPTION_PATH_SEPARATOR = "pathSeparatorChar"; + public static final char DEFAULT_PATH_SEPARATOR_CHAR = org.apache.hadoop.fs.Path.SEPARATOR_CHAR; + + boolean policyIsRecursive; + char pathSeparatorChar = DEFAULT_PATH_SEPARATOR_CHAR; + + @Override + public void init() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerURLResourceMatcher.init()"); + } + + Map options = resourceDef == null ? null : resourceDef.getMatcherOptions(); + + policyIsRecursive = policyResource != null && policyResource.getIsRecursive(); + pathSeparatorChar = ServiceDefUtil.getCharOption(options, OPTION_PATH_SEPARATOR, DEFAULT_PATH_SEPARATOR_CHAR); + + super.init(); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerURLResourceMatcher.init()"); + } + } + + @Override + + protected ResourceMatcherWrapper buildResourceMatchers() { + List resourceMatchers = new ArrayList<>(); + boolean needsDynamicEval = false; + + for (String policyValue : policyValues) { + if (optWildCard && policyIsRecursive) { + if (policyValue.charAt(policyValue.length() - 1) == pathSeparatorChar) { + policyValue += WILDCARD_ASTERISK; + } + } + + ResourceMatcher matcher = getMatcher(policyValue); + + if (matcher != null) { + if (matcher.isMatchAny()) { + resourceMatchers.clear(); + break; + } + if (!needsDynamicEval && matcher.getNeedsDynamicEval()) { + needsDynamicEval = true; + } + resourceMatchers.add(matcher); + } + } + + Collections.sort(resourceMatchers, new ResourceMatcher.PriorityComparator()); + + return CollectionUtils.isNotEmpty(resourceMatchers) ? + new ResourceMatcherWrapper(needsDynamicEval, resourceMatchers) : null; + } + + @Override + ResourceMatcher getMatcher(String policyValue) { + if(! policyIsRecursive) { + return super.getMatcher(policyValue); + } + + final int len = policyValue != null ? policyValue.length() : 0; + + if (len == 0) { + return null; + } + + // To ensure that when policyValue is single '*', ResourceMatcher created here returns true for isMatchAny() + if (optWildCard && WILDCARD_ASTERISK.equals(policyValue)) { + return new CaseInsensitiveStringMatcher(""); + } + + boolean isWildcardPresent = false; + + if (optWildCard) { + for (int i = 0; i < len; i++) { + final char c = policyValue.charAt(i); + + if (c == '?' || c == '*') { + isWildcardPresent = true; + break; + } + } + } + + final ResourceMatcher ret; + + if (isWildcardPresent) { + ret = optIgnoreCase ? new CaseInsensitiveURLRecursiveWildcardMatcher(policyValue, pathSeparatorChar) + : new CaseSensitiveURLRecursiveWildcardMatcher(policyValue, pathSeparatorChar); + } else { + ret = optIgnoreCase ? new CaseInsensitiveURLRecursiveMatcher(policyValue, pathSeparatorChar) : new CaseSensitiveURLRecursiveMatcher(policyValue, pathSeparatorChar); + } + + if (optReplaceTokens) { + ret.setDelimiters(startDelimiterChar, endDelimiterChar, escapeChar, tokenPrefix); + } + + return ret; + } + + static boolean isRecursiveWildCardMatch(String pathToCheck, String wildcardPath, char pathSeparatorChar, IOCase caseSensitivity) { + + boolean ret = false; + + String url = StringUtils.trim(pathToCheck); + + if (!StringUtils.isEmpty(url) && isPathURLType(url)) { + String scheme = getScheme(url); + if (StringUtils.isEmpty(scheme)) { + return ret; + } + + String path = getPathWithOutScheme(url); + + String[] pathElements = StringUtils.split(path, pathSeparatorChar); + + if (!ArrayUtils.isEmpty(pathElements)) { + StringBuilder sb = new StringBuilder(); + + sb.append(scheme); + + if (pathToCheck.charAt(0) == pathSeparatorChar) { + sb.append(pathSeparatorChar); // preserve the initial pathSeparatorChar + } + + for (String p : pathElements) { + sb.append(p); + + ret = FilenameUtils.wildcardMatch(sb.toString(), wildcardPath, caseSensitivity); + + if (ret) { + break; + } + + sb.append(pathSeparatorChar); + } + + sb = null; + } else { // pathToCheck consists of only pathSeparatorChar + ret = FilenameUtils.wildcardMatch(pathToCheck, wildcardPath, caseSensitivity); + } + } + + return ret; + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerURLResourceMatcher={"); + + super.toString(sb); + + sb.append("policyIsRecursive={").append(policyIsRecursive).append("} "); + + sb.append("}"); + + return sb; + } + + static boolean isPathURLType(String url) { + + Pattern p1 = Pattern.compile(":/{2}"); + Matcher m1 = p1.matcher(url); + + Pattern p2 = Pattern.compile(":/{3,}"); + Matcher m2 = p2.matcher(url); + + return (m1.find() && !(m2.find())); + } + + + static String getScheme(String url){ + return StringUtils.substring(url,0,(StringUtils.indexOf(url,":") + 3)); + } + + static String getPathWithOutScheme(String url) { + return StringUtils.substring(url,(StringUtils.indexOf(url,":") + 2)); + } +} + +final class CaseSensitiveURLRecursiveWildcardMatcher extends ResourceMatcher { + private final char levelSeparatorChar; + CaseSensitiveURLRecursiveWildcardMatcher(String value, char levelSeparatorChar) { + super(value); + this.levelSeparatorChar = levelSeparatorChar; + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + return RangerURLResourceMatcher.isRecursiveWildCardMatch(resourceValue, getExpandedValue(evalContext), levelSeparatorChar, IOCase.SENSITIVE); + } + int getPriority() { return 7 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);} +} + +final class CaseInsensitiveURLRecursiveWildcardMatcher extends ResourceMatcher { + private final char levelSeparatorChar; + CaseInsensitiveURLRecursiveWildcardMatcher(String value, char levelSeparatorChar) { + super(value); + this.levelSeparatorChar = levelSeparatorChar; + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + return RangerURLResourceMatcher.isRecursiveWildCardMatch(resourceValue, getExpandedValue(evalContext), levelSeparatorChar, IOCase.INSENSITIVE); + } + int getPriority() { return 8 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);} + +} + +abstract class RecursiveMatcher extends ResourceMatcher { + final char levelSeparatorChar; + String valueWithoutSeparator; + String valueWithSeparator; + + RecursiveMatcher(String value, char levelSeparatorChar) { + super(value); + this.levelSeparatorChar = levelSeparatorChar; + } + + String getStringToCompare(String policyValue) { + if (StringUtils.isEmpty(policyValue)) { + return policyValue; + } + return (policyValue.lastIndexOf(levelSeparatorChar) == policyValue.length() - 1) ? + policyValue.substring(0, policyValue.length() - 1) : policyValue; + } +} + +final class CaseSensitiveURLRecursiveMatcher extends RecursiveMatcher { + CaseSensitiveURLRecursiveMatcher(String value, char levelSeparatorChar) { + super(value, levelSeparatorChar); + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + + final String noSeparator; + if (getNeedsDynamicEval()) { + String expandedPolicyValue = getExpandedValue(evalContext); + noSeparator = expandedPolicyValue != null ? getStringToCompare(expandedPolicyValue) : null; + } else { + if (valueWithoutSeparator == null && value != null) { + valueWithoutSeparator = getStringToCompare(value); + valueWithSeparator = valueWithoutSeparator + Character.toString(levelSeparatorChar); + } + noSeparator = valueWithoutSeparator; + } + + boolean ret = StringUtils.equals(resourceValue, noSeparator); + + if (!ret && noSeparator != null) { + final String withSeparator = getNeedsDynamicEval() ? noSeparator + Character.toString(levelSeparatorChar) : valueWithSeparator; + ret = StringUtils.startsWith(resourceValue, withSeparator); + } + + return ret; + } + int getPriority() { return 7 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);} +} + +final class CaseInsensitiveURLRecursiveMatcher extends RecursiveMatcher { + CaseInsensitiveURLRecursiveMatcher(String value, char levelSeparatorChar) { + super(value, levelSeparatorChar); + } + + @Override + boolean isMatch(String resourceValue, Map evalContext) { + + final String noSeparator; + if (getNeedsDynamicEval()) { + String expandedPolicyValue = getExpandedValue(evalContext); + noSeparator = expandedPolicyValue != null ? getStringToCompare(expandedPolicyValue) : null; + } else { + if (valueWithoutSeparator == null && value != null) { + valueWithoutSeparator = getStringToCompare(value); + valueWithSeparator = valueWithoutSeparator + Character.toString(levelSeparatorChar); + } + noSeparator = valueWithoutSeparator; + } + + boolean ret = StringUtils.equalsIgnoreCase(resourceValue, noSeparator); + + if (!ret && noSeparator != null) { + final String withSeparator = getNeedsDynamicEval() ? noSeparator + Character.toString(levelSeparatorChar) : valueWithSeparator; + ret = StringUtils.startsWithIgnoreCase(resourceValue, withSeparator); + } + + return ret; + } + + int getPriority() { return 8 + (getNeedsDynamicEval() ? DYNAMIC_EVALUATION_PENALTY : 0);} +} \ No newline at end of file diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ResourceMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ResourceMatcher.java new file mode 100644 index 00000000000..f23667a5f1b --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ResourceMatcher.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.resourcematcher; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.util.StringTokenReplacer; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Comparator; +import java.util.Map; + +abstract class ResourceMatcher { + private static final Log LOG = LogFactory.getLog(ResourceMatcher.class); + + protected final String value; + protected StringTokenReplacer tokenReplacer; + + static final int DYNAMIC_EVALUATION_PENALTY = 8; + + ResourceMatcher(String value) { this.value = value; } + + abstract boolean isMatch(String resourceValue, Map evalContext); + abstract int getPriority(); + + boolean isMatchAny() { return value != null && value.length() == 0; } + + boolean getNeedsDynamicEval() { + return tokenReplacer != null; + } + + public boolean isMatchAny(Collection resourceValues, Map evalContext) { + if (resourceValues != null) { + for (String resourceValue : resourceValues) { + if (isMatch(resourceValue, evalContext)) { + return true; + } + } + } + + return false; + } + + @Override + public String toString() { + return this.getClass().getName() + "(" + this.value + ")"; + } + + void setDelimiters(char startDelimiterChar, char endDelimiterChar, char escapeChar, String tokenPrefix) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> setDelimiters(value= " + value + ", startDelimiter=" + startDelimiterChar + + ", endDelimiter=" + endDelimiterChar + ", escapeChar=" + escapeChar + ", prefix=" + tokenPrefix); + } + + if(value != null && (value.indexOf(escapeChar) != -1 || (value.indexOf(startDelimiterChar) != -1 && value.indexOf(endDelimiterChar) != -1))) { + tokenReplacer = new StringTokenReplacer(startDelimiterChar, endDelimiterChar, escapeChar, tokenPrefix); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== setDelimiters(value= " + value + ", startDelimiter=" + startDelimiterChar + + ", endDelimiter=" + endDelimiterChar + ", escapeChar=" + escapeChar + ", prefix=" + tokenPrefix); + } + } + + String getExpandedValue(Map evalContext) { + final String ret; + + if(tokenReplacer != null) { + ret = tokenReplacer.replaceTokens(value, evalContext); + } else { + ret = value; + } + + return ret; + } + + public static boolean startsWithAnyChar(String value, String startChars) { + boolean ret = false; + + if (value != null && value.length() > 0 && startChars != null) { + ret = StringUtils.contains(startChars, value.charAt(0)); + } + + return ret; + } + + public static class PriorityComparator implements Comparator, Serializable { + @Override + public int compare(ResourceMatcher me, ResourceMatcher other) { + return Integer.compare(me.getPriority(), other.getPriority()); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ScheduledTimeAlwaysMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ScheduledTimeAlwaysMatcher.java new file mode 100644 index 00000000000..01d52bed72b --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ScheduledTimeAlwaysMatcher.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.resourcematcher; + +public class ScheduledTimeAlwaysMatcher implements ScheduledTimeMatcher { + @Override + public boolean isMatch(int currentTime) { + return true; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ScheduledTimeExactMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ScheduledTimeExactMatcher.java new file mode 100644 index 00000000000..4160c605dca --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ScheduledTimeExactMatcher.java @@ -0,0 +1,32 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.resourcematcher; + +public class ScheduledTimeExactMatcher implements ScheduledTimeMatcher { + private int scheduledTime; + + public ScheduledTimeExactMatcher(int scheduledTime) { + this.scheduledTime = scheduledTime; + } + @Override + public boolean isMatch(int currentTime) { + return currentTime == scheduledTime; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ScheduledTimeMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ScheduledTimeMatcher.java new file mode 100644 index 00000000000..1553a1c4932 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ScheduledTimeMatcher.java @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.resourcematcher; + +public interface ScheduledTimeMatcher { + boolean isMatch(int targetTime); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ScheduledTimeRangeMatcher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ScheduledTimeRangeMatcher.java new file mode 100644 index 00000000000..06487e5d2fe --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/resourcematcher/ScheduledTimeRangeMatcher.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.resourcematcher; + +public class ScheduledTimeRangeMatcher implements ScheduledTimeMatcher { + private int lowerBound; + private int upperBound; + + public ScheduledTimeRangeMatcher(int lowerBound, int upperBound) { + this.lowerBound = lowerBound; + this.upperBound = upperBound; + } + @Override + public boolean isMatch(int currentTime) { + return currentTime >= lowerBound && currentTime <= upperBound; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerAuthContext.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerAuthContext.java new file mode 100644 index 00000000000..092c3455339 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerAuthContext.java @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.service; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.atlas.plugin.contextenricher.RangerContextEnricher; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngine; +import org.apache.atlas.plugin.util.RangerRoles; +import org.apache.atlas.plugin.util.RangerRolesUtil; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +public class RangerAuthContext { + private final Map requestContextEnrichers; + private RangerRolesUtil rolesUtil; + + + public RangerAuthContext(Map requestContextEnrichers, RangerRoles roles) { + this.requestContextEnrichers = requestContextEnrichers != null ? requestContextEnrichers : new ConcurrentHashMap<>(); + + setRoles(roles); + } + + public Map getRequestContextEnrichers() { + return requestContextEnrichers; + } + + public void addOrReplaceRequestContextEnricher(RangerContextEnricher enricher, Object database) { + // concurrentHashMap does not allow null to be inserted into it, so insert a dummy which is checked + // when enrich() is called + requestContextEnrichers.put(enricher, database != null ? database : enricher); + } + + public void cleanupRequestContextEnricher(RangerContextEnricher enricher) { + requestContextEnrichers.remove(enricher); + } + + public void setRoles(RangerRoles roles) { + this.rolesUtil = roles != null ? new RangerRolesUtil(roles) : new RangerRolesUtil(null); + } + + public Set getRolesForUserAndGroups(String user, Set groups) { + RangerRolesUtil rolesUtil = this.rolesUtil; + Map> userRoleMapping = rolesUtil.getUserRoleMapping(); + Map> groupRoleMapping = rolesUtil.getGroupRoleMapping(); + Set allRoles = new HashSet<>(); + + if (MapUtils.isNotEmpty(userRoleMapping) && StringUtils.isNotEmpty(user)) { + Set userRoles = userRoleMapping.get(user); + + if (CollectionUtils.isNotEmpty(userRoles)) { + allRoles.addAll(userRoles); + } + } + + if (MapUtils.isNotEmpty(groupRoleMapping)) { + if (CollectionUtils.isNotEmpty(groups)) { + for (String group : groups) { + Set groupRoles = groupRoleMapping.get(group); + + if (CollectionUtils.isNotEmpty(groupRoles)) { + allRoles.addAll(groupRoles); + } + } + } + + Set publicGroupRoles = groupRoleMapping.get(RangerPolicyEngine.GROUP_PUBLIC); + + if (CollectionUtils.isNotEmpty(publicGroupRoles)) { + allRoles.addAll(publicGroupRoles); + } + } + + return allRoles; + } + + public long getRoleVersion() { return this.rolesUtil.getRoleVersion(); } + + public RangerRolesUtil getRangerRolesUtil() { + return this.rolesUtil; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerAuthContextListener.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerAuthContextListener.java new file mode 100644 index 00000000000..20f608418d1 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerAuthContextListener.java @@ -0,0 +1,25 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.service; + + +public interface RangerAuthContextListener { + void contextChanged(); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerBasePlugin.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerBasePlugin.java new file mode 100644 index 00000000000..15ec7f974fc --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerBasePlugin.java @@ -0,0 +1,778 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.service; + +import org.apache.atlas.authorizer.store.PoliciesStore; +import org.apache.atlas.authorizer.store.UsersStore; +import org.apache.atlas.type.AtlasTypeRegistry; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.audit.provider.AuditHandler; +import org.apache.atlas.audit.provider.AuditProviderFactory; +import org.apache.atlas.authorization.config.RangerPluginConfig; +import org.apache.atlas.authorization.utils.RangerUtil; +import org.apache.atlas.plugin.conditionevaluator.RangerScriptExecutionContext; +import org.apache.atlas.plugin.contextenricher.RangerContextEnricher; +import org.apache.atlas.plugin.contextenricher.RangerTagEnricher; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.atlas.plugin.policyengine.RangerAccessResult; +import org.apache.atlas.plugin.policyengine.RangerAccessResultProcessor; +import org.apache.atlas.plugin.policyengine.RangerPluginContext; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngine; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngineImpl; +import org.apache.atlas.plugin.policyengine.RangerResourceACLs; +import org.apache.atlas.plugin.policyevaluator.RangerPolicyEvaluator; +import org.apache.atlas.plugin.store.ServiceDefsUtil; +import org.apache.atlas.plugin.util.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + + +public class RangerBasePlugin { + private static final Log LOG = LogFactory.getLog(RangerBasePlugin.class); + + private final RangerPluginConfig pluginConfig; + private final RangerPluginContext pluginContext; + private final Map logHistoryList = new Hashtable<>(); + private final int logInterval = 30000; // 30 seconds + private final DownloadTrigger accessTrigger = new DownloadTrigger(); + private PolicyRefresher refresher; + private RangerPolicyEngine policyEngine; + private RangerAuthContext currentAuthContext; + private RangerAccessResultProcessor resultProcessor; + private RangerRoles roles; + private RangerUserStore userStore; + private final List chainedPlugins; + private AtlasTypeRegistry typeRegistry = null; + private final UsersStore usersStore; + private final PoliciesStore policiesStore; + + + public RangerBasePlugin(String serviceType, String appId) { + this(new RangerPluginConfig(serviceType, null, appId, null, null, null)); + } + + public RangerBasePlugin(String serviceType, String serviceName, String appId) { + this(new RangerPluginConfig(serviceType, serviceName, appId, null, null, null)); + } + + public RangerBasePlugin(String serviceType, String serviceName, AtlasTypeRegistry typeRegistry) { + this(new RangerPluginConfig(serviceType, serviceName, null, null, null, null)); + this.typeRegistry = typeRegistry; + } + + public RangerBasePlugin(RangerPluginConfig pluginConfig) { + this.pluginConfig = pluginConfig; + this.pluginContext = new RangerPluginContext(pluginConfig); + this.usersStore = UsersStore.getInstance(); + this.policiesStore = PoliciesStore.getInstance(); + + Set superUsers = toSet(pluginConfig.get(pluginConfig.getPropertyPrefix() + ".super.users")); + Set superGroups = toSet(pluginConfig.get(pluginConfig.getPropertyPrefix() + ".super.groups")); + Set auditExcludeUsers = toSet(pluginConfig.get(pluginConfig.getPropertyPrefix() + ".audit.exclude.users")); + Set auditExcludeGroups = toSet(pluginConfig.get(pluginConfig.getPropertyPrefix() + ".audit.exclude.groups")); + Set auditExcludeRoles = toSet(pluginConfig.get(pluginConfig.getPropertyPrefix() + ".audit.exclude.roles")); + Set serviceAdmins = toSet(pluginConfig.get(pluginConfig.getPropertyPrefix() + ".service.admins")); + + setSuperUsersAndGroups(superUsers, superGroups); + setAuditExcludedUsersGroupsRoles(auditExcludeUsers, auditExcludeGroups, auditExcludeRoles); + setIsFallbackSupported(pluginConfig.getBoolean(pluginConfig.getPropertyPrefix() + ".is.fallback.supported", false)); + setServiceAdmins(serviceAdmins); + + RangerScriptExecutionContext.init(pluginConfig); + + this.chainedPlugins = initChainedPlugins(); + } + + public static AuditHandler getAuditProvider(String serviceName) { + AuditProviderFactory providerFactory = RangerBasePlugin.getAuditProviderFactory(serviceName); + AuditHandler ret = providerFactory.getAuditProvider(); + + return ret; + } + + public String getServiceType() { + return pluginConfig.getServiceType(); + } + + public String getAppId() { + return pluginConfig.getAppId(); + } + + public RangerPluginConfig getConfig() { + return pluginConfig; + } + + public String getClusterName() { + return pluginConfig.getClusterName(); + } + + public RangerPluginContext getPluginContext() { + return pluginContext; + } + + public RangerAuthContext getCurrentRangerAuthContext() { return currentAuthContext; } + + public List getChainedPlugins() { return chainedPlugins; } + + // For backward compatibility + public RangerAuthContext createRangerAuthContext() { return currentAuthContext; } + + public RangerRoles getRoles() { + return this.roles; + } + + public void setRoles(RangerRoles roles) { + this.roles = roles; + this.usersStore.setAllRoles(roles); + + RangerPolicyEngine policyEngine = this.policyEngine; + + if (policyEngine != null) { + policyEngine.setRoles(roles); + } + + pluginContext.notifyAuthContextChanged(); + } + + public RangerUserStore getUserStore() { + return this.userStore; + } + + public void setUserStore(RangerUserStore userStore) { + this.userStore = userStore; + this.usersStore.setUserStore(userStore); + } + + public void setAuditExcludedUsersGroupsRoles(Set users, Set groups, Set roles) { + pluginConfig.setAuditExcludedUsersGroupsRoles(users, groups, roles); + } + + public void setSuperUsersAndGroups(Set users, Set groups) { + pluginConfig.setSuperUsersGroups(users, groups); + } + + public void setIsFallbackSupported(boolean isFallbackSupported) { + pluginConfig.setIsFallbackSupported(isFallbackSupported); + } + + public void setServiceAdmins(Set users) { + pluginConfig.setServiceAdmins(users); + } + + public RangerServiceDef getServiceDef() { + RangerPolicyEngine policyEngine = this.policyEngine; + + return policyEngine != null ? policyEngine.getServiceDef() : null; + } + + public int getServiceDefId() { + RangerServiceDef serviceDef = getServiceDef(); + + return serviceDef != null && serviceDef.getId() != null ? serviceDef.getId().intValue() : -1; + } + + public String getServiceName() { + return pluginConfig.getServiceName(); + } + + public AtlasTypeRegistry getTypeRegistry() { + return typeRegistry; + } + + public void setTypeRegistry(AtlasTypeRegistry typeRegistry) { + this.typeRegistry = typeRegistry; + } + + public void init() { + cleanup(); + + AuditProviderFactory providerFactory = AuditProviderFactory.getInstance(); + + if (!providerFactory.isInitDone()) { + if (pluginConfig.getProperties() != null) { + providerFactory.init(pluginConfig.getProperties(), getAppId()); + } else { + LOG.error("Audit subsystem is not initialized correctly. Please check audit configuration. "); + LOG.error("No authorization audits will be generated. "); + } + } + + if (!pluginConfig.getPolicyEngineOptions().disablePolicyRefresher) { + refresher = new PolicyRefresher(this); + LOG.info("Created PolicyRefresher Thread(" + refresher.getName() + ")"); + refresher.setDaemon(true); + refresher.startRefresher(); + } + + for (RangerChainedPlugin chainedPlugin : chainedPlugins) { + chainedPlugin.init(); + } + } + + public long getPoliciesVersion() { + RangerPolicyEngine policyEngine = this.policyEngine; + Long ret = policyEngine != null ? policyEngine.getPolicyVersion() : null; + + return ret != null ? ret : -1L; + } + + public long getTagsVersion() { + RangerTagEnricher tagEnricher = getTagEnricher(); + Long ret = tagEnricher != null ? tagEnricher.getServiceTagsVersion() : null; + + return ret != null ? ret : -1L; + } + + public long getRolesVersion() { + RangerPolicyEngine policyEngine = this.policyEngine; + Long ret = policyEngine != null ? policyEngine.getRoleVersion() : null; + + return ret != null ? ret : -1L; + } + + public void setPolicies(ServicePolicies policies) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> setPolicies(" + policies + ")"); + } + + // guard against catastrophic failure during policy engine Initialization or + try { + RangerPolicyEngine oldPolicyEngine = this.policyEngine; + ServicePolicies servicePolicies = null; + boolean isNewEngineNeeded = true; + boolean usePolicyDeltas = false; + + if (policies == null) { + policies = getDefaultSvcPolicies(); + + if (policies == null) { + LOG.error("Could not get default Service Policies. Keeping old policy-engine!"); + isNewEngineNeeded = false; + } + } else { + Boolean hasPolicyDeltas = RangerPolicyDeltaUtil.hasPolicyDeltas(policies); + + if (hasPolicyDeltas == null) { + LOG.info("Downloaded policies do not require policy change !! [" + (policies.getPolicies() != null ? policies.getPolicies().size() : 0) + "]"); + + if (this.policyEngine == null) { + + LOG.info("There are no material changes, and current policy-engine is null! Creating a policy-engine with default service policies"); + ServicePolicies defaultSvcPolicies = getDefaultSvcPolicies(); + + if (defaultSvcPolicies == null) { + LOG.error("Could not get default Service Policies. Keeping old policy-engine! This is a FATAL error as the old policy-engine is null!"); + isNewEngineNeeded = false; + throw new RuntimeException("PolicyRefresher("+policies.getServiceName()+").setPolicies: fetched service policies contains no policies or delta and current policy engine is null"); + } else { + defaultSvcPolicies.setPolicyVersion(policies.getPolicyVersion()); + policies = defaultSvcPolicies; + isNewEngineNeeded = true; + } + } else { + LOG.info("Keeping old policy-engine!"); + isNewEngineNeeded = false; + } + } else { + if (hasPolicyDeltas.equals(Boolean.TRUE)) { + // Rebuild policies from deltas + RangerPolicyEngineImpl policyEngine = (RangerPolicyEngineImpl) oldPolicyEngine; + + servicePolicies = ServicePolicies.applyDelta(policies, policyEngine); + + if (servicePolicies != null) { + usePolicyDeltas = true; + } else { + LOG.error("Could not apply deltas=" + Arrays.toString(policies.getPolicyDeltas().toArray())); + LOG.warn("Keeping old policy-engine!"); + isNewEngineNeeded = false; + } + } else { + if (policies.getPolicies() == null) { + policies.setPolicies(new ArrayList<>()); + } + } + } + } + + if (isNewEngineNeeded) { + RangerPolicyEngine newPolicyEngine = null; + boolean isPolicyEngineShared = false; + + if (!usePolicyDeltas) { + if (LOG.isDebugEnabled()) { + LOG.debug("Creating engine from policies"); + } + + newPolicyEngine = new RangerPolicyEngineImpl(policies, pluginContext, roles); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("policy-deltas are not null"); + } + + if (CollectionUtils.isNotEmpty(policies.getPolicyDeltas()) || MapUtils.isNotEmpty(policies.getSecurityZones())) { + if (LOG.isDebugEnabled()) { + LOG.debug("Non empty policy-deltas found. Cloning engine using policy-deltas"); + } + + if (oldPolicyEngine != null) { + // Create new evaluator for the updated policies + newPolicyEngine = new RangerPolicyEngineImpl(servicePolicies, pluginContext, roles); + } + + if (newPolicyEngine != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Applied policyDeltas=" + Arrays.toString(policies.getPolicyDeltas().toArray()) + ")"); + } + + isPolicyEngineShared = true; + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Failed to apply policyDeltas=" + Arrays.toString(policies.getPolicyDeltas().toArray()) + "), Creating engine from policies"); + LOG.debug("Creating new engine from servicePolicies:[" + servicePolicies + "]"); + } + + newPolicyEngine = new RangerPolicyEngineImpl(servicePolicies, pluginContext, roles); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Empty policy-deltas. No need to change policy engine"); + } + } + } + + if (newPolicyEngine != null) { + if (!isPolicyEngineShared) { + newPolicyEngine.setUseForwardedIPAddress(pluginConfig.isUseForwardedIPAddress()); + newPolicyEngine.setTrustedProxyAddresses(pluginConfig.getTrustedProxyAddresses()); + } + + this.policyEngine = newPolicyEngine; + this.currentAuthContext = pluginContext.getAuthContext(); + + pluginContext.notifyAuthContextChanged(); + + if (oldPolicyEngine != null && oldPolicyEngine != newPolicyEngine) { + ((RangerPolicyEngineImpl) oldPolicyEngine).releaseResources(!isPolicyEngineShared); + } + + if (this.refresher != null) { + this.refresher.saveToCache(usePolicyDeltas ? servicePolicies : policies); + } + LOG.info("New RangerPolicyEngine created with policy count:"+ (usePolicyDeltas? servicePolicies.getPolicies().size() : policies.getPolicies().size())); + + List abacPolicies = policies.getAbacPolicies() != null ? policies.getAbacPolicies().getPolicies() : new ArrayList<>(); + if (usePolicyDeltas) { + abacPolicies = servicePolicies.getAbacPolicies() != null ? servicePolicies.getAbacPolicies().getPolicies() : new ArrayList<>(); + } + this.policiesStore.setAbacPolicies(abacPolicies); + this.policiesStore.setResourcePolicies(this.policyEngine.getResourcePolicies()); + this.policiesStore.setTagPolicies(this.policyEngine.getTagPolicies()); + LOG.info("PolicyRefresher: ABAC_AUTH: abac policies set: " + abacPolicies.size()); + } + + } else { + LOG.warn("Leaving current policy engine as-is"); + LOG.warn("Policies are not saved to cache. policyVersion in the policy-cache may be different than in Ranger-admin, even though the policies are the same!"); + LOG.warn("Ranger-PolicyVersion:[" + (policies != null ? policies.getPolicyVersion() : -1L) + "], Cached-PolicyVersion:[" + (this.policyEngine != null ? this.policyEngine.getPolicyVersion() : -1L) + "]"); + } + + } catch (Exception e) { + LOG.error("setPolicies: Failed to set policies, didn't set policies", e); + throw e; + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== setPolicies(" + policies + ")"); + } + } + + public void cleanup() { + PolicyRefresher refresher = this.refresher; + this.refresher = null; + + RangerPolicyEngine policyEngine = this.policyEngine; + this.policyEngine = null; + + if (refresher != null) { + refresher.stopRefresher(); + } + + if (policyEngine != null) { + ((RangerPolicyEngineImpl) policyEngine).releaseResources(true); + } + } + + public void setResultProcessor(RangerAccessResultProcessor resultProcessor) { + this.resultProcessor = resultProcessor; + } + + public RangerAccessResult isAccessAllowed(RangerAccessRequest request) { + return isAccessAllowed(request, resultProcessor); + } + + public Collection isAccessAllowed(Collection requests) { + return isAccessAllowed(requests, resultProcessor); + } + + public RangerAccessResult isAccessAllowed(RangerAccessRequest request, RangerAccessResultProcessor resultProcessor) { + RangerAccessResult ret = null; + RangerPolicyEngine policyEngine = this.policyEngine; + + if (policyEngine != null) { + ret = policyEngine.evaluatePolicies(request, RangerPolicy.POLICY_TYPE_ACCESS, null); + } + + if (ret != null) { + for (RangerChainedPlugin chainedPlugin : chainedPlugins) { + RangerAccessResult chainedResult = chainedPlugin.isAccessAllowed(request); + + if (chainedResult != null) { + updateResultFromChainedResult(ret, chainedResult); + } + } + + } + + if (policyEngine != null) { + policyEngine.evaluateAuditPolicies(ret); + } + + if (resultProcessor != null) { + resultProcessor.processResult(ret); + } + + return ret; + } + + public Collection isAccessAllowed(Collection requests, RangerAccessResultProcessor resultProcessor) { + Collection ret = null; + RangerPolicyEngine policyEngine = this.policyEngine; + + if (policyEngine != null) { + ret = policyEngine.evaluatePolicies(requests, RangerPolicy.POLICY_TYPE_ACCESS, null); + } + + if (CollectionUtils.isNotEmpty(ret)) { + for (RangerChainedPlugin chainedPlugin : chainedPlugins) { + Collection chainedResults = chainedPlugin.isAccessAllowed(requests); + + if (CollectionUtils.isNotEmpty(chainedResults)) { + Iterator iterRet = ret.iterator(); + Iterator iterChainedResults = chainedResults.iterator(); + + while (iterRet.hasNext() && iterChainedResults.hasNext()) { + RangerAccessResult result = iterRet.next(); + RangerAccessResult chainedResult = iterChainedResults.next(); + + if (result != null && chainedResult != null) { + updateResultFromChainedResult(result, chainedResult); + } + } + } + } + } + + if (policyEngine != null && CollectionUtils.isNotEmpty(ret)) { + for (RangerAccessResult result : ret) { + policyEngine.evaluateAuditPolicies(result); + } + } + + if (resultProcessor != null) { + resultProcessor.processResults(ret); + } + + return ret; + } + + public RangerAccessResult getAssetAccessors(RangerAccessRequest request) { + RangerAccessResult ret = null; + RangerPolicyEngine policyEngine = this.policyEngine; + + if (policyEngine != null) { + ret = policyEngine.evaluatePolicies(request, RangerPolicy.POLICY_TYPE_ACCESS, null); + } + + return ret; + } + + public RangerAccessResult evalDataMaskPolicies(RangerAccessRequest request, RangerAccessResultProcessor resultProcessor) { + RangerPolicyEngine policyEngine = this.policyEngine; + RangerAccessResult ret = null; + + if(policyEngine != null) { + ret = policyEngine.evaluatePolicies(request, RangerPolicy.POLICY_TYPE_DATAMASK, resultProcessor); + + policyEngine.evaluateAuditPolicies(ret); + } + + return ret; + } + + public RangerAccessResult evalRowFilterPolicies(RangerAccessRequest request, RangerAccessResultProcessor resultProcessor) { + RangerPolicyEngine policyEngine = this.policyEngine; + RangerAccessResult ret = null; + + if(policyEngine != null) { + ret = policyEngine.evaluatePolicies(request, RangerPolicy.POLICY_TYPE_ROWFILTER, resultProcessor); + + policyEngine.evaluateAuditPolicies(ret); + } + + return ret; + } + + public Set getRolesFromUserAndGroups(String user, Set groups) { + RangerPolicyEngine policyEngine = this.policyEngine; + + if(policyEngine != null) { + return policyEngine.getRolesFromUserAndGroups(user, groups); + } + + return null; + } + + private RangerServiceDef getDefaultServiceDef() { + RangerServiceDef ret = null; + + if (StringUtils.isNotBlank(getServiceType())) { + try { + ret = ServiceDefsUtil.instance().getEmbeddedServiceDef(getServiceType()); + } catch (Exception exp) { + LOG.error("Could not get embedded service-def for " + getServiceType()); + } + } + return ret; + } + + private ServicePolicies getDefaultSvcPolicies() { + ServicePolicies ret = null; + RangerServiceDef serviceDef = getServiceDef(); + + if (serviceDef == null) { + serviceDef = getDefaultServiceDef(); + } + + if (serviceDef != null) { + ret = new ServicePolicies(); + + ret.setServiceDef(serviceDef); + ret.setServiceName(getServiceName()); + ret.setPolicies(new ArrayList()); + } + + return ret; + } + + private Set toSet(String value) { + return StringUtils.isNotBlank(value) ? RangerUtil.toSet(value) : Collections.emptySet(); + } + + static private final class LogHistory { + long lastLogTime; + int counter; + } + + public RangerTagEnricher getTagEnricher() { + RangerTagEnricher ret = null; + RangerAuthContext authContext = getCurrentRangerAuthContext(); + + if (authContext != null) { + Map contextEnricherMap = authContext.getRequestContextEnrichers(); + + if (MapUtils.isNotEmpty(contextEnricherMap)) { + Set contextEnrichers = contextEnricherMap.keySet(); + + for (RangerContextEnricher enricher : contextEnrichers) { + if (enricher instanceof RangerTagEnricher) { + ret = (RangerTagEnricher) enricher; + + break; + } + } + } + } + return ret; + } + + private List initChainedPlugins() { + List ret = new ArrayList<>(); + String chainedServicePropPrefix = pluginConfig.getPropertyPrefix() + ".chained.services"; + + for (String chainedService : RangerUtil.toList(pluginConfig.get(chainedServicePropPrefix))) { + if (StringUtils.isBlank(chainedService)) { + continue; + } + + String className = pluginConfig.get(chainedServicePropPrefix + "." + chainedService + ".impl"); + + if (StringUtils.isBlank(className)) { + LOG.error("Ignoring chained service " + chainedService + ": no impl class specified"); + + continue; + } + + try { + @SuppressWarnings("unchecked") + Class pluginClass = (Class) Class.forName(className); + RangerChainedPlugin chainedPlugin = pluginClass.getConstructor(RangerBasePlugin.class, String.class).newInstance(this, chainedService); + + ret.add(chainedPlugin); + } catch (Throwable t) { + LOG.error("initChainedPlugins(): error instantiating plugin impl " + className, t); + } + } + + return ret; + } + + private void updateResultFromChainedResult(RangerAccessResult result, RangerAccessResult chainedResult) { + boolean overrideResult = false; + + if (chainedResult.getIsAccessDetermined()) { // only if chained-result is definitive + // override if result is not definitive or chained-result is by a higher priority policy + overrideResult = !result.getIsAccessDetermined() || chainedResult.getPolicyPriority() > result.getPolicyPriority(); + + if (!overrideResult) { + // override if chained-result is from the same policy priority, and if denies access + if (chainedResult.getPolicyPriority() == result.getPolicyPriority() && !chainedResult.getIsAllowed()) { + // let's not override if result is already denied + if (result.getIsAllowed()) { + overrideResult = true; + } + } + } + } + + if (overrideResult) { + result.setIsAllowed(chainedResult.getIsAllowed()); + result.setIsAccessDetermined(chainedResult.getIsAccessDetermined()); + result.setPolicyId(chainedResult.getPolicyId()); + result.setPolicyVersion(chainedResult.getPolicyVersion()); + result.setPolicyPriority(chainedResult.getPolicyPriority()); + result.setZoneName(chainedResult.getZoneName()); + } + + if (!result.getIsAuditedDetermined() && chainedResult.getIsAuditedDetermined()) { + result.setIsAudited(chainedResult.getIsAudited()); + result.setAuditPolicyId(chainedResult.getAuditPolicyId()); + } + } + + private static void overrideACLs(final RangerResourceACLs chainedResourceACLs, RangerResourceACLs baseResourceACLs, final RangerRolesUtil.ROLES_FOR userType) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerBasePlugin.overrideACLs(isUser=" + userType.name() + ")"); + } + Map> chainedACLs = null; + Map> baseACLs = null; + + switch (userType) { + case USER: + chainedACLs = chainedResourceACLs.getUserACLs(); + baseACLs = baseResourceACLs.getUserACLs(); + break; + case GROUP: + chainedACLs = chainedResourceACLs.getGroupACLs(); + baseACLs = baseResourceACLs.getGroupACLs(); + break; + case ROLE: + chainedACLs = chainedResourceACLs.getRoleACLs(); + baseACLs = baseResourceACLs.getRoleACLs(); + break; + default: + break; + } + + for (Map.Entry> chainedPermissionsMap : chainedACLs.entrySet()) { + String name = chainedPermissionsMap.getKey(); + Map chainedPermissions = chainedPermissionsMap.getValue(); + Map basePermissions = baseACLs.get(name); + + for (Map.Entry chainedPermission : chainedPermissions.entrySet()) { + String chainedAccessType = chainedPermission.getKey(); + RangerResourceACLs.AccessResult chainedAccessResult = chainedPermission.getValue(); + RangerResourceACLs.AccessResult baseAccessResult = basePermissions == null ? null : basePermissions.get(chainedAccessType); + + final boolean useChainedAccessResult; + + if (baseAccessResult == null) { + useChainedAccessResult = true; + } else { + if (chainedAccessResult.getPolicy().getPolicyPriority() > baseAccessResult.getPolicy().getPolicyPriority()) { + useChainedAccessResult = true; + } else if (chainedAccessResult.getPolicy().getPolicyPriority().equals(baseAccessResult.getPolicy().getPolicyPriority())) { + if (chainedAccessResult.getResult() == baseAccessResult.getResult()) { + useChainedAccessResult = true; + } else { + useChainedAccessResult = chainedAccessResult.getResult() == RangerPolicyEvaluator.ACCESS_DENIED; + } + } else { // chainedAccessResult.getPolicy().getPolicyPriority() < baseAccessResult.getPolicy().getPolicyPriority() + useChainedAccessResult = false; + } + } + + final RangerResourceACLs.AccessResult finalAccessResult = useChainedAccessResult ? chainedAccessResult : baseAccessResult; + + switch (userType) { + case USER: + baseResourceACLs.setUserAccessInfo(name, chainedAccessType, finalAccessResult.getResult(), finalAccessResult.getPolicy()); + break; + case GROUP: + baseResourceACLs.setGroupAccessInfo(name, chainedAccessType, finalAccessResult.getResult(), finalAccessResult.getPolicy()); + break; + case ROLE: + baseResourceACLs.setRoleAccessInfo(name, chainedAccessType, finalAccessResult.getResult(), finalAccessResult.getPolicy()); + break; + default: + break; + } + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerBasePlugin.mergeACLsOneWay(isUser=" + userType.name() + ")"); + } + } + + private static AuditProviderFactory getAuditProviderFactory(String serviceName) { + AuditProviderFactory ret = AuditProviderFactory.getInstance(); + + if (ret == null || !ret.isInitDone()) { + LOG.error("AuditProviderFactory not configured properly, will not log authz events"); + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerChainedPlugin.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerChainedPlugin.java new file mode 100644 index 00000000000..7ea35eedf34 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerChainedPlugin.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.service; + +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.atlas.plugin.policyengine.RangerAccessResult; +import org.apache.atlas.plugin.policyengine.RangerResourceACLs; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.Collection; + +public abstract class RangerChainedPlugin { + private static final Log LOG = LogFactory.getLog(RangerChainedPlugin.class); + + protected final RangerBasePlugin rootPlugin; + protected final String serviceType; + protected final String serviceName; + protected final RangerBasePlugin plugin; + + protected RangerChainedPlugin(RangerBasePlugin rootPlugin, String serviceType, String serviceName) { + LOG.info("RangerChainedPlugin(" + serviceType + ", " + serviceName + ")"); + + this.rootPlugin = rootPlugin; + this.serviceType = serviceType; + this.serviceName = serviceName; + this.plugin = buildChainedPlugin(serviceType, serviceName, rootPlugin.getAppId()); + } + + public void init() { + LOG.info("==> RangerChainedPlugin.init(" + serviceType + ", " + serviceName + ")"); + + this.plugin.init(); + + LOG.info("<== RangerChainedPlugin.init(" + serviceType + ", " + serviceName + ")"); + } + + protected RangerBasePlugin buildChainedPlugin(String serviceType, String serviceName, String appId) { + return new RangerBasePlugin(serviceType, serviceName, appId); + } + + public abstract RangerAccessResult isAccessAllowed(RangerAccessRequest request); + + public abstract Collection isAccessAllowed(Collection requests); + + public abstract RangerResourceACLs getResourceACLs(RangerAccessRequest request); + + public abstract RangerResourceACLs getResourceACLs(RangerAccessRequest request, String policyType); + + public boolean isAuthorizeOnlyWithChainedPlugin() { return false; } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerDefaultRequestProcessor.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerDefaultRequestProcessor.java new file mode 100644 index 00000000000..cdef3fca548 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/service/RangerDefaultRequestProcessor.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.service; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.atlas.plugin.contextenricher.RangerContextEnricher; +import org.apache.atlas.plugin.policyengine.PolicyEngine; +import org.apache.atlas.plugin.policyengine.RangerAccessRequest; +import org.apache.atlas.plugin.policyengine.RangerAccessRequestImpl; +import org.apache.atlas.plugin.policyengine.RangerAccessRequestProcessor; +import org.apache.atlas.plugin.policyengine.RangerAccessResource; +import org.apache.atlas.plugin.policyengine.RangerMutableResource; +import org.apache.atlas.plugin.util.RangerAccessRequestUtil; + +import java.util.List; +import java.util.Set; + +public class RangerDefaultRequestProcessor implements RangerAccessRequestProcessor { + + protected final PolicyEngine policyEngine; + + public RangerDefaultRequestProcessor(PolicyEngine policyEngine) { + this.policyEngine = policyEngine; + } + + @Override + public void preProcess(RangerAccessRequest request) { + + setResourceServiceDef(request); + if (request instanceof RangerAccessRequestImpl) { + RangerAccessRequestImpl reqImpl = (RangerAccessRequestImpl) request; + + if (reqImpl.getClientIPAddress() == null) { + reqImpl.extractAndSetClientIPAddress(policyEngine.getUseForwardedIPAddress(), policyEngine.getTrustedProxyAddresses()); + } + + if(policyEngine.getPluginContext() != null) { + if (reqImpl.getClusterName() == null) { + reqImpl.setClusterName(policyEngine.getPluginContext().getClusterName()); + } + + if (reqImpl.getClusterType() == null) { + reqImpl.setClusterType(policyEngine.getPluginContext().getClusterType()); + } + } + } + + RangerAccessRequestUtil.setCurrentUserInContext(request.getContext(), request.getUser()); + + String owner = request.getResource() != null ? request.getResource().getOwnerUser() : null; + + if (StringUtils.isNotEmpty(owner)) { + RangerAccessRequestUtil.setOwnerInContext(request.getContext(), owner); + } + + Set roles = request.getUserRoles(); + if (CollectionUtils.isEmpty(roles)) { + roles = policyEngine.getPluginContext().getAuthContext().getRolesForUserAndGroups(request.getUser(), request.getUserGroups()); + } + + if (CollectionUtils.isNotEmpty(roles)) { + RangerAccessRequestUtil.setCurrentUserRolesInContext(request.getContext(), roles); + } + + enrich(request); + } + + @Override + public void enrich(RangerAccessRequest request) { + List enrichers = policyEngine.getAllContextEnrichers(); + + if (!CollectionUtils.isEmpty(enrichers)) { + for(RangerContextEnricher enricher : enrichers) { + enricher.enrich(request); + } + } + } + + private void setResourceServiceDef(RangerAccessRequest request) { + RangerAccessResource resource = request.getResource(); + + if (resource.getServiceDef() == null) { + if (resource instanceof RangerMutableResource) { + RangerMutableResource mutable = (RangerMutableResource) resource; + mutable.setServiceDef(policyEngine.getServiceDef()); + } + } + } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/store/ServiceDefsUtil.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/store/ServiceDefsUtil.java new file mode 100644 index 00000000000..6071a77b10d --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/store/ServiceDefsUtil.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.store; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.model.RangerServiceDef; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.List; + +public class ServiceDefsUtil { + private static final Log LOG = LogFactory.getLog(ServiceDefsUtil.class); + + public static final String EMBEDDED_SERVICEDEF_TAG_NAME = "tag"; + + private static ServiceDefsUtil instance = new ServiceDefsUtil(); + + private final Gson gsonBuilder; + + /** Private constructor to restrict instantiation of this singleton utility class. */ + private ServiceDefsUtil() { + gsonBuilder = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z").setPrettyPrinting().create(); + } + + public static ServiceDefsUtil instance() { + return instance; + } + + public RangerServiceDef getEmbeddedServiceDef(String defType) throws Exception { + RangerServiceDef serviceDef=null; + if(StringUtils.isNotEmpty(defType)){ + serviceDef=loadEmbeddedServiceDef(defType); + } + return serviceDef; + } + + public static boolean isRecursiveEnabled(final RangerServiceDef rangerServiceDef, final String resourceDefName) { + boolean ret = false; + List resourceDefs = rangerServiceDef.getResources(); + for(RangerServiceDef.RangerResourceDef resourceDef:resourceDefs) { + if (resourceDefName.equals(resourceDef.getName())) { + ret = resourceDef.getRecursiveSupported(); + break; + } + } + return ret; + } + + private RangerServiceDef loadEmbeddedServiceDef(String serviceType) throws Exception { + if(LOG.isDebugEnabled()) { + LOG.debug("==> EmbeddedServiceDefsUtil.loadEmbeddedServiceDef(" + serviceType + ")"); + } + + RangerServiceDef ret = null; + + String resource = "/service-defs/ranger-servicedef-" + serviceType + ".json"; + + try (InputStream inStream = getClass().getResourceAsStream(resource)) { + + try (InputStreamReader reader = new InputStreamReader(inStream)) { + ret = gsonBuilder.fromJson(reader, RangerServiceDef.class); + + //Set DEFAULT displayName if missing + if (ret != null && StringUtils.isBlank(ret.getDisplayName())) { + ret.setDisplayName(ret.getName()); + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("==> EmbeddedServiceDefsUtil.loadEmbeddedServiceDef(" + serviceType + ")"); + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/DownloadTrigger.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/DownloadTrigger.java new file mode 100644 index 00000000000..0cd0bdaf747 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/DownloadTrigger.java @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +public final class DownloadTrigger { + private boolean isNotified = false; + + public synchronized void waitForCompletion() throws InterruptedException { + while (!isNotified) { + wait(); + } + isNotified = false; + } + + public synchronized void signalCompletion() { + isNotified = true; + notifyAll(); + } +} \ No newline at end of file diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/DownloaderTask.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/DownloaderTask.java new file mode 100644 index 00000000000..6d88dec4433 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/DownloaderTask.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.TimerTask; +import java.util.concurrent.BlockingQueue; + +public final class DownloaderTask extends TimerTask { + private static final Log LOG = LogFactory.getLog(DownloaderTask.class); + + private final DownloadTrigger timerTrigger = new DownloadTrigger(); + private final BlockingQueue queue; + + public DownloaderTask(BlockingQueue queue) { + this.queue = queue; + } + + @Override + public void run() { + try { + queue.put(timerTrigger); + timerTrigger.waitForCompletion(); + } catch (InterruptedException excp) { + LOG.error("Caught exception. Exiting thread"); + } + } +} \ No newline at end of file diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/GrantRevokeRequest.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/GrantRevokeRequest.java new file mode 100644 index 00000000000..7ac0b76d332 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/GrantRevokeRequest.java @@ -0,0 +1,443 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + + +import com.fasterxml.jackson.annotation.JsonInclude; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class GrantRevokeRequest implements Serializable { + private static final long serialVersionUID = 1L; + + private String grantor; + private Set grantorGroups; + private Map resource; + private Set users; + private Set groups; + private Set roles; + private Set accessTypes; + private List forwardedAddresses; + private String remoteIPAddress; + private Boolean delegateAdmin = Boolean.FALSE; + private Boolean enableAudit = Boolean.TRUE; + private Boolean replaceExistingPermissions = Boolean.FALSE; + private Boolean isRecursive = Boolean.FALSE; + private String clientIPAddress; + private String clientType; + private String requestData; + private String sessionId; + private String clusterName; + private String zoneName; + private String ownerUser; + + public GrantRevokeRequest() { + this(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); + } + + public GrantRevokeRequest(String grantor, Set grantorGroups, Map resource, Set users, + Set groups, Set accessTypes, Boolean delegateAdmin, Boolean enableAudit, + Boolean replaceExistingPermissions, Boolean isRecursive, String clientIPAddress, + String clientType, String requestData, String sessionId, String clusterName, String zoneName) { + this(grantor, grantorGroups, resource, users, groups, null, accessTypes, delegateAdmin, enableAudit, replaceExistingPermissions, isRecursive, clientIPAddress, clientType, requestData, sessionId, clusterName, zoneName); + } + + public GrantRevokeRequest(String grantor, Set grantorGroups, Map resource, Set users, + Set groups, Set roles, Set accessTypes, Boolean delegateAdmin, Boolean enableAudit, + Boolean replaceExistingPermissions, Boolean isRecursive, String clientIPAddress, + String clientType, String requestData, String sessionId, String clusterName, String zoneName) { + this(grantor, grantorGroups, resource, users, groups, roles, accessTypes, delegateAdmin, enableAudit, replaceExistingPermissions, isRecursive, clientIPAddress, clientType, requestData, sessionId, clusterName, zoneName, null); + } + + public GrantRevokeRequest(String grantor, Set grantorGroups, Map resource, Set users, + Set groups, Set roles, Set accessTypes, Boolean delegateAdmin, Boolean enableAudit, + Boolean replaceExistingPermissions, Boolean isRecursive, String clientIPAddress, + String clientType, String requestData, String sessionId, String clusterName, String zoneName, String ownerUser) { + setGrantor(grantor); + setGrantorGroups(grantorGroups); + setResource(resource); + setUsers(users); + setGroups(groups); + setRoles(roles); + setAccessTypes(accessTypes); + setDelegateAdmin(delegateAdmin); + setEnableAudit(enableAudit); + setReplaceExistingPermissions(replaceExistingPermissions); + setIsRecursive(isRecursive); + setClientIPAddress(clientIPAddress); + setClientType(clientType); + setRequestData(requestData); + setSessionId(sessionId); + setClusterName(clusterName); + setZoneName(zoneName); + setOwnerUser(ownerUser); + } + + /** + * @return the grantor + */ + public String getGrantor() { + return grantor; + } + + /** + * @param grantor the grantor to set + */ + public void setGrantor(String grantor) { + this.grantor = grantor; + } + + /** + * @return the grantorGroups + */ + public Set getGrantorGroups() { + return grantorGroups; + } + + /** + * @param grantorGroups the grantorGroups to set + */ + public void setGrantorGroups(Set grantorGroups) { + this.grantorGroups = grantorGroups == null ? new HashSet() : grantorGroups; + } + /** + * @return the resource + */ + public Map getResource() { + return resource; + } + + public void setForwardedAddresses(List forwardedAddresses) { + this.forwardedAddresses = (forwardedAddresses == null) ? new ArrayList() : forwardedAddresses; + } + + public void setRemoteIPAddress(String remoteIPAddress) { + this.remoteIPAddress = remoteIPAddress; + } + + + /** + * @param resource the resource to set + */ + public void setResource(Map resource) { + this.resource = resource == null ? new HashMap() : resource; + } + + /** + * @return the users + */ + public Set getUsers() { + return users; + } + + /** + * @param users the users to set + */ + public void setUsers(Set users) { + this.users = users == null ? new HashSet() : users; + } + + /** + * @return the groups + */ + public Set getGroups() { + return groups; + } + + /** + * @param groups the groups to set + */ + public void setGroups(Set groups) { + this.groups = groups == null ? new HashSet() : groups; + } + + /** + * @return the roles + */ + public Set getRoles() { + return roles; + } + + /** + * @param roles the roles to set + */ + public void setRoles(Set roles) { + this.roles = roles == null ? new HashSet() : roles; + } + + + /** + * @return the accessTypes + */ + public Set getAccessTypes() { + return accessTypes; + } + + /** + * @param accessTypes the accessTypes to set + */ + public void setAccessTypes(Set accessTypes) { + this.accessTypes = accessTypes == null ? new HashSet() : accessTypes; + } + + /** + * @return the delegateAdmin + */ + public Boolean getDelegateAdmin() { + return delegateAdmin; + } + + /** + * @param delegateAdmin the delegateAdmin to set + */ + public void setDelegateAdmin(Boolean delegateAdmin) { + this.delegateAdmin = delegateAdmin == null ? Boolean.FALSE : delegateAdmin; + } + + /** + * @return the enableAudit + */ + public Boolean getEnableAudit() { + return enableAudit; + } + + /** + * @param enableAudit the enableAudit to set + */ + public void setEnableAudit(Boolean enableAudit) { + this.enableAudit = enableAudit == null ? Boolean.TRUE : enableAudit; + } + + /** + * @return the ownerUser + */ + public String getOwnerUser() { + return ownerUser; + } + + /** + * @param ownerUser the ownerUser to set + */ + public void setOwnerUser(String ownerUser) { + this.ownerUser = ownerUser; + } + + /** + * @return the replaceExistingPermissions + */ + public Boolean getReplaceExistingPermissions() { + return replaceExistingPermissions; + } + + /** + * @param replaceExistingPermissions the replaceExistingPermissions to set + */ + public void setReplaceExistingPermissions(Boolean replaceExistingPermissions) { + this.replaceExistingPermissions = replaceExistingPermissions == null ? Boolean.FALSE : replaceExistingPermissions; + } + + /** + * @return the isRecursive + */ + public Boolean getIsRecursive() { + return isRecursive; + } + + /** + * @param isRecursive the isRecursive to set + */ + public void setIsRecursive(Boolean isRecursive) { + this.isRecursive = isRecursive == null ? Boolean.FALSE : isRecursive; + } + + /** + * @return the clientIPAddress + */ + public String getClientIPAddress() { + return clientIPAddress; + } + + /** + * @param clientIPAddress the clientIPAddress to set + */ + public void setClientIPAddress(String clientIPAddress) { + this.clientIPAddress = clientIPAddress; + } + + /** + * @return the clientType + */ + public String getClientType() { + return clientType; + } + + /** + * @param clientType the clientType to set + */ + public void setClientType(String clientType) { + this.clientType = clientType; + } + + /** + * @return the requestData + */ + public String getRequestData() { + return requestData; + } + + /** + * @param requestData the requestData to set + */ + public void setRequestData(String requestData) { + this.requestData = requestData; + } + + /** + * @return the sessionId + */ + public String getSessionId() { + return sessionId; + } + + /** + * @param sessionId the sessionId to set + */ + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } + + /** + * @return the clusterName + */ + public String getClusterName() { + return clusterName; + } + + public String getRemoteIPAddress() { + return remoteIPAddress; + } + + public List getForwardedAddresses() { + return forwardedAddresses; + } + + /** + * @param clusterName the clusterName to set + */ + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + /** + * @return the clusterName + */ + public String getZoneName() { + return zoneName; + } + + /** + * @param zoneName the clusterName to set + */ + public void setZoneName(String zoneName) { + this.zoneName = zoneName; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("GrantRevokeRequest={"); + + sb.append("grantor={").append(grantor).append("} "); + + sb.append("grantorGroups={"); + if(grantorGroups != null) { + for(String grantorGroup : grantorGroups) { + sb.append(grantorGroup).append(" "); + } + } + sb.append("} "); + + sb.append("resource={"); + if(resource != null) { + for(Map.Entry e : resource.entrySet()) { + sb.append(e.getKey()).append("=").append(e.getValue()).append("; "); + } + } + sb.append("} "); + + sb.append("users={"); + if(users != null) { + for(String user : users) { + sb.append(user).append(" "); + } + } + sb.append("} "); + + sb.append("groups={"); + if(groups != null) { + for(String group : groups) { + sb.append(group).append(" "); + } + } + sb.append("} "); + + sb.append("accessTypes={"); + if(accessTypes != null) { + for(String accessType : accessTypes) { + sb.append(accessType).append(" "); + } + } + sb.append("} "); + + sb.append("delegateAdmin={").append(delegateAdmin).append("} "); + sb.append("enableAudit={").append(enableAudit).append("} "); + sb.append("replaceExistingPermissions={").append(replaceExistingPermissions).append("} "); + sb.append("isRecursive={").append(isRecursive).append("} "); + sb.append("clientIPAddress={").append(clientIPAddress).append("} "); + sb.append("clientType={").append(clientType).append("} "); + sb.append("requestData={").append(requestData).append("} "); + sb.append("sessionId={").append(sessionId).append("} "); + sb.append("clusterName={").append(clusterName).append("} "); + sb.append("zoneName={").append(zoneName).append("} "); + + sb.append("}"); + + return sb; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/GrantRevokeRoleRequest.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/GrantRevokeRoleRequest.java new file mode 100644 index 00000000000..8d3d083d72b --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/GrantRevokeRoleRequest.java @@ -0,0 +1,299 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class GrantRevokeRoleRequest implements Serializable { + private static final long serialVersionUID = 1L; + + private String grantor; + private Set grantorGroups; + private Set targetRoles; + private Set users; + private Set groups; + private Set roles; + private Boolean grantOption = Boolean.FALSE; + private String clientIPAddress; + private String clientType; + private String requestData; + private String sessionId; + private String clusterName; + + public GrantRevokeRoleRequest() { + this(null, null, null, null, null, null, null, null, null, null, null); + } + + public GrantRevokeRoleRequest(String grantor, Set grantorGroups, Set targetRoles, Set users, + Set groups, Set roles, Boolean grantOption, + String clientIPAddress, String clientType, + String requestData, String sessionId) { + setGrantor(grantor); + setGrantorGroups(grantorGroups); + setTargetRoles(targetRoles); + setUsers(users); + setGroups(groups); + setRoles(roles); + setGrantOption(grantOption); + setClientIPAddress(clientIPAddress); + setClientType(clientType); + setRequestData(requestData); + setSessionId(sessionId); + setClusterName(clusterName); + } + + /** + * @return the grantor + */ + public String getGrantor() { + return grantor; + } + + /** + * @param grantor the grantor to set + */ + public void setGrantor(String grantor) { + this.grantor = grantor; + } + + /** + * @return the grantorRoles + */ + public Set getGrantorGroups() { + return grantorGroups; + } + + /** + * @param grantorGroups the grantorRoles to set + */ + + public void setGrantorGroups(Set grantorGroups) { + this.grantorGroups = grantorGroups; + } + + /** + * @return the targetRoles + */ + public Set getTargetRoles() { + return targetRoles; + } + + /** + * @param targetRoles the targetRoles to set + */ + public void setTargetRoles(Set targetRoles) { + this.targetRoles = targetRoles == null ? new HashSet() : targetRoles; + } + + /** + * @return the users + */ + public Set getUsers() { + return users; + } + + /** + * @param users the users to set + */ + public void setUsers(Set users) { + this.users = users == null ? new HashSet() : users; + } + + /** + * @return the groups + */ + public Set getGroups() { + return groups; + } + + /** + * @param groups the groups to set + */ + public void setGroups(Set groups) { + this.groups = groups; + } + + /** + * @return the roles + */ + public Set getRoles() { + return roles; + } + + /** + * @param roles the roles to set + */ + public void setRoles(Set roles) { + this.roles = roles == null ? new HashSet() : roles; + } + + /** + * @return the grantOption + */ + public Boolean getGrantOption() { + return grantOption; + } + + /** + * @param grantOption the grantOption to set + */ + public void setGrantOption(Boolean grantOption) { + this.grantOption = grantOption == null ? Boolean.FALSE : grantOption; + } + + /** + * @return the clientIPAddress + */ + public String getClientIPAddress() { + return clientIPAddress; + } + + /** + * @param clientIPAddress the clientIPAddress to set + */ + public void setClientIPAddress(String clientIPAddress) { + this.clientIPAddress = clientIPAddress; + } + + /** + * @return the clientType + */ + public String getClientType() { + return clientType; + } + + /** + * @param clientType the clientType to set + */ + public void setClientType(String clientType) { + this.clientType = clientType; + } + + /** + * @return the requestData + */ + public String getRequestData() { + return requestData; + } + + /** + * @param requestData the requestData to set + */ + public void setRequestData(String requestData) { + this.requestData = requestData; + } + + /** + * @return the sessionId + */ + public String getSessionId() { + return sessionId; + } + + /** + * @param sessionId the sessionId to set + */ + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } + + /** + * @return the clusterName + */ + public String getClusterName() { + return clusterName; + } + + /** + * @param clusterName the clusterName to set + */ + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("GrantRevokeRoleRequest={"); + + sb.append("grantor={").append(grantor).append("} "); + + sb.append("targetRoles={"); + if(targetRoles != null) { + for(String targetRole : targetRoles) { + sb.append(targetRole).append(" "); + } + } + sb.append("} "); + + sb.append("users={"); + if(users != null) { + for(String user : users) { + sb.append(user).append(" "); + } + } + sb.append("} "); + + sb.append("groups={"); + if(roles != null) { + for(String group : groups) { + sb.append(group).append(" "); + } + } + sb.append("} "); + + sb.append("roles={"); + if(roles != null) { + for(String role : roles) { + sb.append(role).append(" "); + } + } + sb.append("} "); + + sb.append("grantOption={").append(grantOption).append("} "); + sb.append("clientIPAddress={").append(clientIPAddress).append("} "); + sb.append("clientType={").append(clientType).append("} "); + sb.append("requestData={").append(requestData).append("} "); + sb.append("sessionId={").append(sessionId).append("} "); + sb.append("clusterName={").append(clusterName).append("} "); + + sb.append("}"); + + return sb; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/KeySearchFilter.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/KeySearchFilter.java new file mode 100644 index 00000000000..88c8029c32d --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/KeySearchFilter.java @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class KeySearchFilter { + public static final String KEY_NAME = "name";// search, sort + + public static final String START_INDEX = "startIndex"; + public static final String PAGE_SIZE = "pageSize"; + public static final String SORT_BY = "sortBy"; + + private Map params; + private int startIndex; + private int maxRows = Integer.MAX_VALUE; + private boolean getCount = true; + private String sortBy; + private String sortType; + + public KeySearchFilter() { + this(null); + } + + public KeySearchFilter(String name, String value) { + setParam(name, value); + } + + public KeySearchFilter(Map values) { + setParams(values); + } + + public Map getParams() { + return params; + } + + public void setParams(Map params) { + this.params = params; + } + + public String getParam(String name) { + return params == null ? null : params.get(name); + } + + public void setParam(String name, String value) { + if(StringUtils.isEmpty(name) || StringUtils.isEmpty(value)) { + return; + } + + if(params == null) { + params = new HashMap<>(); + } + + params.put(name, value); + } + public boolean isEmpty() { + return MapUtils.isEmpty(params); + } + + public int getStartIndex() { + return startIndex; + } + + public void setStartIndex(int startIndex) { + this.startIndex = startIndex; + } + + public int getMaxRows() { + return maxRows; + } + + public void setMaxRows(int maxRows) { + this.maxRows = maxRows; + } + + public boolean isGetCount() { + return getCount; + } + + public void setGetCount(boolean getCount) { + this.getCount = getCount; + } + + public String getSortBy() { + return sortBy; + } + + public void setSortBy(String sortBy) { + this.sortBy = sortBy; + } + + public String getSortType() { + return sortType; + } + + public void setSortType(String sortType) { + this.sortType = sortType; + } + + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof KeySearchFilter)) { + return false; + } + KeySearchFilter that = (KeySearchFilter)object; + return Objects.equals(params, that.params); + } + + @Override + public int hashCode() { + return Objects.hash(params); + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/KeycloakUserStore.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/KeycloakUserStore.java new file mode 100644 index 00000000000..b3224585434 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/KeycloakUserStore.java @@ -0,0 +1,352 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.atlas.AtlasConfiguration; +import org.apache.atlas.RequestContext; +import org.apache.atlas.auth.client.heracles.models.HeraclesRoleViewRepresentation; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.plugin.model.RangerRole; +import org.apache.atlas.utils.AtlasPerfMetrics; +import org.apache.atlas.utils.AtlasPerfTracer; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.keycloak.representations.idm.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; +import java.util.stream.Collectors; + +import static org.apache.atlas.auth.client.keycloak.AtlasKeycloakClient.getKeycloakClient; +import static org.apache.atlas.auth.client.heracles.AtlasHeraclesClient.getHeraclesClient; +import static org.apache.atlas.repository.Constants.*; +import static org.apache.atlas.repository.util.AccessControlUtils.ARGO_SERVICE_USER_NAME; +import static org.apache.atlas.repository.util.AccessControlUtils.BACKEND_SERVICE_USER_NAME; + + +public class KeycloakUserStore { + private static final Logger PERF_LOG = AtlasPerfTracer.getPerfLogger("KeycloakUserStore"); + private static final Logger LOG = LoggerFactory.getLogger(KeycloakUserStore.class); + + private static int NUM_THREADS = 5; + + private static String LOGIN_EVENT_DETAIL_KEY = "custom_required_action"; + private static String LOGIN_EVENT_DETAIL_VALUE = "UPDATE_PROFILE"; + + private static List EVENT_TYPES = Arrays.asList("LOGIN"); + private static List OPERATION_TYPES = Arrays.asList("CREATE", "UPDATE", "DELETE"); + private static List RESOURCE_TYPES = Arrays.asList("USER", "GROUP", "REALM_ROLE", "CLIENT", "REALM_ROLE_MAPPING", "GROUP_MEMBERSHIP", "CLIENT_ROLE_MAPPING"); + + private enum KEYCLOAK_FIELDS { + ROLES, + COMPOSITE_ROLES, + GROUPS, + USERS, + + } + + private final String serviceName; + + public KeycloakUserStore(String serviceName) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerRolesProvider(serviceName=" + serviceName + ").RangerRolesProvider()"); + } + + this.serviceName = serviceName; + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerRolesProvider(serviceName=" + serviceName + ").RangerRolesProvider()"); + } + } + + public boolean isKeycloakSubjectsStoreUpdated(long cacheLastUpdatedTime) throws AtlasBaseException { + AtlasPerfMetrics.MetricRecorder metricRecorder = RequestContext.get().startMetricRecord("getKeycloakSubjectsStoreUpdatedTime"); + if (cacheLastUpdatedTime == -1) { + return true; + } + + long latestKeycloakEventTime = -1L; + + try { + int size = 100; + + for (int from = 0; ; from += size) { + + List adminEvents = getKeycloakClient().getAdminEvents(OPERATION_TYPES, + null, null, null, null, null, null, null, + from, size); + + if (CollectionUtils.isEmpty(adminEvents) || cacheLastUpdatedTime > adminEvents.get(0).getTime()) { + break; + } + + Optional event = adminEvents.stream().filter(x -> RESOURCE_TYPES.contains(x.getResourceType())).findFirst(); + + if (event.isPresent()) { + latestKeycloakEventTime = event.get().getTime(); + break; + } + } + + if (latestKeycloakEventTime > cacheLastUpdatedTime) { + return true; + } + + //check Events for user registration event via OKTA + for (int from = 0; ; from += size) { + + List events = getKeycloakClient().getEvents(EVENT_TYPES, + null, null, null, null, null, from, size); + + if (CollectionUtils.isEmpty(events) || cacheLastUpdatedTime > events.get(0).getTime()) { + break; + } + + Optional event = events.stream().filter(this::isUpdateProfileEvent).findFirst(); + + if (event.isPresent()) { + latestKeycloakEventTime = event.get().getTime(); + break; + } + } + + if (latestKeycloakEventTime > cacheLastUpdatedTime) { + return true; + } + + } catch (Exception e) { + LOG.error("Error while fetching latest event time", e); + } finally { + RequestContext.get().endMetricRecord(metricRecorder); + } + + return false; + } + + private boolean isUpdateProfileEvent(EventRepresentation event) { + return MapUtils.isNotEmpty(event.getDetails()) && + event.getDetails().containsKey(LOGIN_EVENT_DETAIL_KEY) && + event.getDetails().get(LOGIN_EVENT_DETAIL_KEY).equals(LOGIN_EVENT_DETAIL_VALUE); + } + + public RangerRoles loadRolesIfUpdated(long lastUpdatedTime) throws AtlasBaseException { + AtlasPerfMetrics.MetricRecorder recorder = RequestContext.get().startMetricRecord("loadRolesIfUpdated"); + + boolean isKeycloakUpdated = isKeycloakSubjectsStoreUpdated(lastUpdatedTime); + if (!isKeycloakUpdated) { + return null; + } + RangerRoles rangerRoles = new RangerRoles(); + Map> roleUserMapping = new HashMap<>(); + Set roleSet = new HashSet<>(); + + int userSize = AtlasConfiguration.HERACLES_CLIENT_PAGINATION_SIZE.getInt(); + int userFrom = 0; + List userRetrievalResult; + + do { + userRetrievalResult = getHeraclesClient().getUsersMappings(userFrom, userSize, new String[]{KEYCLOAK_FIELDS.ROLES.name().toLowerCase()}); + + if (!CollectionUtils.isEmpty(userRetrievalResult)) { + userRetrievalResult.forEach(user -> { + Set userRoles = new HashSet<>(user.getRealmRoles()); + + userRoles.forEach(role -> roleUserMapping + .computeIfAbsent(role, k -> new ArrayList<>()) + .add(new RangerRole.RoleMember(user.getUsername(), false)) + ); + }); + + userFrom += userSize; + } + + } while (!CollectionUtils.isEmpty(userRetrievalResult) && userRetrievalResult.size() % userSize == 0); + + int roleSize = AtlasConfiguration.HERACLES_CLIENT_PAGINATION_SIZE.getInt(); + int roleFrom = 0; + List roleRetrievalResult; + + do { + roleRetrievalResult = getHeraclesClient().getRolesMappings(roleFrom, roleSize, new String[]{KEYCLOAK_FIELDS.COMPOSITE_ROLES.name().toLowerCase(), + KEYCLOAK_FIELDS.GROUPS.name()}); + + if (!CollectionUtils.isEmpty(roleRetrievalResult)) { + roleRetrievalResult.forEach(role -> { + RangerRole rangerRole = new RangerRole(); + rangerRole.setName(role.getName()); + rangerRole.setGroups(role.getGroups().stream() + .map(x -> new RangerRole.RoleMember(x, false)) + .collect(Collectors.toList())); + rangerRole.setUsers(roleUserMapping.get(role.getName())); + rangerRole.setRoles(role.getRoles().stream() + .map(x -> new RangerRole.RoleMember(x, false)) + .collect(Collectors.toList())); + + roleSet.add(rangerRole); + }); + + roleFrom += roleSize; + } + + } while (!CollectionUtils.isEmpty(roleRetrievalResult) && roleRetrievalResult.size() % roleSize == 0); + + + processDefaultRole(roleSet); + LOG.info("Inverting roles"); + invertRoles(roleSet); + + rangerRoles.setRangerRoles(roleSet); + rangerRoles.setServiceName(serviceName); + + Date current = new Date(); + rangerRoles.setRoleUpdateTime(current); + rangerRoles.setServiceName(serviceName); + rangerRoles.setRoleVersion(-1L); + + RequestContext.get().endMetricRecord(recorder); + + return rangerRoles; + } + + private void extractUserGroupMapping(List users, Map> userGroupMapping) { + for (UserRepresentation user : users) { + userGroupMapping.put(user.getUsername(), new HashSet<>(user.getGroups() == null ? Collections.emptyList() : user.getGroups())); + } + } + + public void invertRoles(Set roleSet) { + Map roleMap = new HashMap<>(); + for (RangerRole role : roleSet) { + RangerRole existingRole = roleMap.get(role.getName()); + if (existingRole != null) { + existingRole.setGroups(role.getGroups()); + existingRole.setUsers(role.getUsers()); + } else { + RangerRole newRole = new RangerRole(); + newRole.setName(role.getName()); + newRole.setUsers(role.getUsers()); + newRole.setGroups(role.getGroups()); + roleMap.put(role.getName(), newRole); + } + + List roles = role.getRoles(); + for (RangerRole.RoleMember roleMember : roles) { + if (role.getName().equals("default-roles-default") && roleMember.getName().equals("$guest")) { + continue; + } + RangerRole existingRoleMember = roleMap.get(roleMember.getName()); + if (existingRoleMember != null) { + List existingRoleMemberRoles = existingRoleMember.getRoles(); + // If the role already present in existing role, then skip + if (existingRoleMemberRoles.stream().anyMatch(x -> x.getName().equals(role.getName()))) { + continue; + } + existingRoleMemberRoles.add(new RangerRole.RoleMember(role.getName(), false)); + } else { + RangerRole newRoleMember = new RangerRole(); + newRoleMember.setName(roleMember.getName()); + newRoleMember.setRoles(new ArrayList<>(Arrays.asList(new RangerRole.RoleMember(role.getName(), false)))); + roleMap.put(roleMember.getName(), newRoleMember); + } + } + } + roleSet.clear(); + roleSet.addAll(roleMap.values()); + } + + private void processDefaultRole(Set roleSet) { + Optional defaultRole = roleSet.stream().filter(x -> KEYCLOAK_ROLE_DEFAULT.equals(x.getName())).findFirst(); + + if (defaultRole.isPresent()) { + List realmDefaultRoles = defaultRole.get().getRoles().stream().map(x -> x.getName()).collect(Collectors.toList()); + String tenantDefaultRealmUserRole = ""; + + if (realmDefaultRoles.contains(KEYCLOAK_ROLE_ADMIN)) { + tenantDefaultRealmUserRole = KEYCLOAK_ROLE_ADMIN; + } else if (realmDefaultRoles.contains(KEYCLOAK_ROLE_MEMBER)) { + tenantDefaultRealmUserRole = KEYCLOAK_ROLE_MEMBER; + } else if (realmDefaultRoles.contains(KEYCLOAK_ROLE_GUEST)) { + tenantDefaultRealmUserRole = KEYCLOAK_ROLE_GUEST; + } + + String finalTenantDefaultRealmUserRole = tenantDefaultRealmUserRole; + Optional targetRole = roleSet.stream().filter(x -> finalTenantDefaultRealmUserRole.equals(x.getName())).findFirst(); + + if (targetRole.isPresent()) { + List defaultUsers = new ArrayList<>(defaultRole.get().getUsers()); + List nonGuestUsers = new ArrayList<>(0); + + Optional adminRole = roleSet.stream().filter(x -> KEYCLOAK_ROLE_ADMIN.equals(x.getName())).findFirst(); + adminRole.ifPresent(rangerRole -> nonGuestUsers.addAll(rangerRole.getUsers())); + + Optional memberRole = roleSet.stream().filter(x -> KEYCLOAK_ROLE_MEMBER.equals(x.getName())).findFirst(); + memberRole.ifPresent(rangerRole -> nonGuestUsers.addAll(rangerRole.getUsers())); + + Optional apiTokenDefaultAccessRole = roleSet.stream().filter(x -> KEYCLOAK_ROLE_API_TOKEN.equals(x.getName())).findFirst(); + apiTokenDefaultAccessRole.ifPresent(rangerRole -> nonGuestUsers.addAll(rangerRole.getUsers())); + + defaultUsers.removeAll(nonGuestUsers); + defaultUsers.remove(new RangerRole.RoleMember(ARGO_SERVICE_USER_NAME, false)); + defaultUsers.remove(new RangerRole.RoleMember(BACKEND_SERVICE_USER_NAME, false)); + + targetRole.get().getUsers().addAll(defaultUsers); + } + } + } + + public RangerUserStore loadUserStoreIfUpdated(long lastUpdatedTime) throws AtlasBaseException { + AtlasPerfMetrics.MetricRecorder recorder = RequestContext.get().startMetricRecord("loadUserStoreIfUpdated"); + boolean isKeycloakUpdated = isKeycloakSubjectsStoreUpdated(lastUpdatedTime); + if (!isKeycloakUpdated) { + return null; + } + + int userSize = 100; + int userFrom = 0; + boolean userFound = true; + Map> userGroupMapping = new HashMap<>(); + List ret = new ArrayList<>(); + + do { + List users = getHeraclesClient().getUsersMappings(userFrom, userSize, + new String[]{KEYCLOAK_FIELDS.GROUPS.name().toLowerCase()}); + if (CollectionUtils.isEmpty(users)) { + userFound = false; + } else { + ret.addAll(users); + userFrom += userSize; + } + extractUserGroupMapping(users, userGroupMapping); + + } while (userFound && ret.size() % userSize == 0); + + RangerUserStore userStore = new RangerUserStore(); + userStore.setUserGroupMapping(userGroupMapping); + userStore.setUserStoreUpdateTime(new Date()); + userStore.setServiceName(serviceName); + userStore.setUserStoreVersion(-1L); + + RequestContext.get().endMetricRecord(recorder); + + + return userStore; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/PasswordUtils.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/PasswordUtils.java new file mode 100644 index 00000000000..bc18f331d9e --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/PasswordUtils.java @@ -0,0 +1,231 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.atlas.plugin.util; + +import com.google.common.base.Splitter; +import com.google.common.base.Strings; +import com.google.common.collect.Lists; +import com.sun.jersey.core.util.Base64; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import java.io.IOException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.util.Map; + +public class PasswordUtils { + + private static final Logger LOG = LoggerFactory.getLogger(PasswordUtils.class); + + private final String cryptAlgo; + private String password; + private final int iterationCount; + private final char[] encryptKey; + private final byte[] salt; + private final byte[] iv; + private static final String LEN_SEPARATOR_STR = ":"; + + public static final String PBE_SHA512_AES_128 = "PBEWITHHMACSHA512ANDAES_128"; + + public static final String DEFAULT_CRYPT_ALGO = "PBEWithMD5AndDES"; + public static final String DEFAULT_ENCRYPT_KEY = "tzL1AKl5uc4NKYaoQ4P3WLGIBFPXWPWdu1fRm9004jtQiV"; + public static final String DEFAULT_SALT = "f77aLYLo"; + public static final int DEFAULT_ITERATION_COUNT = 17; + public static final byte[] DEFAULT_INITIAL_VECTOR = new byte[16]; + + public static String encryptPassword(String aPassword) throws IOException { + return build(aPassword).encrypt(); + } + + public static PasswordUtils build(String aPassword) { + return new PasswordUtils(aPassword); + } + + private String encrypt() throws IOException { + String ret = null; + String strToEncrypt = null; + if (password == null) { + strToEncrypt = ""; + } else { + strToEncrypt = password.length() + LEN_SEPARATOR_STR + password; + } + try { + Cipher engine = Cipher.getInstance(cryptAlgo); + PBEKeySpec keySpec = new PBEKeySpec(encryptKey); + SecretKeyFactory skf = SecretKeyFactory.getInstance(cryptAlgo); + SecretKey key = skf.generateSecret(keySpec); + engine.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(salt, iterationCount, new IvParameterSpec(iv))); + byte[] encryptedStr = engine.doFinal(strToEncrypt.getBytes()); + ret = new String(Base64.encode(encryptedStr)); + } + catch(Throwable t) { + LOG.error("Unable to encrypt password due to error", t); + throw new IOException("Unable to encrypt password due to error", t); + } + return ret; + } + + PasswordUtils(String aPassword) { + String[] crypt_algo_array = null; + byte[] SALT; + char[] ENCRYPT_KEY; + if (aPassword != null && aPassword.contains(",")) { + crypt_algo_array = Lists.newArrayList(Splitter.on(",").split(aPassword)).toArray(new String[0]); + } + if (crypt_algo_array != null && crypt_algo_array.length > 4) { + int index = 0; + cryptAlgo = crypt_algo_array[index++]; // 0 + ENCRYPT_KEY = crypt_algo_array[index++].toCharArray(); // 1 + SALT = crypt_algo_array[index++].getBytes(); // 2 + iterationCount = Integer.parseInt(crypt_algo_array[index++]);// 3 + if (needsIv(cryptAlgo)) { + iv = Base64.decode(crypt_algo_array[index++]); + } else { + iv = DEFAULT_INITIAL_VECTOR; + } + password = crypt_algo_array[index++]; + if (crypt_algo_array.length > index) { + for (int i = index; i < crypt_algo_array.length; i++) { + password = password + "," + crypt_algo_array[i]; + } + } + } else { + cryptAlgo = DEFAULT_CRYPT_ALGO; + ENCRYPT_KEY = DEFAULT_ENCRYPT_KEY.toCharArray(); + SALT = DEFAULT_SALT.getBytes(); + iterationCount = DEFAULT_ITERATION_COUNT; + iv = DEFAULT_INITIAL_VECTOR; + password = aPassword; + } + Map env = System.getenv(); + String encryptKeyStr = env.get("ENCRYPT_KEY"); + if (encryptKeyStr == null) { + encryptKey=ENCRYPT_KEY; + }else{ + encryptKey=encryptKeyStr.toCharArray(); + } + String saltStr = env.get("ENCRYPT_SALT"); + if (saltStr == null) { + salt = SALT; + }else{ + salt=saltStr.getBytes(); + } + } + + public static String decryptPassword(String aPassword) throws IOException { + return build(aPassword).decrypt(); + } + + private String decrypt() throws IOException { + String ret = null; + try { + byte[] decodedPassword = Base64.decode(password); + Cipher engine = Cipher.getInstance(cryptAlgo); + PBEKeySpec keySpec = new PBEKeySpec(encryptKey); + SecretKeyFactory skf = SecretKeyFactory.getInstance(cryptAlgo); + SecretKey key = skf.generateSecret(keySpec); + engine.init(Cipher.DECRYPT_MODE, key,new PBEParameterSpec(salt, iterationCount, new IvParameterSpec(iv))); + String decrypted = new String(engine.doFinal(decodedPassword)); + int foundAt = decrypted.indexOf(LEN_SEPARATOR_STR); + if (foundAt > -1) { + if (decrypted.length() > foundAt) { + ret = decrypted.substring(foundAt+1); + } + else { + ret = ""; + } + } + else { + ret = null; + } + } + catch(Throwable t) { + LOG.error("Unable to decrypt password due to error", t); + throw new IOException("Unable to decrypt password due to error", t); + } + return ret; + } + + public static boolean needsIv(String cryptoAlgo) { + if (Strings.isNullOrEmpty(cryptoAlgo)) + return false; + + return PBE_SHA512_AES_128.toLowerCase().equals(cryptoAlgo.toLowerCase()) + || cryptoAlgo.toLowerCase().contains("aes_128") || cryptoAlgo.toLowerCase().contains("aes_256"); + } + + public static String generateIvIfNeeded(String cryptAlgo) throws NoSuchAlgorithmException { + if (!needsIv(cryptAlgo)) + return null; + return generateBase64EncodedIV(); + } + + private static String generateBase64EncodedIV() throws NoSuchAlgorithmException { + byte[] iv = new byte[16]; + SecureRandom.getInstance("NativePRNGNonBlocking").nextBytes(iv); + return new String(Base64.encode(iv)); + } + + public String getCryptAlgo() { + return cryptAlgo; + } + + public String getPassword() { + return password; + } + + public int getIterationCount() { + return iterationCount; + } + + public char[] getEncryptKey() { + return encryptKey; + } + + public byte[] getSalt() { + return salt; + } + + public byte[] getIv() { + return iv; + } + + public String getIvAsString() { + return new String(Base64.encode(getIv())); + } + public static String getDecryptPassword(String password) { + String decryptedPwd = null; + try { + decryptedPwd = decryptPassword(password); + } catch (Exception ex) { + LOG.warn("Password decryption failed, trying original password string."); + decryptedPwd = null; + } finally { + if (decryptedPwd == null) { + decryptedPwd = password; + } + } + return decryptedPwd; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/PerfDataRecorder.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/PerfDataRecorder.java new file mode 100644 index 00000000000..5c10c9d424d --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/PerfDataRecorder.java @@ -0,0 +1,173 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import com.google.common.collect.ImmutableMap; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +public class PerfDataRecorder { + private static final Log LOG = LogFactory.getLog(PerfDataRecorder.class); + private static final Log PERF = RangerPerfTracer.getPerfLogger(PerfDataRecorder.class); + + private static volatile PerfDataRecorder instance; + private Map perfStatistics = new HashMap<>(); + + public static void initialize(List names) { + if (instance == null) { + synchronized (PerfDataRecorder.class) { + if (instance == null) { + instance = new PerfDataRecorder(names); + } + } + } + } + + public static boolean collectStatistics() { + return instance != null; + } + + public static void printStatistics() { + if (instance != null) { + instance.dumpStatistics(); + } + } + + public static void clearStatistics() { + if (instance != null) { + instance.clear(); + } + } + + public static void recordStatistic(String tag, long elapsedTime) { + if (instance != null) { + instance.record(tag, elapsedTime); + } + } + + private void dumpStatistics() { + List tags = new ArrayList<>(perfStatistics.keySet()); + + Collections.sort(tags); + + for (String tag : tags) { + PerfStatistic perfStatistic = perfStatistics.get(tag); + + long averageTimeSpent = 0L; + + if (perfStatistic.numberOfInvocations.get() != 0L) { + averageTimeSpent = perfStatistic.microSecondsSpent.get()/perfStatistic.numberOfInvocations.get(); + } + + String logMsg = "[" + tag + "]" + + " execCount: " + perfStatistic.numberOfInvocations.get() + + ", totalTimeTaken: " + perfStatistic.microSecondsSpent.get() + " μs" + + ", maxTimeTaken: " + perfStatistic.maxTimeSpent.get() + " μs" + + ", minTimeTaken: " + perfStatistic.minTimeSpent.get() + " μs" + + ", avgTimeTaken: " + averageTimeSpent + " μs"; + + LOG.info(logMsg); + PERF.debug(logMsg); + } + } + + private void clear() { + perfStatistics.clear(); + } + + private void record(String tag, long elapsedTime) { + PerfStatistic perfStatistic = perfStatistics.get(tag); + + if (perfStatistic == null) { + synchronized (PerfDataRecorder.class) { + perfStatistic = perfStatistics.get(tag); + + if(perfStatistic == null) { + perfStatistic = new PerfStatistic(); + perfStatistics.put(tag, perfStatistic); + } + } + } + + perfStatistic.addPerfDataItem(elapsedTime); + } + + private PerfDataRecorder(List names) { + if (CollectionUtils.isNotEmpty(names)) { + for (String name : names) { + // Create structure + perfStatistics.put(name, new PerfStatistic()); + } + } + } + + public static Map exposeStatistics() { + if (instance != null) { + return ImmutableMap.copyOf(instance.perfStatistics); + } + return ImmutableMap.of(); + } + + public static class PerfStatistic { + private AtomicLong numberOfInvocations = new AtomicLong(0L); + private AtomicLong microSecondsSpent = new AtomicLong(0L); + private AtomicLong minTimeSpent = new AtomicLong(Long.MAX_VALUE); + private AtomicLong maxTimeSpent = new AtomicLong(Long.MIN_VALUE); + + void addPerfDataItem(final long timeTaken) { + numberOfInvocations.getAndIncrement(); + microSecondsSpent.getAndAdd(timeTaken); + + long min = minTimeSpent.get(); + if(timeTaken < min) { + minTimeSpent.compareAndSet(min, timeTaken); + } + + long max = maxTimeSpent.get(); + if(timeTaken > max) { + maxTimeSpent.compareAndSet(max, timeTaken); + } + } + + public long getNumberOfInvocations() { + return numberOfInvocations.get(); + } + + public long getMicroSecondsSpent() { + return microSecondsSpent.get(); + } + + public long getMinTimeSpent() { + return minTimeSpent.get(); + } + + public long getMaxTimeSpent() { + return maxTimeSpent.get(); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/PolicyRefresher.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/PolicyRefresher.java new file mode 100644 index 00000000000..cce31645ba3 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/PolicyRefresher.java @@ -0,0 +1,527 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.apache.atlas.AtlasConfiguration; +import org.apache.atlas.authz.admin.client.AtlasAuthAdminClient; +import org.apache.atlas.policytransformer.CachePolicyTransformerImpl; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.authorization.config.RangerPluginConfig; +import org.apache.atlas.plugin.policyengine.RangerPluginContext; +import org.apache.atlas.plugin.service.RangerBasePlugin; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.Timer; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + + +public class PolicyRefresher extends Thread { + private static final Log LOG = LogFactory.getLog(PolicyRefresher.class); + + private static final Log PERF_POLICYENGINE_INIT_LOG = RangerPerfTracer.getPerfLogger("policyengine.init"); + + private final RangerBasePlugin plugIn; + private final String serviceType; + private final String serviceName; + private final AtlasAuthAdminClient atlasAuthAdminClient; + private final RangerRolesProvider rolesProvider; + private final RangerUserStoreProvider userStoreProvider; + private final long pollingIntervalMs; + private final String cacheFileName; + private final String cacheDir; + private final Gson gson; + private final BlockingQueue policyDownloadQueue = new LinkedBlockingQueue<>(); + private Timer policyDownloadTimer; + private long lastKnownVersion = -1L; + private long lastUpdatedTimeInMillis = -1L; + private long lastActivationTimeInMillis; + private boolean policiesSetInPlugin; + private boolean serviceDefSetInPlugin; + private boolean enableDeltaBasedRefresh; + + + public PolicyRefresher(RangerBasePlugin plugIn) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> PolicyRefresher(serviceName=" + plugIn.getServiceName() + ").PolicyRefresher()"); + } + LOG.info("==> PolicyRefresher(serviceName=" + plugIn.getServiceName() + ").PolicyRefresher()"); + + RangerPluginConfig pluginConfig = plugIn.getConfig(); + String propertyPrefix = pluginConfig.getPropertyPrefix(); + + this.plugIn = plugIn; + this.serviceType = plugIn.getServiceType(); + this.serviceName = plugIn.getServiceName(); + this.cacheDir = pluginConfig.get(propertyPrefix + ".policy.cache.dir"); + + String appId = StringUtils.isEmpty(plugIn.getAppId()) ? serviceType : plugIn.getAppId(); + String cacheFilename = String.format("%s_%s.json", appId, serviceName); + + cacheFilename = cacheFilename.replace(File.separatorChar, '_'); + cacheFilename = cacheFilename.replace(File.pathSeparatorChar, '_'); + + this.cacheFileName = cacheFilename; + + Gson gson = null; + try { + gson = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z").create(); + } catch(Throwable excp) { + LOG.fatal("PolicyRefresher(): failed to create GsonBuilder object", excp); + } + + RangerPluginContext pluginContext = plugIn.getPluginContext(); + this.atlasAuthAdminClient = pluginContext.getAtlasAuthAdminClient(); + this.gson = gson; + this.rolesProvider = new RangerRolesProvider(getServiceType(), appId, getServiceName(), atlasAuthAdminClient, cacheDir, pluginConfig); + this.userStoreProvider = new RangerUserStoreProvider(getServiceType(), appId, getServiceName(), atlasAuthAdminClient, cacheDir, pluginConfig); + this.pollingIntervalMs = pluginConfig.getLong(propertyPrefix + ".policy.pollIntervalMs", 30 * 1000); + + this.enableDeltaBasedRefresh = AtlasConfiguration.DELTA_BASED_REFRESH_ENABLED.getBoolean(); + LOG.info("PolicyRefresher(serviceName=" + serviceName + ") - delta based policy refresh enabled="+this.enableDeltaBasedRefresh); + + setName("PolicyRefresher(serviceName=" + serviceName + ")-" + getId()); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== PolicyRefresher(serviceName=" + serviceName + ").PolicyRefresher()"); + } + } + + /** + * @return the plugIn + */ + public RangerBasePlugin getPlugin() { + return plugIn; + } + + /** + * @return the serviceType + */ + public String getServiceType() { + return serviceType; + } + + /** + * @return the serviceName + */ + public String getServiceName() { + return serviceName; + } + + public long getLastActivationTimeInMillis() { + return lastActivationTimeInMillis; + } + + public void setLastActivationTimeInMillis(long lastActivationTimeInMillis) { + this.lastActivationTimeInMillis = lastActivationTimeInMillis; + } + + public void startRefresher() { + loadRoles(); + loadPolicy(); + loadUserStore(); + super.start(); + + policyDownloadTimer = new Timer("policyDownloadTimer", true); + + try { + policyDownloadTimer.schedule(new DownloaderTask(policyDownloadQueue), pollingIntervalMs, pollingIntervalMs); + + LOG.info("Scheduled policyDownloadRefresher to download policies every " + pollingIntervalMs + " milliseconds"); + + } catch (IllegalStateException exception) { + LOG.error("Error scheduling policyDownloadTimer:", exception); + LOG.error("*** Policies will NOT be downloaded every " + pollingIntervalMs + " milliseconds ***"); + + policyDownloadTimer = null; + } + + } + + public void stopRefresher() { + + Timer policyDownloadTimer = this.policyDownloadTimer; + + this.policyDownloadTimer = null; + + if (policyDownloadTimer != null) { + policyDownloadTimer.cancel(); + } + + if (super.isAlive()) { + super.interrupt(); + + boolean setInterrupted = false; + boolean isJoined = false; + + while (!isJoined) { + try { + super.join(); + isJoined = true; + } catch (InterruptedException excp) { + LOG.warn("PolicyRefresher(serviceName=" + serviceName + "): error while waiting for thread to exit", excp); + LOG.warn("Retrying Thread.join(). Current thread will be marked as 'interrupted' after Thread.join() returns"); + setInterrupted = true; + } + } + if (setInterrupted) { + Thread.currentThread().interrupt(); + } + } + } + + public void run() { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> PolicyRefresher(serviceName=" + serviceName + ").run()"); + } + + while(true) { + DownloadTrigger trigger = null; + try { + trigger = policyDownloadQueue.take(); + + loadRoles(); + loadPolicy(); + loadUserStore(); + } catch(InterruptedException excp) { + LOG.info("PolicyRefreshxer(serviceName=" + serviceName + ").run(): interrupted! Exiting thread", excp); + break; + } finally { + if (trigger != null) { + trigger.signalCompletion(); + } + } + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== PolicyRefresher(serviceName=" + serviceName + ").run()"); + } + } + + public void syncPoliciesWithAdmin(DownloadTrigger token) throws InterruptedException { + policyDownloadQueue.put(token); + token.waitForCompletion(); + } + + private void loadPolicy() { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> PolicyRefresher(serviceName=" + serviceName + ").loadPolicy()"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "PolicyRefresher.loadPolicy(serviceName=" + serviceName + ")"); + long freeMemory = Runtime.getRuntime().freeMemory(); + long totalMemory = Runtime.getRuntime().totalMemory(); + PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory-freeMemory) + ", Free memory:" + freeMemory); + } + + try { + //load policy from PolicyAdmin + ServicePolicies svcPolicies = loadPolicyfromPolicyAdmin(); + + if (svcPolicies == null) { + //if Policy fetch from Policy Admin Fails, load from cache + if (!policiesSetInPlugin) { + svcPolicies = loadFromCache(); + } + } + + if (PERF_POLICYENGINE_INIT_LOG.isDebugEnabled()) { + long freeMemory = Runtime.getRuntime().freeMemory(); + long totalMemory = Runtime.getRuntime().totalMemory(); + PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory - freeMemory) + ", Free memory:" + freeMemory); + } + + if (svcPolicies != null) { + plugIn.setPolicies(svcPolicies); + policiesSetInPlugin = true; + serviceDefSetInPlugin = false; + setLastActivationTimeInMillis(System.currentTimeMillis()); + lastKnownVersion = svcPolicies.getPolicyVersion() != null ? svcPolicies.getPolicyVersion() : -1L; + lastUpdatedTimeInMillis = svcPolicies.getPolicyUpdateTime() != null ? svcPolicies.getPolicyUpdateTime().getTime() : -1L; + } else { + if (!policiesSetInPlugin && !serviceDefSetInPlugin) { + plugIn.setPolicies(null); + serviceDefSetInPlugin = true; + } + } + } catch (RangerServiceNotFoundException snfe) { + if (!serviceDefSetInPlugin) { + disableCache(); + plugIn.setPolicies(null); + serviceDefSetInPlugin = true; + setLastActivationTimeInMillis(System.currentTimeMillis()); + lastKnownVersion = -1; + lastUpdatedTimeInMillis = -1; + } + } catch (Exception excp) { + LOG.error("Encountered unexpected exception!!!!!!!!!!! Message:" + excp.getMessage() + "Stacktrace: " + excp.getStackTrace().toString(), excp); + } + + RangerPerfTracer.log(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== PolicyRefresher(serviceName=" + serviceName + ").loadPolicy()"); + } + } + + private ServicePolicies loadPolicyfromPolicyAdmin() throws RangerServiceNotFoundException { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> PolicyRefresher(serviceName=" + serviceName + ").loadPolicyfromPolicyAdmin()"); + } + + ServicePolicies svcPolicies = null; + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "PolicyRefresher.loadPolicyFromPolicyAdmin(serviceName=" + serviceName + ")"); + } + + try { + + if (serviceName.equals("atlas") && plugIn.getTypeRegistry() != null && lastUpdatedTimeInMillis == -1) { + LOG.info("PolicyRefresher(serviceName=" + serviceName + "): loading all policies for first time"); + RangerRESTUtils restUtils = new RangerRESTUtils(); + CachePolicyTransformerImpl transformer = new CachePolicyTransformerImpl(plugIn.getTypeRegistry()); + + svcPolicies = transformer.getPoliciesAll(serviceName, + restUtils.getPluginId(serviceName, plugIn.getAppId()), + lastUpdatedTimeInMillis); + } else { + LOG.info("PolicyRefresher(serviceName=" + serviceName + "): loading delta policies from last known version=" + lastKnownVersion + ", lastUpdatedTime=" + lastUpdatedTimeInMillis); + + svcPolicies = atlasAuthAdminClient.getServicePoliciesIfUpdated(lastUpdatedTimeInMillis, this.enableDeltaBasedRefresh); + } + + boolean isUpdated = svcPolicies != null; + + if(isUpdated) { + long newVersion = svcPolicies.getPolicyVersion() == null ? -1 : svcPolicies.getPolicyVersion().longValue(); + + if(!StringUtils.equals(serviceName, svcPolicies.getServiceName())) { + LOG.warn("PolicyRefresher(serviceName=" + serviceName + "): ignoring unexpected serviceName '" + svcPolicies.getServiceName() + "' in service-store"); + + svcPolicies.setServiceName(serviceName); + } + + LOG.info("PolicyRefresher(serviceName=" + serviceName + "): found updated version. lastKnownVersion=" + lastKnownVersion + "; newVersion=" + newVersion); + + } else { + if(LOG.isDebugEnabled()) { + LOG.debug("PolicyRefresher(serviceName=" + serviceName + ").run(): no update found. lastKnownVersion=" + lastKnownVersion); + } + } + } catch (Exception excp) { + LOG.error("PolicyRefresher(serviceName=" + serviceName + "): failed to refresh policies. Will continue to use last known version of policies (" + lastKnownVersion + ")", excp); + svcPolicies = null; + } + + RangerPerfTracer.log(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== PolicyRefresher(serviceName=" + serviceName + ").loadPolicyfromPolicyAdmin()"); + } + + return svcPolicies; + } + + private ServicePolicies loadFromCache() { + + ServicePolicies policies = null; + + if(LOG.isDebugEnabled()) { + LOG.debug("==> PolicyRefresher(serviceName=" + serviceName + ").loadFromCache()"); + } + + File cacheFile = cacheDir == null ? null : new File(cacheDir + File.separator + cacheFileName); + + if(cacheFile != null && cacheFile.isFile() && cacheFile.canRead()) { + Reader reader = null; + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "PolicyRefresher.loadFromCache(serviceName=" + serviceName + ")"); + } + + try { + reader = new FileReader(cacheFile); + + policies = gson.fromJson(reader, ServicePolicies.class); + + if(policies != null) { + if(!StringUtils.equals(serviceName, policies.getServiceName())) { + LOG.warn("ignoring unexpected serviceName '" + policies.getServiceName() + "' in cache file '" + cacheFile.getAbsolutePath() + "'"); + + policies.setServiceName(serviceName); + } + + lastKnownVersion = policies.getPolicyVersion() == null ? -1 : policies.getPolicyVersion().longValue(); + lastUpdatedTimeInMillis = policies.getPolicyUpdateTime() == null ? -1 : policies.getPolicyUpdateTime().getTime(); + } + } catch (Exception excp) { + LOG.error("failed to load policies from cache file " + cacheFile.getAbsolutePath(), excp); + } finally { + RangerPerfTracer.log(perf); + + if(reader != null) { + try { + reader.close(); + } catch(Exception excp) { + LOG.error("error while closing opened cache file " + cacheFile.getAbsolutePath(), excp); + } + } + } + } else { + LOG.warn("cache file does not exist or not readable '" + (cacheFile == null ? null : cacheFile.getAbsolutePath()) + "'"); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== PolicyRefresher(serviceName=" + serviceName + ").loadFromCache()"); + } + + return policies; + } + public void saveToCache(ServicePolicies policies) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> PolicyRefresher(serviceName=" + serviceName + ").saveToCache()"); + } + + if(policies != null) { + File cacheFile = null; + if (cacheDir != null) { + // Create the cacheDir if it doesn't already exist + File cacheDirTmp = new File(cacheDir); + if (cacheDirTmp.exists()) { + cacheFile = new File(cacheDir + File.separator + cacheFileName); + } else { + try { + cacheDirTmp.mkdirs(); + cacheFile = new File(cacheDir + File.separator + cacheFileName); + } catch (SecurityException ex) { + LOG.error("Cannot create cache directory", ex); + } + } + } + + if(cacheFile != null) { + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "PolicyRefresher.saveToCache(serviceName=" + serviceName + ")"); + } + + Writer writer = null; + + try { + writer = new FileWriter(cacheFile); + + gson.toJson(policies, writer); + } catch (Exception excp) { + LOG.error("failed to save policies to cache file '" + cacheFile.getAbsolutePath() + "'", excp); + } finally { + if(writer != null) { + try { + writer.close(); + } catch(Exception excp) { + LOG.error("error while closing opened cache file '" + cacheFile.getAbsolutePath() + "'", excp); + } + } + } + + RangerPerfTracer.log(perf); + + } + } else { + LOG.info("policies is null. Nothing to save in cache"); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== PolicyRefresher(serviceName=" + serviceName + ").saveToCache()"); + } + } + + private void disableCache() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> PolicyRefresher.disableCache(serviceName=" + serviceName + ")"); + } + + File cacheFile = cacheDir == null ? null : new File(cacheDir + File.separator + cacheFileName); + + if(cacheFile != null && cacheFile.isFile() && cacheFile.canRead()) { + LOG.warn("Cleaning up local cache"); + String renamedCacheFile = cacheFile.getAbsolutePath() + "_" + System.currentTimeMillis(); + if (!cacheFile.renameTo(new File(renamedCacheFile))) { + LOG.error("Failed to move " + cacheFile.getAbsolutePath() + " to " + renamedCacheFile); + } else { + LOG.warn("Moved " + cacheFile.getAbsolutePath() + " to " + renamedCacheFile); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("No local policy cache found. No need to disable it!"); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== PolicyRefresher.disableCache(serviceName=" + serviceName + ")"); + } + } + + private void loadRoles() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> PolicyRefresher(serviceName=" + serviceName + ").loadRoles()"); + } + + //Load the Ranger UserGroup Roles + rolesProvider.loadUserGroupRoles(plugIn); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== PolicyRefresher(serviceName=" + serviceName + ").loadRoles()"); + } + } + + private void loadUserStore() { + if(LOG.isDebugEnabled()) { + LOG.debug("==> PolicyRefresher(serviceName=" + serviceName + ").loadGroups()"); + } + + //Load the Ranger UserGroup Roles + userStoreProvider.loadUserStore(plugIn); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== PolicyRefresher(serviceName=" + serviceName + ").loadRoles()"); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerAccessRequestUtil.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerAccessRequestUtil.java new file mode 100644 index 00000000000..3a37ecdc1ed --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerAccessRequestUtil.java @@ -0,0 +1,187 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.contextenricher.RangerTagForEval; +import org.apache.atlas.plugin.policyengine.RangerAccessResource; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class RangerAccessRequestUtil { + private static final Log LOG = LogFactory.getLog(RangerAccessRequestUtil.class); + + public static final String KEY_CONTEXT_TAGS = "TAGS"; + public static final String KEY_CONTEXT_TAG_OBJECT = "TAG_OBJECT"; + public static final String KEY_CONTEXT_RESOURCE = "RESOURCE"; + public static final String KEY_CONTEXT_REQUESTED_RESOURCES = "REQUESTED_RESOURCES"; + public static final String KEY_CONTEXT_USERSTORE = "USERSTORE"; + public static final String KEY_TOKEN_NAMESPACE = "token:"; + public static final String KEY_USER = "USER"; + public static final String KEY_OWNER = "OWNER"; + public static final String KEY_ROLES = "ROLES"; + public static final String KEY_CONTEXT_ACCESSTYPES = "ACCESSTYPES"; + public static final String KEY_CONTEXT_IS_ANY_ACCESS = "ISANYACCESS"; + + public static void setRequestTagsInContext(Map context, Set tags) { + if(CollectionUtils.isEmpty(tags)) { + context.remove(KEY_CONTEXT_TAGS); + } else { + context.put(KEY_CONTEXT_TAGS, tags); + } + } + + public static Set getRequestTagsFromContext(Map context) { + Set ret = null; + Object val = context.get(RangerAccessRequestUtil.KEY_CONTEXT_TAGS); + + if (val instanceof Set) { + try { + @SuppressWarnings("unchecked") + Set tags = (Set) val; + + ret = tags; + } catch (Throwable t) { + LOG.error("getRequestTags(): failed to get tags from context", t); + } + } + + return ret; + } + + public static void setCurrentTagInContext(Map context, RangerTagForEval tag) { + context.put(KEY_CONTEXT_TAG_OBJECT, tag); + } + + public static RangerTagForEval getCurrentTagFromContext(Map context) { + RangerTagForEval ret = null; + Object val = context.get(KEY_CONTEXT_TAG_OBJECT); + + if(val instanceof RangerTagForEval) { + ret = (RangerTagForEval)val; + } + + return ret; + } + + public static void setRequestedResourcesInContext(Map context, RangerRequestedResources resources) { + context.put(KEY_CONTEXT_REQUESTED_RESOURCES, resources); + } + + public static RangerRequestedResources getRequestedResourcesFromContext(Map context) { + RangerRequestedResources ret = null; + Object val = context.get(KEY_CONTEXT_REQUESTED_RESOURCES); + + if(val instanceof RangerRequestedResources) { + ret = (RangerRequestedResources)val; + } + + return ret; + } + + public static void setCurrentResourceInContext(Map context, RangerAccessResource resource) { + context.put(KEY_CONTEXT_RESOURCE, resource); + } + + public static RangerAccessResource getCurrentResourceFromContext(Map context) { + RangerAccessResource ret = null; + Object val = MapUtils.isNotEmpty(context) ? context.get(KEY_CONTEXT_RESOURCE) : null; + + if(val instanceof RangerAccessResource) { + ret = (RangerAccessResource)val; + } + + return ret; + } + + public static Map copyContext(Map context) { + final Map ret; + + if(MapUtils.isEmpty(context)) { + ret = new HashMap<>(); + } else { + ret = new HashMap<>(context); + + ret.remove(KEY_CONTEXT_TAGS); + ret.remove(KEY_CONTEXT_TAG_OBJECT); + ret.remove(KEY_CONTEXT_RESOURCE); + // don't remove REQUESTED_RESOURCES + } + + return ret; + } + + public static void setCurrentUserInContext(Map context, String user) { + setTokenInContext(context, KEY_USER, user); + } + public static void setOwnerInContext(Map context, String owner) { + setTokenInContext(context, KEY_OWNER, owner); + } + public static String getCurrentUserFromContext(Map context) { + Object ret = getTokenFromContext(context, KEY_USER); + return ret != null ? ret.toString() : ""; + } + + public static void setTokenInContext(Map context, String tokenName, Object tokenValue) { + String tokenNameWithNamespace = KEY_TOKEN_NAMESPACE + tokenName; + context.put(tokenNameWithNamespace, tokenValue); + } + public static Object getTokenFromContext(Map context, String tokenName) { + String tokenNameWithNamespace = KEY_TOKEN_NAMESPACE + tokenName; + return MapUtils.isNotEmpty(context) ? context.get(tokenNameWithNamespace) : null; + } + + public static void setCurrentUserRolesInContext(Map context, Set roles) { + setTokenInContext(context, KEY_ROLES, roles); + } + public static Set getCurrentUserRolesFromContext(Map context) { + Object ret = getTokenFromContext(context, KEY_ROLES); + return ret != null ? (Set) ret : Collections.EMPTY_SET; + } + + public static void setRequestUserStoreInContext(Map context, RangerUserStore rangerUserStore) { + context.put(KEY_CONTEXT_USERSTORE, rangerUserStore); + } + + public static RangerUserStore getRequestUserStoreFromContext(Map context) { + RangerUserStore ret = null; + Object val = context.get(KEY_CONTEXT_USERSTORE); + + if(val instanceof RangerUserStore) { + ret = (RangerUserStore) val; + } + + return ret; + } + + public static void setIsAnyAccessInContext(Map context, Boolean value) { + context.put(KEY_CONTEXT_IS_ANY_ACCESS, value); + } + + public static Boolean getIsAnyAccessInContext(Map context) { + return (Boolean)context.get(KEY_CONTEXT_IS_ANY_ACCESS); + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerCommonConstants.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerCommonConstants.java new file mode 100644 index 00000000000..da939a7ad0f --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerCommonConstants.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +public class RangerCommonConstants { + + public static final String PROP_COOKIE_NAME = "ranger.admin.cookie.name"; + public static final String DEFAULT_COOKIE_NAME = "RANGERADMINSESSIONID"; + + public static final String RANGER_ADMIN_SUFFIX_POLICY_DELTA = ".supports.policy.deltas"; + public static final String PLUGIN_CONFIG_SUFFIX_POLICY_DELTA = ".supports.policy.deltas"; + + public static final String RANGER_ADMIN_SUFFIX_TAG_DELTA = ".supports.tag.deltas"; + public static final String PLUGIN_CONFIG_SUFFIX_TAG_DELTA = ".supports.tag.deltas"; + + public static final String RANGER_ADMIN_SUFFIX_IN_PLACE_POLICY_UPDATES = ".supports.in.place.policy.updates"; + public static final String PLUGIN_CONFIG_SUFFIX_IN_PLACE_POLICY_UPDATES = ".supports.in.place.policy.updates"; + + public static final String RANGER_ADMIN_SUFFIX_IN_PLACE_TAG_UPDATES = ".supports.in.place.tag.updates"; + public static final String PLUGIN_CONFIG_SUFFIX_IN_PLACE_TAG_UPDATES = ".supports.in.place.tag.updates"; + + public static final boolean RANGER_ADMIN_SUFFIX_POLICY_DELTA_DEFAULT = false; + public static final boolean PLUGIN_CONFIG_SUFFIX_POLICY_DELTA_DEFAULT = false; + + public static final boolean RANGER_ADMIN_SUFFIX_TAG_DELTA_DEFAULT = false; + public static final boolean PLUGIN_CONFIG_SUFFIX_TAG_DELTA_DEFAULT = false; + + public static final boolean RANGER_ADMIN_SUFFIX_IN_PLACE_POLICY_UPDATES_DEFAULT = false; + public static final boolean PLUGIN_CONFIG_SUFFIX_IN_PLACE_POLICY_UPDATES_DEFAULT = false; + + public static final boolean RANGER_ADMIN_SUFFIX_IN_PLACE_TAG_UPDATES_DEFAULT = false; + public static final boolean PLUGIN_CONFIG_SUFFIX_IN_PLACE_TAG_UPDATES_DEFAULT = false; + + public static final boolean POLICY_REST_CLIENT_SESSION_COOKIE_ENABLED = true; + + public static final String SCRIPT_OPTION_ENABLE_JSON_CTX = "enableJsonCtx"; + public static final String SCRIPT_VAR_CONTEXT = "_ctx"; + public static final String SCRIPT_VAR_CONTEXT_JSON = "_ctx_json"; + public static final String SCRIPT_FIELD_ACCESS_TIME = "accessTime"; + public static final String SCRIPT_FIELD_ACCESS_TYPE = "accessType"; + public static final String SCRIPT_FIELD_ACTION = "action"; + public static final String SCRIPT_FIELD_CLIENT_IP_ADDRESS = "clientIPAddress"; + public static final String SCRIPT_FIELD_CLIENT_TYPE = "clientType"; + public static final String SCRIPT_FIELD_CLUSTER_NAME = "clusterName"; + public static final String SCRIPT_FIELD_CLUSTER_TYPE = "clusterType"; + public static final String SCRIPT_FIELD_FORWARDED_ADDRESSES = "forwardedAddresses"; + public static final String SCRIPT_FIELD_REMOTE_IP_ADDRESS = "remoteIPAddress"; + public static final String SCRIPT_FIELD_REQUEST_DATA = "requestData"; + public static final String SCRIPT_FIELD_RESOURCE = "resource"; + public static final String SCRIPT_FIELD_RESOURCE_OWNER_USER = "resourceOwnerUser"; + public static final String SCRIPT_FIELD_RESOURCE_MATCHING_SCOPE = "resourceMatchingScope"; + public static final String SCRIPT_FIELD_TAG = "tag"; + public static final String SCRIPT_FIELD_TAGS = "tags"; + public static final String SCRIPT_FIELD_USER = "user"; + public static final String SCRIPT_FIELD_USER_ATTRIBUTES = "userAttributes"; + public static final String SCRIPT_FIELD_USER_GROUPS = "userGroups"; + public static final String SCRIPT_FIELD_USER_GROUP_ATTRIBUTES = "userGroupAttributes"; + public static final String SCRIPT_FIELD_USER_ROLES = "userRoles"; + public static final String SCRIPT_FIELD_REQUEST = "request"; +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerMetricsUtil.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerMetricsUtil.java new file mode 100644 index 00000000000..ee7516ed211 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerMetricsUtil.java @@ -0,0 +1,189 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import com.google.gson.Gson; +import org.apache.commons.lang.StringUtils; +import org.apache.atlas.plugin.model.RangerMetrics; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FileWriter; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; +import java.lang.management.MemoryPoolMXBean; +import java.lang.management.MemoryType; +import java.lang.management.MemoryUsage; +import java.lang.management.OperatingSystemMXBean; +import java.lang.management.RuntimeMXBean; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Connect Worker system and runtime information. + */ +public class RangerMetricsUtil { + + private static final Logger LOG = LoggerFactory.getLogger(RangerMetricsUtil.class); + private static final OperatingSystemMXBean OS; + private static final MemoryMXBean MEM_BEAN; + public static final String NL = System.getProperty("line.separator"); + + private static final RuntimeMXBean RUNTIME = ManagementFactory.getRuntimeMXBean(); + private static final String JVM_MACHINE_ACTUAL_NAME = RUNTIME.getVmName(); + private static final String VERSION = RUNTIME.getVmVersion(); + private static final String JVM_MACHINE_REPRESENTATION_NAME = RUNTIME.getName(); + private static final long UP_TIME_OF_JVM = RUNTIME.getUptime(); + private static final String JVM_VENDOR_NAME = RUNTIME.getVmVendor(); + + + static { + OS = ManagementFactory.getOperatingSystemMXBean(); + MEM_BEAN = ManagementFactory.getMemoryMXBean(); + } + + public Map getValues() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerMetricsUtil.getValues()"); + } + + Map values = new LinkedHashMap<>(); + values.put("os.spec", StringUtils.join(Arrays.asList(addSystemInfo()), ", ")); + values.put("os.vcpus", String.valueOf(OS.getAvailableProcessors())); + values.put("memory", addMemoryDetails()); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerMetricsUtil.getValues()" + values); + } + + return values; + } + + /** + * collect the pool division of java + */ + protected Map getPoolDivision() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerMetricsUtil.getPoolDivision()"); + } + + Map poolDivisionValues = new LinkedHashMap<>(); + for (MemoryPoolMXBean mpBean : ManagementFactory.getMemoryPoolMXBeans()) { + if (mpBean.getType() == MemoryType.HEAP) { + poolDivisionValues.put(mpBean.getName(), mpBean.getUsage()); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerMetricsUtil.getPoolDivision()" + poolDivisionValues); + } + + return poolDivisionValues; + } + + /** + * Add memory details + */ + protected Map addMemoryDetails() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerMetricsUtil.addMemoryDetails()"); + } + + Map memory = new LinkedHashMap<>(); + MemoryUsage memHeapUsage = MEM_BEAN.getHeapMemoryUsage(); + MemoryUsage nonHeapUsage = MEM_BEAN.getNonHeapMemoryUsage(); + memory.put("heapInit", String.valueOf(memHeapUsage.getInit())); + memory.put("heapMax", String.valueOf(memHeapUsage.getMax())); + memory.put("heapCommitted", String.valueOf(memHeapUsage.getCommitted())); + memory.put("heapUsed", String.valueOf(memHeapUsage.getUsed())); + memory.put("nonHeapInit", String.valueOf(nonHeapUsage.getInit())); + memory.put("nonHeapMax", String.valueOf(nonHeapUsage.getMax())); + memory.put("nonHeapCommitted", String.valueOf(nonHeapUsage.getCommitted())); + memory.put("nonHeapUsed", String.valueOf(nonHeapUsage.getUsed())); + memory.put("memory_pool_usages", getPoolDivision()); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerMetricsUtil.addMemoryDetails()" + memory); + } + + return memory; + } + + /** + * Collect system information. + */ + protected String[] addSystemInfo() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerMetricsUtil.addSystemInfo()"); + } + + String[] osInfo = { OS.getName(), OS.getArch(), OS.getVersion() }; + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerMetricsUtil.addSystemInfo()" + osInfo); + } + + return osInfo; + } + + public RangerMetrics getVMStatus() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerMetricsUtil.getVMStatus()"); + } + + Map jvm = new LinkedHashMap<>(); + Map vmDetails = new LinkedHashMap<>(); + vmDetails.put("JVM Machine Actual Name", JVM_MACHINE_ACTUAL_NAME); + vmDetails.put("version", VERSION); + vmDetails.put("JVM Machine Representation Name", JVM_MACHINE_REPRESENTATION_NAME); + vmDetails.put("Up time of JVM", UP_TIME_OF_JVM); + vmDetails.put("JVM Vendor Name", JVM_VENDOR_NAME); + vmDetails.putAll(getValues()); + jvm.put("jvm", vmDetails); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerMetricsUtil.getVMStatus() " + jvm); + } + + return new RangerMetrics(jvm); + } + + public void writeMetricsToFile(File filePath) throws Throwable { + + RangerMetrics rangerMetrics = null; + rangerMetrics = getVMStatus(); + if (null == rangerMetrics || null == filePath) { + LOG.debug("RangerMetrics or filePath can not be null)"); + return; + } + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerMetricsUtil.writeMetricsToFIle() for path: "+ filePath); + } + Gson gson = new Gson(); + try (FileWriter file = new FileWriter(filePath)) { + gson.toJson(rangerMetrics, file); + file.flush(); + } catch (Exception e ) { + LOG.error("RangerMetricsUtil.writeMetricsToFile() got an error",e); + throw e; + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerObjectFactory.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerObjectFactory.java new file mode 100644 index 00000000000..72c2f68287f --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerObjectFactory.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicyResourceSignature; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.validation.RangerServiceDefHelper; + +public class RangerObjectFactory { + public RangerPolicyResourceSignature createPolicyResourceSignature(RangerPolicy policy) { + return new RangerPolicyResourceSignature(policy); + } + + public RangerServiceDefHelper createServiceDefHelper(RangerServiceDef serviceDef) { + return new RangerServiceDefHelper(serviceDef); + } + + public RangerServiceDefHelper createServiceDefHelper(RangerServiceDef serviceDef, boolean useCache) { + return new RangerServiceDefHelper(serviceDef, useCache, true); + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPerfCollectorTracer.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPerfCollectorTracer.java new file mode 100644 index 00000000000..98990a64f87 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPerfCollectorTracer.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.commons.logging.Log; + +public class RangerPerfCollectorTracer extends RangerPerfTracer { + private final long startTimeNanos; + + public RangerPerfCollectorTracer(Log logger, String tag, String data) { + super(logger, tag, data); + startTimeNanos = System.nanoTime(); + } + + @Override + public void log() { + // Collect elapsed time in microseconds + PerfDataRecorder.recordStatistic(tag, ((System.nanoTime() - startTimeNanos) + 500) / 1000); + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPerfTracer.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPerfTracer.java new file mode 100644 index 00000000000..e34d7ae690b --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPerfTracer.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class RangerPerfTracer { + protected final Log logger; + protected final String tag; + protected final String data; + private final long startTimeMs; + + private static long reportingThresholdMs; + + private final static String tagEndMarker = "("; + + public static Log getPerfLogger(String name) { + return LogFactory.getLog("org.apache.atlas.auth.perf." + name); + } + + public static Log getPerfLogger(Class cls) { + return RangerPerfTracer.getPerfLogger(cls.getName()); + } + + public static boolean isPerfTraceEnabled(Log logger) { + return logger.isDebugEnabled(); + } + + public static RangerPerfTracer getPerfTracer(Log logger, String tag) { + String data = ""; + String realTag = ""; + + if (tag != null) { + int indexOfTagEndMarker = StringUtils.indexOf(tag, tagEndMarker); + if (indexOfTagEndMarker != -1) { + realTag = StringUtils.substring(tag, 0, indexOfTagEndMarker); + data = StringUtils.substring(tag, indexOfTagEndMarker); + } else { + realTag = tag; + } + } + return RangerPerfTracerFactory.getPerfTracer(logger, realTag, data); + } + + public static RangerPerfTracer getPerfTracer(Log logger, String tag, String data) { + return RangerPerfTracerFactory.getPerfTracer(logger, tag, data); + } + + public static void log(RangerPerfTracer tracer) { + if(tracer != null) { + tracer.log(); + } + } + + public static void logAlways(RangerPerfTracer tracer) { + if(tracer != null) { + tracer.logAlways(); + } + } + public RangerPerfTracer(Log logger, String tag, String data) { + this.logger = logger; + this.tag = tag; + this.data = data; + startTimeMs = System.currentTimeMillis(); + } + + public final String getTag() { + return tag; + } + + public final long getStartTime() { + return startTimeMs; + } + + public final long getElapsedTime() { + return System.currentTimeMillis() - startTimeMs; + } + + public void log() { + long elapsedTime = getElapsedTime(); + if (elapsedTime > reportingThresholdMs) { + logger.debug("[PERF] " + tag + data + ": " + elapsedTime); + } + } + public void logAlways() { + long elapsedTime = getElapsedTime(); + logger.debug("[PERF] " + tag + data + ": " + elapsedTime); + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPerfTracerFactory.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPerfTracerFactory.java new file mode 100644 index 00000000000..24a7ca9d931 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPerfTracerFactory.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.commons.logging.Log; + +public class RangerPerfTracerFactory { + + static RangerPerfTracer getPerfTracer(Log logger, String tag, String data) { + + RangerPerfTracer ret = null; + + if (PerfDataRecorder.collectStatistics()) { + ret = new RangerPerfCollectorTracer(logger, tag, data); + } else if (logger.isDebugEnabled()) { + ret = new RangerPerfTracer(logger, tag, data); + } + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPluginCapability.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPluginCapability.java new file mode 100644 index 00000000000..dcd073ce6d1 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPluginCapability.java @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.atlas.authorization.utils.RangerUtil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class RangerPluginCapability { + + /* + - tag-policies + - allowExceptions/deny/denyExceptions + - masking/row-filtering + - Macros - like ${USER} + - tag-based masking/row-filtering + - audit mode support + - service-def changes - isValidLeaf + - validity periods + - policy priority + - security zones + - policy-level conditions + - deny AllElse policies + - roles + - role download timer + - Audit-excluded-users + - Chained plugins + - Super-user permission + - UserStore download + - Audit-policies + */ + private final long pluginCapabilities; + private static final String baseRangerCapabilities = computeBaseCapabilities(); + + // Any new RANGER_PLUGIN_CAPABILITY needs to be added to the end of this enum. Existing enumerator order should *NOT* be changed // + public enum RangerPluginFeature { + RANGER_PLUGIN_CAPABILITY_TAG_POLICIES("Tag Policies"), + RANGER_PLUGIN_CAPABILITY_MASKING_AND_ROW_FILTERING("Masking and Row-filtering"), + RANGER_PLUGIN_CAPABILITY_MACROS("Macros"), + RANGER_PLUGIN_CAPABILITY_AUDIT_MODE("Audit Mode"), + RANGER_PLUGIN_CAPABILITY_RESOURCE_IS_VALID_LEAF("Support for leaf node"), + RANGER_PLUGIN_CAPABILITY_VALIDITY_PERIOD("Validity Period"), + RANGER_PLUGIN_CAPABILITY_POLICY_PRIORITY("Policy Priority"), + RANGER_PLUGIN_CAPABILITY_SECURITY_ZONE("Security Zone"), + RANGER_PLUGIN_CAPABILITY_POLICY_LEVEL_CONDITION("Policy-level Condition"), + RANGER_PLUGIN_CAPABILITY_DENY_ALL_ELSE_POLICY("Deny-all-else Policy"), + RANGER_PLUGIN_CAPABILITY_ROLE("Role"), + RANGER_PLUGIN_CAPABILITY_ROLE_DOWNLOAD_TIMER("Role Timer"), + RANGER_PLUGIN_CAPABILITY_AUDIT_EXCLUDED_USERS("Audit-Excluded Users"), + RANGER_PLUGIN_CAPABILITY_CHAINED_PLUGINS("Chained Plugins"), + RANGER_PLUGIN_CAPABILITY_SUPERUSER_PERMISSIONS("Super-user Permissions"), + RANGER_PLUGIN_CAPABILITY_USERSTORE_DOWNLOAD("UserStore Download"), + RANGER_PLUGIN_CAPABILITY_AUDIT_POLICY("Audit Policy"); + + private final String name; + RangerPluginFeature(String name) { + this.name = name; + } + String getName() { return name; } + } + + + public RangerPluginCapability() { + + long vector = 0L; + for (RangerPluginFeature feature : RangerPluginFeature.values()) { + vector += 1L << feature.ordinal(); + } + pluginCapabilities = vector; + } + + public RangerPluginCapability(long pluginCapabilities) { + this.pluginCapabilities = pluginCapabilities; + } + + public RangerPluginCapability(List capabilities) { + + long vector = 0L; + + for (String capability : capabilities) { + RangerPluginFeature feature; + try { + feature = RangerPluginFeature.valueOf(capability); + vector += 1L << feature.ordinal(); + } catch (Exception e) { + // Ignore + } + } + this.pluginCapabilities = vector; + } + + public long getPluginCapabilities() { + return pluginCapabilities; + } + + public List compare(RangerPluginCapability other) { + final List ret; + + if (pluginCapabilities != other.pluginCapabilities) { + + long mismatchedCapabilitiesVector = this.pluginCapabilities ^ other.pluginCapabilities; + + List missingFeatures = toStrings(mismatchedCapabilitiesVector); + + if (mismatchedCapabilitiesVector > (1L << (RangerPluginFeature.values().length))) { + missingFeatures.add("unknown"); + } + + ret = missingFeatures; + } else { + ret = Collections.EMPTY_LIST; + } + + return ret; + } + + @Override + public String toString() { + List capabilities = toStrings(pluginCapabilities); + return RangerUtil.objectToJson(capabilities); + } + + public static String getBaseRangerCapabilities() { + return baseRangerCapabilities; + } + + private static List toStrings(long vector) { + + List ret = new ArrayList<>(); + + for (RangerPluginFeature feature : RangerPluginFeature.values()) { + long test = 1L << feature.ordinal(); + if ((test & vector) > 0) { + ret.add(feature.name()); + } + } + + return ret; + } + + + private static String computeBaseCapabilities() { + List baseCapabilities = Arrays.asList(RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_TAG_POLICIES.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_MASKING_AND_ROW_FILTERING.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_MACROS.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_AUDIT_MODE.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_RESOURCE_IS_VALID_LEAF.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_VALIDITY_PERIOD.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_POLICY_PRIORITY.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_SECURITY_ZONE.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_POLICY_LEVEL_CONDITION.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_DENY_ALL_ELSE_POLICY.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_ROLE.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_ROLE_DOWNLOAD_TIMER.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_AUDIT_EXCLUDED_USERS.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_CHAINED_PLUGINS.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_SUPERUSER_PERMISSIONS.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_USERSTORE_DOWNLOAD.getName() + , RangerPluginFeature.RANGER_PLUGIN_CAPABILITY_AUDIT_POLICY.getName()); + + return Long.toHexString(new RangerPluginCapability(baseCapabilities).getPluginCapabilities()); + } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPolicyDeltaUtil.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPolicyDeltaUtil.java new file mode 100644 index 00000000000..99faa9710bb --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerPolicyDeltaUtil.java @@ -0,0 +1,186 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicyDelta; +import org.apache.atlas.plugin.store.ServiceDefsUtil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class RangerPolicyDeltaUtil { + + private static final Log LOG = LogFactory.getLog(RangerPolicyDeltaUtil.class); + + private static final Log PERF_POLICY_DELTA_LOG = RangerPerfTracer.getPerfLogger("policy.delta"); + + public static List deletePoliciesByDelta(List policies, Map deltas) { + if (MapUtils.isNotEmpty(deltas)) { + List ret = new ArrayList<>(policies); + ret.removeIf(policy -> deltas.containsKey(policy.getAtlasGuid())); + return ret; + } else { + return policies; + } + } + + public static List applyDeltas(List policies, List deltas, String serviceType, String serviceName) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> applyDeltas(serviceType=" + serviceType + ")"); + } + + if (CollectionUtils.isEmpty(deltas)) { + if (LOG.isDebugEnabled()) { + LOG.debug("applyDeltas called with empty deltas. Returning policies without changes."); + } + return policies; + } + + boolean hasExpectedServiceName = deltas.stream().anyMatch(delta -> serviceName.equals(delta.getPolicy().getService())); + + if (!hasExpectedServiceName) { + if (LOG.isDebugEnabled()) { + LOG.debug("No deltas match the expected serviceType: " + serviceType); + } + return policies; + } + + List updatedPolicies = new ArrayList<>(policies); + + for (RangerPolicyDelta delta : deltas) { + if (!serviceName.equals(delta.getPolicy().getService())) { + continue; + } + + switch (delta.getChangeType()) { + case RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE: + case RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE: + updatedPolicies.add(delta.getPolicy()); + break; + default: + LOG.warn("Unexpected changeType in policyDelta: [" + delta.getPolicyGuid() + "]. Ignoring delta."); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== applyDeltas(serviceType=" + serviceType + "): " + updatedPolicies); + } + + return updatedPolicies; + } + + public static boolean isValidDeltas(List deltas, String componentServiceType) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> isValidDeltas(deltas=" + Arrays.toString(deltas.toArray()) + ", componentServiceType=" + componentServiceType +")"); + } + boolean isValid = true; + + for (RangerPolicyDelta delta : deltas) { + final Integer changeType = delta.getChangeType(); + final String policyGuid = delta.getPolicyGuid(); + + if (changeType == null) { + isValid = false; + break; + } + + if (changeType != RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE + && changeType != RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE + && changeType != RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE) { + isValid = false; + } else if (policyGuid == null) { + isValid = false; + } else { + final String serviceType = delta.getServiceType(); + final String policyType = delta.getPolicyType(); + + if (serviceType == null || (!serviceType.equals(ServiceDefsUtil.EMBEDDED_SERVICEDEF_TAG_NAME) && + !serviceType.equals(componentServiceType))) { + isValid = false; + } else if (StringUtils.isEmpty(policyType) || (!RangerPolicy.POLICY_TYPE_ACCESS.equals(policyType) + && !RangerPolicy.POLICY_TYPE_DATAMASK.equals(policyType) + && !RangerPolicy.POLICY_TYPE_ROWFILTER.equals(policyType))) { + isValid = false; + } + } + + if (!isValid) { + break; + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== isValidDeltas(deltas=" + Arrays.toString(deltas.toArray()) + ", componentServiceType=" + componentServiceType +"): " + isValid); + } + return isValid; + } + + public static Boolean hasPolicyDeltas(final ServicePolicies servicePolicies) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> hasPolicyDeltas(servicePolicies:[" + servicePolicies + "]"); + } + final Boolean ret; + + if (servicePolicies == null) { + LOG.error("ServicePolicies are null!"); + ret = null; + } else { + boolean isPoliciesExistInSecurityZones = false; + boolean isPolicyDeltasExistInSecurityZones = false; + + if (MapUtils.isNotEmpty(servicePolicies.getSecurityZones())) { + for (ServicePolicies.SecurityZoneInfo element : servicePolicies.getSecurityZones().values()) { + if (CollectionUtils.isNotEmpty(element.getPolicies()) && CollectionUtils.isEmpty(element.getPolicyDeltas())) { + isPoliciesExistInSecurityZones = true; + } + if (CollectionUtils.isEmpty(element.getPolicies()) && CollectionUtils.isNotEmpty(element.getPolicyDeltas())) { + isPolicyDeltasExistInSecurityZones = true; + } + } + } + + boolean isPoliciesExist = CollectionUtils.isNotEmpty(servicePolicies.getPolicies()) || (servicePolicies.getTagPolicies() != null && CollectionUtils.isNotEmpty(servicePolicies.getTagPolicies().getPolicies())) || isPoliciesExistInSecurityZones; + boolean isPolicyDeltasExist = CollectionUtils.isNotEmpty(servicePolicies.getPolicyDeltas()) || isPolicyDeltasExistInSecurityZones; + + if (isPoliciesExist && isPolicyDeltasExist) { + LOG.warn("ServicePolicies contain both policies and policy-deltas!! Cannot build policy-engine from these servicePolicies. Please check server-side code!"); + LOG.warn("Downloaded ServicePolicies for [" + servicePolicies.getServiceName() + "]"); + ret = null; + } else if (!isPoliciesExist && !isPolicyDeltasExist) { + LOG.warn("ServicePolicies do not contain any policies or policy-deltas!! There are no material changes in the policies."); + LOG.warn("Downloaded ServicePolicies for [" + servicePolicies.getServiceName() + "]"); + ret = null; + } else { + ret = isPolicyDeltasExist; + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== hasPolicyDeltas(servicePolicies:[" + servicePolicies + "], ret:[" + ret + "]"); + } + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerRESTUtils.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerRESTUtils.java new file mode 100644 index 00000000000..48ccc19051e --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerRESTUtils.java @@ -0,0 +1,164 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + + +//import com.kstruct.gethostname4j.Hostname; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Since this class does not retain any state. It isn't a singleton for testability. + * + */ +public class RangerRESTUtils { + + private static final Log LOG = LogFactory.getLog(RangerRESTUtils.class); + + public static final String REST_URL_POLICY_GET_FOR_SERVICE_IF_UPDATED = "/service/plugins/policies/download/"; + public static final String REST_URL_SERVICE_GRANT_ACCESS = "/service/plugins/services/grant/"; + public static final String REST_URL_SERVICE_REVOKE_ACCESS = "/service/plugins/services/revoke/"; + + public static final String REST_URL_POLICY_GET_FOR_SECURE_SERVICE_IF_UPDATED = "/service/plugins/secure/policies/download/"; + public static final String REST_URL_SECURE_SERVICE_GRANT_ACCESS = "/service/plugins/secure/services/grant/"; + public static final String REST_URL_SECURE_SERVICE_REVOKE_ACCESS = "/service/plugins/secure/services/revoke/"; + + public static final String REST_URL_SERVICE_CREATE_ROLE = "/service/public/v2/api/roles/"; + public static final String REST_URL_SERVICE_DROP_ROLE = "/service/public/v2/api/roles/name/"; + public static final String REST_URL_SERVICE_GET_ALL_ROLES = "/service/public/v2/api/roles/names/"; + public static final String REST_URL_SERVICE_GET_USER_ROLES = "/service/public/v2/api/roles/user/"; + public static final String REST_URL_SERVICE_GET_ROLE_INFO = "/service/public/v2/api/roles/name/"; + public static final String REST_URL_SERVICE_GRANT_ROLE = "/service/public/v2/api/roles/grant/"; + public static final String REST_URL_SERVICE_REVOKE_ROLE = "/service/public/v2/api/roles/revoke/"; + + public static final String REST_URL_SERVICE_SERCURE_GET_USER_GROUP_ROLES = "/service/roles/secure/download/"; + public static final String REST_URL_SERVICE_GET_USER_GROUP_ROLES = "/service/roles/download/"; + + public static final String REST_URL_GET_SERVICE_TAGS_IF_UPDATED = "/service/tags/download/"; + public static final String REST_URL_GET_SECURE_SERVICE_TAGS_IF_UPDATED = "/service/tags/secure/download/"; + public static final String SERVICE_NAME_PARAM = "serviceName"; + public static final String LAST_KNOWN_TAG_VERSION_PARAM = "lastKnownVersion"; + public static final String PATTERN_PARAM = "pattern"; + + public static final String REST_URL_LOOKUP_TAG_NAMES = "/service/tags/lookup"; + + public static final String REST_EXPECTED_MIME_TYPE = "application/json"; + public static final String REST_MIME_TYPE_JSON = "application/json"; + + public static final String REST_PARAM_LAST_KNOWN_POLICY_VERSION = "lastKnownVersion"; + public static final String REST_PARAM_LAST_ACTIVATION_TIME = "lastActivationTime"; + public static final String REST_PARAM_PLUGIN_ID = "pluginId"; + + public static final String REST_PARAM_LAST_KNOWN_ROLE_VERSION = "lastKnownRoleVersion"; + + public static final String REST_PARAM_LAST_KNOWN_USERSTORE_VERSION = "lastKnownUserStoreVersion"; + public static final String REST_URL_SERVICE_SERCURE_GET_USERSTORE = "/service/xusers/secure/download/"; + public static final String REST_URL_SERVICE_GET_USERSTORE = "/service/xusers/download/"; + + private static final int MAX_PLUGIN_ID_LEN = 255; + + public static final String REST_PARAM_CLUSTER_NAME = "clusterName"; + public static final String REST_PARAM_SUPPORTS_POLICY_DELTAS = "supportsPolicyDeltas"; + public static final String REST_PARAM_SUPPORTS_TAG_DELTAS = "supportsTagDeltas"; + + public static final String REST_PARAM_ZONE_NAME = "zoneName"; + public static final String REST_PARAM_EXEC_USER = "execUser"; + + public static final String REST_PARAM_CAPABILITIES = "pluginCapabilities"; + + public static String hostname; + + static { + try { + //hostname = Hostname.getHostname(); + hostname = InetAddress.getLocalHost().getHostName(); + } + catch(Exception e) { + LOG.error("ERROR: Unable to find hostname for the agent ", e); + hostname = "unknownHost"; + } + } + + public String getPluginId(String serviceName, String appId) { + String hostName = null; + + try { + hostName = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + LOG.error("ERROR: Unable to find hostname for the agent ", e); + hostName = "unknownHost"; + } + + String ret = hostName + "-" + serviceName; + + if(! StringUtils.isEmpty(appId)) { + ret = appId + "@" + ret; + } + + if (ret.length() > MAX_PLUGIN_ID_LEN ) { + ret = ret.substring(0,MAX_PLUGIN_ID_LEN); + } + + return ret ; + } + /* + * This method returns the hostname of agents. + */ + public String getAgentHostname() { + return hostname; + } + + public String getHostnameFromPluginId(String pluginId, String serviceName) { + String ret = ""; + + if (StringUtils.isNotBlank(pluginId)) { + int lastIndex; + String[] parts = pluginId.split("@"); + int index = parts.length > 1 ? 1 : 0; + if (StringUtils.isNotBlank(serviceName)) { + lastIndex = StringUtils.lastIndexOf(parts[index], serviceName); + if (lastIndex > 1) { + ret = parts[index].substring(0, lastIndex-1); + } + } else { + lastIndex = StringUtils.lastIndexOf(parts[index], "-"); + if (lastIndex > 0) { + ret = parts[index].substring(0, lastIndex); + } + } + } + + return ret; + } + public String getAppIdFromPluginId(String pluginId) { + String ret = "**Unknown**"; + + if (StringUtils.isNotBlank(pluginId)) { + String[] parts = pluginId.split("@"); + ret = parts[0]; + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerReadWriteLock.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerReadWriteLock.java new file mode 100644 index 00000000000..06af2dc6863 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerReadWriteLock.java @@ -0,0 +1,98 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +public class RangerReadWriteLock { + + private static final RangerLock NO_OP_LOCK = new RangerLock(null); + + private final ReentrantReadWriteLock lock; + + public RangerReadWriteLock(boolean isUseLock) { + lock = isUseLock ? new ReentrantReadWriteLock(true) : null; + } + + public RangerLock getReadLock() { + final RangerLock ret; + if (lock != null) { + ReentrantReadWriteLock.ReadLock readLock = lock.readLock(); + readLock.lock(); + ret = new RangerLock(readLock); + } else { + ret = NO_OP_LOCK; + } + return ret; + } + + public RangerLock getWriteLock() { + final RangerLock ret; + if (lock != null) { + boolean isLocked = false; + ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock(); + while (!isLocked) { + isLocked = writeLock.tryLock(); + // Another thread has acquired write lock. Hint to scheduler to schedule some other thread if needed + if (!isLocked && lock.getReadLockCount() == 0) { + Thread.yield(); + } + } + ret = new RangerLock(writeLock); + } else { + ret = NO_OP_LOCK; + } + return ret; + } + + @Override + public String toString() { + if (lock != null) { + return "ReadWriteLock:[" + lock.toString() + "], ReadLock:[" + lock.readLock().toString() + "], WriteLock:[" + lock.writeLock().toString() + "]"; + } else { + return "ReadWriteLock:[null]"; + } + } + + static final public class RangerLock implements AutoCloseable { + private final Lock lock; + + private RangerLock(Lock lock) { + this.lock = lock; + } + + @Override + public void close() { + if (lock != null) { + lock.unlock(); + } + } + + public boolean isLockingEnabled() { + return lock != null; + } + + @Override + public String toString() { + return lock == null ? "null" : lock.toString(); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerRequestedResources.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerRequestedResources.java new file mode 100644 index 00000000000..999d2ecd542 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerRequestedResources.java @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you 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 org.apache.atlas.plugin.util; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.apache.commons.collections.CollectionUtils; +import org.apache.atlas.plugin.policyengine.RangerAccessResource; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) +/*@JsonAutoDetect(getterVisibility= JsonAutoDetect.Visibility.NONE, setterVisibility= JsonAutoDetect.Visibility.NONE, fieldVisibility= JsonAutoDetect.Visibility.ANY) +@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL ) +@JsonIgnoreProperties(ignoreUnknown=true)*/ +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) + +public class RangerRequestedResources { + private List requestedResources = new ArrayList<>(); + + public RangerRequestedResources() { + } + + public void addRequestedResource(RangerAccessResource requestedResource) { + if (requestedResource != null) { + + if (CollectionUtils.isEmpty(requestedResources)) { + requestedResources = new ArrayList<>(); + } + + boolean exists = requestedResources.contains(requestedResource); + + if (!exists) { + requestedResources.add(requestedResource); + } + } + } + + public boolean isMutuallyExcluded(final List matchers, final Map evalContext) { + boolean ret = true; + + int matchedCount = 0; + + if (!CollectionUtils.isEmpty(matchers) && !CollectionUtils.isEmpty(requestedResources) && requestedResources.size() > 1) { + + for (RangerAccessResource resource : requestedResources) { + + for (RangerPolicyResourceMatcher matcher : matchers) { + + if (matcher.isMatch(resource, evalContext) && matchedCount++ > 0) { + ret = false; + break; + } + } + } + } + + return ret; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + StringBuilder toString(StringBuilder sb) { + sb.append("AllRequestedHiveResources={"); + for (RangerAccessResource resource : requestedResources) { + if (resource != null) { + sb.append(resource.getAsString()); + sb.append("; "); + } + } + sb.append("} "); + + return sb; + } +} + + diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerRolesProvider.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerRolesProvider.java new file mode 100644 index 00000000000..dc44402046c --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerRolesProvider.java @@ -0,0 +1,374 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.apache.atlas.authz.admin.client.AtlasAuthAdminClient; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.atlas.plugin.service.RangerBasePlugin; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.Date; +import java.util.HashSet; + + +public class RangerRolesProvider { + private static final Log LOG = LogFactory.getLog(RangerRolesProvider.class); + + private static final Log PERF_POLICYENGINE_INIT_LOG = RangerPerfTracer.getPerfLogger("policyengine.init"); + + private final String serviceType; + private final String serviceName; + private final AtlasAuthAdminClient atlasAuthAdminClient; + private final KeycloakUserStore keycloakUserStore; + + private final String cacheFileName; + private final String cacheFileNamePrefix; + private final String cacheDir; + private final Gson gson; + private final boolean disableCacheIfServiceNotFound; + + private long lastUpdatedTimeInMillis = -1; + private long lastActivationTimeInMillis; + private long lastKnownRoleVersion = -1L; + private boolean rangerUserGroupRolesSetInPlugin; + private boolean serviceDefSetInPlugin; + + public RangerRolesProvider(String serviceType, String appId, String serviceName, AtlasAuthAdminClient atlasAuthAdminClient, String cacheDir, Configuration config) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerRolesProvider(serviceName=" + serviceName + ").RangerRolesProvider()"); + } + + this.serviceType = serviceType; + this.serviceName = serviceName; + this.atlasAuthAdminClient = atlasAuthAdminClient; + this.keycloakUserStore = new KeycloakUserStore(serviceType); + + + if (StringUtils.isEmpty(appId)) { + appId = serviceType; + } + + cacheFileNamePrefix = "roles"; + String cacheFilename = String.format("%s_%s_%s.json", appId, serviceName, cacheFileNamePrefix); + cacheFilename = cacheFilename.replace(File.separatorChar, '_'); + cacheFilename = cacheFilename.replace(File.pathSeparatorChar, '_'); + + this.cacheFileName = cacheFilename; + this.cacheDir = cacheDir; + + Gson gson = null; + try { + gson = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z").create(); + } catch (Throwable excp) { + LOG.fatal("RangerRolesProvider(): failed to create GsonBuilder object", excp); + } + this.gson = gson; + + String propertyPrefix = "ranger.plugin." + serviceType; + disableCacheIfServiceNotFound = config.getBoolean(propertyPrefix + ".disable.cache.if.servicenotfound", true); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerRolesProvider(serviceName=" + serviceName + ").RangerRolesProvider()"); + } + } + + public long getLastUpdatedTimeInMillis() { + return lastUpdatedTimeInMillis; + } + + public void setLastUpdatedTimeInMillis(long lastUpdatedTimeInMillis) { + this.lastUpdatedTimeInMillis = lastUpdatedTimeInMillis; + } + + public long getLastActivationTimeInMillis() { + return lastActivationTimeInMillis; + } + + public void setLastActivationTimeInMillis(long lastActivationTimeInMillis) { + this.lastActivationTimeInMillis = lastActivationTimeInMillis; + } + + public void loadUserGroupRoles(RangerBasePlugin plugIn) { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerRolesProvider(serviceName= " + serviceName + " serviceType= " + serviceType +").loadUserGroupRoles()"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerRolesProvider.loadUserGroupRoles(serviceName=" + serviceName + ")"); + long freeMemory = Runtime.getRuntime().freeMemory(); + long totalMemory = Runtime.getRuntime().totalMemory(); + PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory-freeMemory) + ", Free memory:" + freeMemory); + } + + try { + //load userGroupRoles from ranger admin + RangerRoles roles = loadUserGroupRolesFromAdmin(); + + if (roles == null) { + //if userGroupRoles fetch from ranger Admin Fails, load from cache + if (!rangerUserGroupRolesSetInPlugin) { + roles = loadUserGroupRolesFromCache(); + } + } + + if (PERF_POLICYENGINE_INIT_LOG.isDebugEnabled()) { + long freeMemory = Runtime.getRuntime().freeMemory(); + long totalMemory = Runtime.getRuntime().totalMemory(); + PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory - freeMemory) + ", Free memory:" + freeMemory); + } + + if (roles != null) { + plugIn.setRoles(roles); + rangerUserGroupRolesSetInPlugin = true; + setLastActivationTimeInMillis(System.currentTimeMillis()); + lastKnownRoleVersion = roles.getRoleVersion() == null ? -1 : roles.getRoleVersion(); + lastUpdatedTimeInMillis = roles.getRoleUpdateTime() == null ? -1 : roles.getRoleUpdateTime().getTime(); + } else { + if (!rangerUserGroupRolesSetInPlugin && !serviceDefSetInPlugin) { + plugIn.setRoles(null); + serviceDefSetInPlugin = true; + } + } + } catch (RangerServiceNotFoundException snfe) { + if (disableCacheIfServiceNotFound) { + disableCache(); + plugIn.setRoles(null); + setLastActivationTimeInMillis(System.currentTimeMillis()); + lastKnownRoleVersion = -1L; + lastUpdatedTimeInMillis = -1L; + serviceDefSetInPlugin = true; + } + } catch (Exception excp) { + LOG.error("Encountered unexpected exception, ignoring..", excp); + } + + RangerPerfTracer.log(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerRolesProvider(serviceName=" + serviceName + ").loadUserGroupRoles()"); + } + } + + private RangerRoles loadUserGroupRolesFromAdmin() throws RangerServiceNotFoundException { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerRolesProvider(serviceName=" + serviceName + ").loadUserGroupRolesFromAdmin()"); + } + + RangerRoles roles = null; + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerRolesProvider.loadUserGroupRolesFromAdmin(serviceName=" + serviceName + ")"); + } + + try { + if ("atlas".equals(serviceName)) { + roles = keycloakUserStore.loadRolesIfUpdated(lastUpdatedTimeInMillis); + } else { + roles = atlasAuthAdminClient.getRolesIfUpdated(lastUpdatedTimeInMillis); + } + + boolean isUpdated = roles != null; + + if(isUpdated) { + long newVersion = roles.getRoleVersion() == null ? -1 : roles.getRoleVersion().longValue(); + saveToCache(roles); + LOG.info("RangerRolesProvider(serviceName=" + serviceName + "): found updated version. lastKnownRoleVersion=" + lastKnownRoleVersion + "; newVersion=" + newVersion ); + } else { + if(LOG.isDebugEnabled()) { + LOG.debug("RangerRolesProvider(serviceName=" + serviceName + ").run(): no update found. lastKnownRoleVersion=" + lastKnownRoleVersion ); + } + } + } catch (Exception excp) { + LOG.error("RangerRolesProvider(serviceName=" + serviceName + "): failed to refresh roles. Will continue to use last known version of roles (" + "lastKnowRoleVersion= " + lastKnownRoleVersion, excp); + roles = null; + } + + RangerPerfTracer.log(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerRolesProvider(serviceName=" + serviceName + " serviceType= " + serviceType + " ).loadUserGroupRolesFromAdmin()"); + } + + return roles; + } + + private RangerRoles loadUserGroupRolesFromCache() { + + RangerRoles roles = null; + + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerRolesProvider(serviceName=" + serviceName + ").loadUserGroupRolesFromCache()"); + } + + File cacheFile = cacheDir == null ? null : new File(cacheDir + File.separator + cacheFileName); + + if (cacheFile != null && cacheFile.isFile() && cacheFile.canRead()) { + Reader reader = null; + + RangerPerfTracer perf = null; + + if (RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerRolesProvider.loadUserGroupRolesFromCache(serviceName=" + serviceName + ")"); + } + + try { + reader = new FileReader(cacheFile); + + roles = gson.fromJson(reader, RangerRoles.class); + + if (roles != null) { + if (!StringUtils.equals(serviceName, roles.getServiceName())) { + LOG.warn("ignoring unexpected serviceName '" + roles.getServiceName() + "' in cache file '" + cacheFile.getAbsolutePath() + "'"); + + roles.setServiceName(serviceName); + } + + lastKnownRoleVersion = roles.getRoleVersion() == null ? -1 : roles.getRoleVersion().longValue(); + lastUpdatedTimeInMillis = roles.getRoleUpdateTime() == null ? -1 : roles.getRoleUpdateTime().getTime(); + } + } catch (Exception excp) { + LOG.error("failed to load userGroupRoles from cache file " + cacheFile.getAbsolutePath(), excp); + } finally { + RangerPerfTracer.log(perf); + + if (reader != null) { + try { + reader.close(); + } catch (Exception excp) { + LOG.error("error while closing opened cache file " + cacheFile.getAbsolutePath(), excp); + } + } + } + } else { + roles = new RangerRoles(); + roles.setServiceName(serviceName); + roles.setRoleVersion(-1L); + roles.setRoleUpdateTime(null); + roles.setRangerRoles(new HashSet<>()); + saveToCache(roles); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerRolesProvider(serviceName=" + serviceName + ").RangerRolesProvider()"); + } + + return roles; + } + + public void saveToCache(RangerRoles roles) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerRolesProvider(serviceName=" + serviceName + ").saveToCache()"); + } + + if(roles != null) { + File cacheFile = null; + if (cacheDir != null) { + // Create the cacheDir if it doesn't already exist + File cacheDirTmp = new File(cacheDir); + if (cacheDirTmp.exists()) { + cacheFile = new File(cacheDir + File.separator + cacheFileName); + } else { + try { + cacheDirTmp.mkdirs(); + cacheFile = new File(cacheDir + File.separator + cacheFileName); + } catch (SecurityException ex) { + LOG.error("Cannot create cache directory", ex); + } + } + } + + if(cacheFile != null) { + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerRolesProvider.saveToCache(serviceName=" + serviceName + ")"); + } + + Writer writer = null; + + try { + writer = new FileWriter(cacheFile); + + gson.toJson(roles, writer); + } catch (Exception excp) { + LOG.error("failed to save roles to cache file '" + cacheFile.getAbsolutePath() + "'", excp); + } finally { + if(writer != null) { + try { + writer.close(); + } catch(Exception excp) { + LOG.error("error while closing opened cache file '" + cacheFile.getAbsolutePath() + "'", excp); + } + } + } + + RangerPerfTracer.log(perf); + } + } else { + LOG.info("roles is null. Nothing to save in cache"); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerRolesProvider.saveToCache(serviceName=" + serviceName + ")"); + } + } + + private void disableCache() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerRolesProvider.disableCache(serviceName=" + serviceName + ")"); + } + + File cacheFile = cacheDir == null ? null : new File(cacheDir + File.separator + cacheFileName); + + if(cacheFile != null && cacheFile.isFile() && cacheFile.canRead()) { + LOG.warn("Cleaning up local RangerRoles cache"); + String renamedCacheFile = cacheFile.getAbsolutePath() + "_" + System.currentTimeMillis(); + if (!cacheFile.renameTo(new File(renamedCacheFile))) { + LOG.error("Failed to move " + cacheFile.getAbsolutePath() + " to " + renamedCacheFile); + } else { + LOG.warn("Moved " + cacheFile.getAbsolutePath() + " to " + renamedCacheFile); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("No local RangerRoles cache found. No need to disable it!"); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerRolesProvider.disableCache(serviceName=" + serviceName + ")"); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerRolesUtil.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerRolesUtil.java new file mode 100644 index 00000000000..78e9e46b144 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerRolesUtil.java @@ -0,0 +1,172 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.atlas.plugin.model.RangerRole; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class RangerRolesUtil { + private final long roleVersion; + private final Map> userRoleMapping = new HashMap<>(); + private final Map> groupRoleMapping = new HashMap<>(); + private final Map> roleRoleMapping = new HashMap<>(); + + private final Map> roleToUserMapping = new HashMap<>(); + private final Map> roleToGroupMapping = new HashMap<>(); + + private RangerRoles roles = null; + public enum ROLES_FOR {USER, GROUP, ROLE} + + public RangerRolesUtil(RangerRoles roles) { + if (roles != null) { + this.roles = roles; + roleVersion = roles.getRoleVersion(); + + if (CollectionUtils.isNotEmpty(roles.getRangerRoles())) { + for (RangerRole role : roles.getRangerRoles()) { + Set containedRoles = getAllContainedRoles(roles.getRangerRoles(), role); + + buildMap(userRoleMapping, role, containedRoles, ROLES_FOR.USER); + buildMap(groupRoleMapping, role, containedRoles, ROLES_FOR.GROUP); + buildMap(roleRoleMapping, role, containedRoles, ROLES_FOR.ROLE); + + Set roleUsers = new HashSet<>(); + Set roleGroups = new HashSet<>(); + + addMemberNames(role.getUsers(), roleUsers); + addMemberNames(role.getGroups(), roleGroups); + + for (RangerRole containedRole : containedRoles) { + addMemberNames(containedRole.getUsers(), roleUsers); + addMemberNames(containedRole.getGroups(), roleGroups); + } + + roleToUserMapping.put(role.getName(), roleUsers); + roleToGroupMapping.put(role.getName(), roleGroups); + } + + } + } else { + roleVersion = -1L; + } + } + + public long getRoleVersion() { return roleVersion; } + + public RangerRoles getRoles() { + return this.roles; + } + + public Map> getUserRoleMapping() { + return this.userRoleMapping; + } + + public Map> getGroupRoleMapping() { + return this.groupRoleMapping; + } + + public Map> getRoleRoleMapping() { + return this.roleRoleMapping; + } + + public Map> getRoleToUserMapping() { + return this.roleToUserMapping; + } + + public Map> getRoleToGroupMapping() { + return this.roleToGroupMapping; + } + + private Set getAllContainedRoles(Set roles, RangerRole role) { + Set allRoles = new HashSet<>(); + + allRoles.add(role); + addContainedRoles(allRoles, roles, role); + + return allRoles; + } + + private void addContainedRoles(Set allRoles, Set roles, RangerRole role) { + List roleMembers = role.getRoles(); + + for (RangerRole.RoleMember roleMember : roleMembers) { + RangerRole containedRole = getContainedRole(roles, roleMember.getName()); + + if (containedRole!= null && !allRoles.contains(containedRole)) { + allRoles.add(containedRole); + addContainedRoles(allRoles, roles, containedRole); + } + } + } + + private void buildMap(Map> map, RangerRole role, Set containedRoles, ROLES_FOR roleFor) { + buildMap(map, role, role.getName(), roleFor); + + for (RangerRole containedRole : containedRoles) { + buildMap(map, containedRole, role.getName(), roleFor); + } + } + + private void buildMap(Map> map, RangerRole role, String roleName, ROLES_FOR roles_for) { + List userOrGroupOrRole = null; + switch(roles_for) { + case USER: + userOrGroupOrRole = role.getUsers(); + break; + case GROUP: + userOrGroupOrRole = role.getGroups(); + break; + case ROLE: + userOrGroupOrRole = role.getRoles(); + break; + } + if (CollectionUtils.isNotEmpty(userOrGroupOrRole)) { + getRoleMap(map, roleName, userOrGroupOrRole); + } + } + + private void getRoleMap(Map> map, String roleName, List userOrGroupOrRole) { + for (RangerRole.RoleMember roleMember : userOrGroupOrRole) { + if (StringUtils.isNotEmpty(roleMember.getName())) { + Set roleNames = map.computeIfAbsent(roleMember.getName(), k -> new HashSet<>()); + roleNames.add(roleName); + } + } + } + + private RangerRole getContainedRole(Set roles, String role) { + return (roles.stream().filter(containedRole -> role.equals(containedRole.getName())).findAny().orElse(null)); + } + + private void addMemberNames(List members, Set names) { + for (RangerRole.RoleMember member : members) { + names.add(member.getName()); + } + } +} + + diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerServiceNotFoundException.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerServiceNotFoundException.java new file mode 100644 index 00000000000..e1c836bc8b3 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerServiceNotFoundException.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.commons.lang.StringUtils; + +public class RangerServiceNotFoundException extends Exception { + static private final String formatString = "\"RANGER_ERROR_SERVICE_NOT_FOUND: ServiceName=%s\""; + public RangerServiceNotFoundException(String serviceName) { + super(serviceName); + } + public static final String buildExceptionMsg(String serviceName) { + return String.format(formatString, serviceName); + } + public static final void throwExceptionIfServiceNotFound(String serviceName, String exceptionMsg) throws RangerServiceNotFoundException { + String expectedExceptionMsg = buildExceptionMsg(serviceName); + if (StringUtils.startsWith(exceptionMsg, expectedExceptionMsg)) { + throw new RangerServiceNotFoundException(serviceName); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerServiceTagsDeltaUtil.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerServiceTagsDeltaUtil.java new file mode 100644 index 00000000000..87be65297e5 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerServiceTagsDeltaUtil.java @@ -0,0 +1,177 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.plugin.model.RangerServiceResource; +import org.apache.atlas.plugin.model.RangerTag; +import org.apache.atlas.plugin.model.RangerTagDef; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public class RangerServiceTagsDeltaUtil { + + private static final Log LOG = LogFactory.getLog(RangerServiceTagsDeltaUtil.class); + + private static final Log PERF_TAGS_DELTA_LOG = RangerPerfTracer.getPerfLogger("tags.delta"); + + /* + It should be possible to call applyDelta() multiple times with serviceTags and delta resulting from previous call to applyDelta() + The end result should be same if called once or multiple times. + */ + static public ServiceTags applyDelta(ServiceTags serviceTags, ServiceTags delta) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerServiceTagsDeltaUtil.applyDelta()"); + } + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_TAGS_DELTA_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_TAGS_DELTA_LOG, "RangerServiceTagsDeltaUtil.applyDelta()"); + } + if (serviceTags != null && !serviceTags.getIsDelta() && delta != null && delta.getIsDelta()) { + serviceTags.setServiceName(delta.getServiceName()); + serviceTags.setTagVersion(delta.getTagVersion()); + + // merge + Map tags = serviceTags.getTags(); + List serviceResources = serviceTags.getServiceResources(); + Map> resourceToTagIds = serviceTags.getResourceToTagIds(); + boolean isAnyMaterialChange = false; + + for (Map.Entry tagEntry : delta.getTags().entrySet()) { + if (StringUtils.isEmpty(tagEntry.getValue().getType())) { + if (null != tags.remove(tagEntry.getKey())) { + isAnyMaterialChange = true; + } + } else { + tags.put(tagEntry.getKey(), tagEntry.getValue()); + } + } + + // This could be expensive - compute time is M x N ( M - number of old tagged service resources, N - number of changed service resources) + + Map deletedServiceResources = new HashMap<>(); + List addedServiceResources = new ArrayList<>(); + + for (RangerServiceResource serviceResource : delta.getServiceResources()) { + + boolean found = false; + Iterator iter = serviceResources.iterator(); + + while (iter.hasNext()) { + RangerServiceResource existingResource = iter.next(); + + if (serviceResource.getId().equals(existingResource.getId())) { + if (!StringUtils.isEmpty(serviceResource.getResourceSignature())) { + if (!serviceResource.getResourceSignature().equals(existingResource.getResourceSignature())) { // ServiceResource changed + iter.remove(); + existingResource.setResourceSignature(null); + addedServiceResources.add(existingResource); + break; + } + } else { + iter.remove(); + deletedServiceResources.put(serviceResource.getId(), serviceResource.getId()); + } + found = true; + break; + } + } + if (!found) { + if (StringUtils.isNotEmpty(serviceResource.getResourceSignature())) { + serviceResources.add(serviceResource); + isAnyMaterialChange = true; + } + } + } + + for (Long deletedServiceResourceId : deletedServiceResources.keySet()) { + resourceToTagIds.remove(deletedServiceResourceId); + } + + resourceToTagIds.putAll(delta.getResourceToTagIds()); + + // Ensure that any modified service-resources are at head of list of service-resources in delta + // So that in in setServiceTags(), they get cleaned out first, and service-resource with new spec gets added + + addedServiceResources.addAll(delta.getServiceResources()); + delta.setServiceResources(addedServiceResources); + + if (!isAnyMaterialChange) { + if (LOG.isDebugEnabled()) { + LOG.debug("No material change may have occurred because of applying this delta"); + } + } + + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Cannot apply deltas to service-tags as one of preconditions is violated. Returning received serviceTags without applying delta!!"); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerServiceTagsDeltaUtil.applyDelta()"); + } + + RangerPerfTracer.log(perf); + + return serviceTags; + } + + public static void pruneUnusedAttributes(ServiceTags serviceTags) { + if (serviceTags != null) { + serviceTags.setTagUpdateTime(null); + + for (Map.Entry entry : serviceTags.getTagDefinitions().entrySet()) { + RangerTagDef tagDef = entry.getValue(); + tagDef.setCreatedBy(null); + tagDef.setCreateTime(null); + tagDef.setUpdatedBy(null); + tagDef.setUpdateTime(null); + tagDef.setGuid(null); + } + + for (Map.Entry entry : serviceTags.getTags().entrySet()) { + RangerTag tag = entry.getValue(); + tag.setCreatedBy(null); + tag.setCreateTime(null); + tag.setUpdatedBy(null); + tag.setUpdateTime(null); + tag.setGuid(null); + } + + for (RangerServiceResource serviceResource : serviceTags.getServiceResources()) { + serviceResource.setCreatedBy(null); + serviceResource.setCreateTime(null); + serviceResource.setUpdatedBy(null); + serviceResource.setUpdateTime(null); + serviceResource.setGuid(null); + + serviceResource.setServiceName(null); + } + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerUserStoreProvider.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerUserStoreProvider.java new file mode 100644 index 00000000000..3dd97bcee87 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/RangerUserStoreProvider.java @@ -0,0 +1,375 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.apache.atlas.authz.admin.client.AtlasAuthAdminClient; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.conf.Configuration; +import org.apache.atlas.plugin.service.RangerBasePlugin; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.HashMap; +import java.util.Set; + + +public class RangerUserStoreProvider { + private static final Log LOG = LogFactory.getLog(RangerUserStoreProvider.class); + + private static final Log PERF_POLICYENGINE_INIT_LOG = RangerPerfTracer.getPerfLogger("policyengine.init"); + + private final String serviceType; + private final String serviceName; + private final AtlasAuthAdminClient atlasAuthAdminClient; + private final KeycloakUserStore keycloakUserStore; + + private final String cacheFileName; + private final String cacheFileNamePrefix; + private final String cacheDir; + private final Gson gson; + private final boolean disableCacheIfServiceNotFound; + + private long lastActivationTimeInMillis; + private long lastUpdateTimeInMillis = -1L; + private long lastKnownUserStoreVersion = -1L; + private boolean rangerUserStoreSetInPlugin; + private boolean serviceDefSetInPlugin; + + public RangerUserStoreProvider(String serviceType, String appId, String serviceName, AtlasAuthAdminClient atlasAuthAdminClient, String cacheDir, Configuration config) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerUserStoreProvider(serviceName=" + serviceName + ").RangerUserStoreProvider()"); + } + + this.serviceType = serviceType; + this.serviceName = serviceName; + this.atlasAuthAdminClient = atlasAuthAdminClient; + + this.keycloakUserStore = new KeycloakUserStore(serviceType); + + if (StringUtils.isEmpty(appId)) { + appId = serviceType; + } + + cacheFileNamePrefix = "userstore"; + String cacheFilename = String.format("%s_%s_%s.json", appId, serviceName, cacheFileNamePrefix); + cacheFilename = cacheFilename.replace(File.separatorChar, '_'); + cacheFilename = cacheFilename.replace(File.pathSeparatorChar, '_'); + + this.cacheFileName = cacheFilename; + this.cacheDir = cacheDir; + + Gson gson = null; + try { + gson = new GsonBuilder().setDateFormat("yyyyMMdd-HH:mm:ss.SSS-Z").create(); + } catch (Throwable excp) { + LOG.fatal("RangerUserStoreProvider(): failed to create GsonBuilder object", excp); + } + this.gson = gson; + + String propertyPrefix = "ranger.plugin." + serviceType; + disableCacheIfServiceNotFound = config.getBoolean(propertyPrefix + ".disable.cache.if.servicenotfound", true); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerUserStoreProvider(serviceName=" + serviceName + ").RangerUserStoreProvider()"); + } + } + + public long getLastActivationTimeInMillis() { + return lastActivationTimeInMillis; + } + + public void setLastActivationTimeInMillis(long lastActivationTimeInMillis) { + this.lastActivationTimeInMillis = lastActivationTimeInMillis; + } + + public boolean isRangerUserStoreSetInPlugin() { + return rangerUserStoreSetInPlugin; + } + + public void setRangerUserStoreSetInPlugin(boolean rangerUserStoreSetInPlugin) { + this.rangerUserStoreSetInPlugin = rangerUserStoreSetInPlugin; + } + + public void loadUserStore(RangerBasePlugin plugIn) { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerUserStoreProvider(serviceName= " + serviceName + " serviceType= " + serviceType +").loadUserGroups()"); + } + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerUserStoreProvider.loadUserGroups(serviceName=" + serviceName + ")"); + long freeMemory = Runtime.getRuntime().freeMemory(); + long totalMemory = Runtime.getRuntime().totalMemory(); + PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory-freeMemory) + ", Free memory:" + freeMemory); + } + + try { + //load userGroupRoles from ranger admin + RangerUserStore userStore = loadUserStoreFromAdmin(); + + if (userStore == null) { + //if userGroupRoles fetch from ranger Admin Fails, load from cache + if (!rangerUserStoreSetInPlugin) { + userStore = loadUserStoreFromCache(); + } + } + + if (PERF_POLICYENGINE_INIT_LOG.isDebugEnabled()) { + long freeMemory = Runtime.getRuntime().freeMemory(); + long totalMemory = Runtime.getRuntime().totalMemory(); + PERF_POLICYENGINE_INIT_LOG.debug("In-Use memory: " + (totalMemory - freeMemory) + ", Free memory:" + freeMemory); + } + + if (userStore != null) { + plugIn.setUserStore(userStore); + rangerUserStoreSetInPlugin = true; + setLastActivationTimeInMillis(System.currentTimeMillis()); + lastKnownUserStoreVersion = userStore.getUserStoreVersion() == null ? -1 : userStore.getUserStoreVersion(); + lastUpdateTimeInMillis = userStore.getUserStoreUpdateTime() == null ? -1 : userStore.getUserStoreUpdateTime().getTime(); + } else { + if (!rangerUserStoreSetInPlugin && !serviceDefSetInPlugin) { + plugIn.setUserStore(userStore); + serviceDefSetInPlugin = true; + } + } + } catch (RangerServiceNotFoundException snfe) { + if (disableCacheIfServiceNotFound) { + disableCache(); + plugIn.setUserStore(null); + setLastActivationTimeInMillis(System.currentTimeMillis()); + lastKnownUserStoreVersion = -1L; + lastUpdateTimeInMillis = -1L; + serviceDefSetInPlugin = true; + } + } catch (Exception excp) { + LOG.error("Encountered unexpected exception, ignoring..", excp); + } + + RangerPerfTracer.log(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerUserStoreProvider(serviceName=" + serviceName + ").loadUserGroups()"); + } + } + + private RangerUserStore loadUserStoreFromAdmin() throws RangerServiceNotFoundException { + + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerUserStoreProvider(serviceName=" + serviceName + ").loadUserStoreFromAdmin()"); + } + + RangerUserStore userStore = null; + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerUserStoreProvider.loadUserStoreFromAdmin(serviceName=" + serviceName + ")"); + } + + try { + if ("atlas".equals(serviceName)) { + userStore = keycloakUserStore.loadUserStoreIfUpdated(lastUpdateTimeInMillis); + } else { + userStore = atlasAuthAdminClient.getUserStoreIfUpdated(lastUpdateTimeInMillis); + } + + boolean isUpdated = userStore != null; + + if(isUpdated) { + + long newVersion = userStore.getUserStoreVersion() == null ? -1 : userStore.getUserStoreVersion().longValue(); + saveToCache(userStore); + LOG.info("RangerUserStoreProvider(serviceName=" + serviceName + "): found updated version. lastKnownUserStoreVersion=" + lastKnownUserStoreVersion + "; newVersion=" + newVersion ); + } else { + if(LOG.isDebugEnabled()) { + LOG.debug("RangerUserStoreProvider(serviceName=" + serviceName + ").run(): no update found. lastKnownUserStoreVersion=" + lastKnownUserStoreVersion ); + } + } + } catch (Exception excp) { + LOG.error("RangerUserStoreProvider(serviceName=" + serviceName + "): failed to refresh userStore. Will continue to use last known version of userStore (" + "lastKnowRoleVersion= " + lastKnownUserStoreVersion, excp); + userStore = null; + } + + RangerPerfTracer.log(perf); + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerUserStoreProvider(serviceName=" + serviceName + " serviceType= " + serviceType + " ).loadUserStoreFromAdmin()"); + } + + return userStore; + } + + private RangerUserStore loadUserStoreFromCache() { + + RangerUserStore userStore = null; + + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerUserStoreProvider(serviceName=" + serviceName + ").loadUserStoreFromCache()"); + } + + File cacheFile = cacheDir == null ? null : new File(cacheDir + File.separator + cacheFileName); + + if (cacheFile != null && cacheFile.isFile() && cacheFile.canRead()) { + Reader reader = null; + + RangerPerfTracer perf = null; + + if (RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerUserStoreProvider.loadUserStoreFromCache(serviceName=" + serviceName + ")"); + } + + try { + reader = new FileReader(cacheFile); + + userStore = gson.fromJson(reader, RangerUserStore.class); + + if (userStore != null) { + if (!StringUtils.equals(serviceName, userStore.getServiceName())) { + LOG.warn("ignoring unexpected serviceName '" + userStore.getServiceName() + "' in cache file '" + cacheFile.getAbsolutePath() + "'"); + + userStore.setServiceName(serviceName); + } + + lastKnownUserStoreVersion = userStore.getUserStoreVersion() == null ? -1 : userStore.getUserStoreVersion().longValue(); + lastUpdateTimeInMillis = userStore.getUserStoreUpdateTime() == null ? -1 : userStore.getUserStoreUpdateTime().getTime(); + } + } catch (Exception excp) { + LOG.error("failed to load userStore from cache file " + cacheFile.getAbsolutePath(), excp); + } finally { + RangerPerfTracer.log(perf); + + if (reader != null) { + try { + reader.close(); + } catch (Exception excp) { + LOG.error("error while closing opened cache file " + cacheFile.getAbsolutePath(), excp); + } + } + } + } else { + userStore = new RangerUserStore(); + userStore.setServiceName(serviceName); + userStore.setUserStoreVersion(-1L); + userStore.setUserStoreUpdateTime(null); + userStore.setUserGroupMapping(new HashMap>()); + saveToCache(userStore); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerUserStoreProvider(serviceName=" + serviceName + ").RangerUserStoreProvider()"); + } + + return userStore; + } + + public void saveToCache(RangerUserStore userStore) { + if(LOG.isDebugEnabled()) { + LOG.debug("==> RangerUserStoreProvider(serviceName=" + serviceName + ").saveToCache()"); + } + + if(userStore != null) { + File cacheFile = null; + if (cacheDir != null) { + // Create the cacheDir if it doesn't already exist + File cacheDirTmp = new File(cacheDir); + if (cacheDirTmp.exists()) { + cacheFile = new File(cacheDir + File.separator + cacheFileName); + } else { + try { + cacheDirTmp.mkdirs(); + cacheFile = new File(cacheDir + File.separator + cacheFileName); + } catch (SecurityException ex) { + LOG.error("Cannot create cache directory", ex); + } + } + } + + if(cacheFile != null) { + + RangerPerfTracer perf = null; + + if(RangerPerfTracer.isPerfTraceEnabled(PERF_POLICYENGINE_INIT_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_POLICYENGINE_INIT_LOG, "RangerUserStoreProvider.saveToCache(serviceName=" + serviceName + ")"); + } + + Writer writer = null; + + try { + writer = new FileWriter(cacheFile); + + gson.toJson(userStore, writer); + } catch (Exception excp) { + LOG.error("failed to save userStore to cache file '" + cacheFile.getAbsolutePath() + "'", excp); + } finally { + if(writer != null) { + try { + writer.close(); + } catch(Exception excp) { + LOG.error("error while closing opened cache file '" + cacheFile.getAbsolutePath() + "'", excp); + } + } + } + + RangerPerfTracer.log(perf); + } + } else { + LOG.info("userStore is null. Nothing to save in cache"); + } + + if(LOG.isDebugEnabled()) { + LOG.debug("<== RangerUserStoreProvider.saveToCache(serviceName=" + serviceName + ")"); + } + } + + private void disableCache() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerUserStoreProvider.disableCache(serviceName=" + serviceName + ")"); + } + + File cacheFile = cacheDir == null ? null : new File(cacheDir + File.separator + cacheFileName); + + if(cacheFile != null && cacheFile.isFile() && cacheFile.canRead()) { + LOG.warn("Cleaning up local RangerUserStore cache"); + String renamedCacheFile = cacheFile.getAbsolutePath() + "_" + System.currentTimeMillis(); + if (!cacheFile.renameTo(new File(renamedCacheFile))) { + LOG.error("Failed to move " + cacheFile.getAbsolutePath() + " to " + renamedCacheFile); + } else { + LOG.warn("Moved " + cacheFile.getAbsolutePath() + " to " + renamedCacheFile); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("No local RangerRoles cache found. No need to disable it!"); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerUserStoreProvider.disableCache(serviceName=" + serviceName + ")"); + } + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/SearchFilter.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/SearchFilter.java new file mode 100644 index 00000000000..87e7ed58356 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/SearchFilter.java @@ -0,0 +1,253 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + + +public class SearchFilter { + public static final String SERVICE_TYPE = "serviceType"; // search, sort + public static final String SERVICE_TYPE_ID = "serviceTypeId"; // search, sort + public static final String SERVICE_NAME = "serviceName"; // search, sort + public static final String SERVICE_ID = "serviceId"; // search, sort + public static final String POLICY_NAME = "policyName"; // search, sort + public static final String POLICY_ID = "policyId"; // search, sort + public static final String IS_ENABLED = "isEnabled"; // search + public static final String IS_RECURSIVE = "isRecursive"; // search + public static final String TAG_SERVICE_NAME = "tagServiceName"; // search + public static final String TAG_SERVICE_ID = "tagServiceId"; // search + public static final String USER = "user"; // search + public static final String GROUP = "group"; // search + public static final String ROLE = "role"; // search + public static final String RESOURCE_PREFIX = "resource:"; // search + public static final String RESOURCE_MATCH_SCOPE = "resourceMatchScope"; // search - valid values: "self", "ancestor", "self_or_ancestor" + public static final String POL_RESOURCE = "polResource"; // search + public static final String POLICY_NAME_PARTIAL = "policyNamePartial"; // search, sort + public static final String CREATE_TIME = "createTime"; // sort + public static final String UPDATE_TIME = "updateTime"; // sort + public static final String START_INDEX = "startIndex"; + public static final String PAGE_SIZE = "pageSize"; + public static final String SORT_BY = "sortBy"; + public static final String RESOURCE_SIGNATURE = "resourceSignature:"; // search + public static final String POLICY_TYPE = "policyType"; // search + public static final String POLICY_PRIORITY = "policyPriority"; // search + public static final String GUID = "guid"; //search + public static final String POLICY_LABEL = "policyLabel"; // search + public static final String POLICY_LABELS_PARTIAL = "policyLabelsPartial"; // search + public static final String POLICY_LABEL_ID = "policyLabelId"; // search, sort + public static final String ZONE_ID = "zoneId"; // search, sort + public static final String ZONE_NAME = "zoneName"; // search, sort + public static final String ROLE_ID = "roleId"; // search, sort + public static final String ROLE_NAME = "roleName"; // search, sort + public static final String GROUP_NAME = "groupName"; // search, sort + public static final String USER_NAME = "userName"; // search, sort + public static final String ROLE_NAME_PARTIAL = "roleNamePartial"; // search + public static final String GROUP_NAME_PARTIAL = "groupNamePartial"; // search + public static final String USER_NAME_PARTIAL = "userNamePartial"; // search + + public static final String TAG_DEF_ID = "tagDefId"; // search + public static final String TAG_DEF_GUID = "tagDefGuid"; // search + public static final String TAG_TYPE = "tagType"; // search + public static final String TAG_ID = "tagId"; // search + public static final String TAG_GUID = "tagGuid"; // search + public static final String TAG_RESOURCE_ID = "resourceId"; // search + public static final String TAG_RESOURCE_GUID = "resourceGuid"; // search + public static final String TAG_RESOURCE_SERVICE_NAME = "resourceServiceName"; // search + public static final String TAG_RESOURCE_SIGNATURE = "resourceSignature"; // search + public static final String TAG_MAP_ID = "tagResourceMapId"; // search + public static final String TAG_MAP_GUID = "tagResourceMapGuid"; // search + + public static final String SERVICE_NAME_PARTIAL = "serviceNamePartial"; + + public static final String PLUGIN_HOST_NAME = "pluginHostName"; + public static final String PLUGIN_APP_TYPE = "pluginAppType"; + public static final String PLUGIN_ENTITY_TYPE = "pluginEntityType"; + public static final String PLUGIN_IP_ADDRESS = "pluginIpAddress"; + public static final String CLUSTER_NAME = "clusterName"; + public static final String FETCH_ZONE_UNZONE_POLICIES= "fetchZoneAndUnzonePolicies"; + public static final String FETCH_TAG_POLICIES = "fetchTagPolicies"; + public static final String FETCH_ZONE_NAME = "zoneName"; + public static final String FETCH_DENY_CONDITION = "denyCondition"; + + public static final String SERVICE_DISPLAY_NAME = "serviceDisplayName"; // search, sort + public static final String SERVICE_DISPLAY_NAME_PARTIAL = "serviceDisplayNamePartial"; // search + public static final String SERVICE_TYPE_DISPLAY_NAME = "serviceTypeDisplayName"; // search, sort + + private Map params; + private int startIndex; + private int maxRows = Integer.MAX_VALUE; + private boolean getCount = true; + private String sortBy; + private String sortType; + + public SearchFilter() { + this(null); + } + + public SearchFilter(String name, String value) { + setParam(name, value); + } + + public SearchFilter(Map values) { + setParams(values); + } + + public Map getParams() { + return params; + } + + public void setParams(Map params) { + this.params = params; + } + + public String getParam(String name) { + return params == null ? null : params.get(name); + } + + public void setParam(String name, String value) { + if(StringUtils.isEmpty(name) || StringUtils.isEmpty(value)) { + return; + } + + if(params == null) { + params = new HashMap(); + } + + params.put(name, value); + } + public void removeParam(String name) { + + params.remove(name); + } + + public Map getParamsWithPrefix(String prefix, boolean stripPrefix) { + Map ret = null; + + if(prefix == null) { + prefix = StringUtils.EMPTY; + } + + if(params != null) { + for(Map.Entry e : params.entrySet()) { + String name = e.getKey(); + + if(name.startsWith(prefix)) { + if(ret == null) { + ret = new HashMap<>(); + } + + if(stripPrefix) { + name = name.substring(prefix.length()); + } + + ret.put(name, e.getValue()); + } + } + } + + return ret; + } + + public boolean isEmpty() { + return MapUtils.isEmpty(params); + } + + public int getStartIndex() { + return startIndex; + } + + public void setStartIndex(int startIndex) { + this.startIndex = startIndex; + } + + public int getMaxRows() { + return maxRows; + } + + public void setMaxRows(int maxRows) { + this.maxRows = maxRows; + } + + public boolean isGetCount() { + return getCount; + } + + public void setGetCount(boolean getCount) { + this.getCount = getCount; + } + + public String getSortBy() { + return sortBy; + } + + public void setSortBy(String sortBy) { + this.sortBy = sortBy; + } + + public String getSortType() { + return sortType; + } + + public void setSortType(String sortType) { + this.sortType = sortType; + } + + @Override + public boolean equals(Object object) { + if (object == null || !(object instanceof SearchFilter)) { + return false; + } + SearchFilter that = (SearchFilter)object; + return Objects.equals(params, that.params); + } + + @Override + public int hashCode() { + return Objects.hash(params); + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("SearchFilter={"); + + sb.append("getCount={").append(getCount).append("} "); + sb.append("maxRows={").append(maxRows).append("} "); + sb.append("params={").append(params).append("} "); + sb.append("sortBy={").append(sortBy).append("} "); + sb.append("sortType={").append(sortType).append("} "); + sb.append("startIndex={").append(startIndex).append("} "); + sb.append("}"); + + return sb; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/ServiceDefUtil.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/ServiceDefUtil.java new file mode 100644 index 00000000000..8492df3f97c --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/ServiceDefUtil.java @@ -0,0 +1,469 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.atlas.constants.RangerAtlasConstants; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.hadoop.conf.Configuration; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerAccessTypeDef; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerDataMaskTypeDef; +import org.apache.atlas.plugin.model.RangerServiceDef.RangerResourceDef; +import org.apache.atlas.plugin.policyengine.RangerPluginContext; +import org.apache.atlas.plugin.store.ServiceDefsUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +public class ServiceDefUtil { + + public static boolean getOption_enableDenyAndExceptionsInPolicies(RangerServiceDef serviceDef, RangerPluginContext pluginContext) { + boolean ret = false; + + if(serviceDef != null) { + Configuration config = pluginContext != null ? pluginContext.getConfig() : null; + boolean enableDenyAndExceptionsInPoliciesHiddenOption = config == null || config.getBoolean("ranger.servicedef.enableDenyAndExceptionsInPolicies", true); + boolean defaultValue = enableDenyAndExceptionsInPoliciesHiddenOption || StringUtils.equalsIgnoreCase(serviceDef.getName(), ServiceDefsUtil.EMBEDDED_SERVICEDEF_TAG_NAME); + + ret = ServiceDefUtil.getBooleanValue(serviceDef.getOptions(), RangerServiceDef.OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES, defaultValue); + } + + return ret; + } + + public static RangerDataMaskTypeDef getDataMaskType(RangerServiceDef serviceDef, String typeName) { + RangerDataMaskTypeDef ret = null; + + if(serviceDef != null && serviceDef.getDataMaskDef() != null) { + List maskTypes = serviceDef.getDataMaskDef().getMaskTypes(); + + if(CollectionUtils.isNotEmpty(maskTypes)) { + for(RangerDataMaskTypeDef maskType : maskTypes) { + if(StringUtils.equals(maskType.getName(), typeName)) { + ret = maskType; + break; + } + } + } + } + + return ret; + } + + public static RangerServiceDef normalize(RangerServiceDef serviceDef) { + normalizeDataMaskDef(serviceDef); + normalizeRowFilterDef(serviceDef); + + return serviceDef; + } + + public static RangerResourceDef getResourceDef(RangerServiceDef serviceDef, String resource) { + RangerResourceDef ret = null; + + if(serviceDef != null && resource != null && CollectionUtils.isNotEmpty(serviceDef.getResources())) { + for(RangerResourceDef resourceDef : serviceDef.getResources()) { + if(StringUtils.equalsIgnoreCase(resourceDef.getName(), resource)) { + ret = resourceDef; + break; + } + } + } + + return ret; + } + + public static Integer getLeafResourceLevel(RangerServiceDef serviceDef, Map policyResource) { + Integer ret = null; + + RangerResourceDef resourceDef = getLeafResourceDef(serviceDef, policyResource); + + if (resourceDef != null) { + ret = resourceDef.getLevel(); + } + + return ret; + } + + public static RangerResourceDef getLeafResourceDef(RangerServiceDef serviceDef, Map policyResource) { + RangerResourceDef ret = null; + + if(serviceDef != null && policyResource != null) { + for(Map.Entry entry : policyResource.entrySet()) { + if (!isEmpty(entry.getValue())) { + String resource = entry.getKey(); + RangerResourceDef resourceDef = ServiceDefUtil.getResourceDef(serviceDef, resource); + + if (resourceDef != null && resourceDef.getLevel() != null) { + if (ret == null) { + ret = resourceDef; + } else if(ret.getLevel() < resourceDef.getLevel()) { + ret = resourceDef; + } + } + } + } + } + + return ret; + } + + public static boolean isAncestorOf(RangerServiceDef serviceDef, RangerResourceDef ancestor, RangerResourceDef descendant) { + + boolean ret = false; + + if (ancestor != null && descendant != null) { + final String ancestorName = ancestor.getName(); + + for (RangerResourceDef node = descendant; node != null; node = ServiceDefUtil.getResourceDef(serviceDef, node.getParent())) { + if (StringUtils.equalsIgnoreCase(ancestorName, node.getParent())) { + ret = true; + break; + } + } + } + + return ret; + } + + public static boolean isEmpty(RangerPolicy.RangerPolicyResource policyResource) { + boolean ret = true; + if (policyResource != null) { + List resourceValues = policyResource.getValues(); + if (CollectionUtils.isNotEmpty(resourceValues)) { + for (String resourceValue : resourceValues) { + if (StringUtils.isNotBlank(resourceValue)) { + ret = false; + break; + } + } + } + } + return ret; + } + + public static String getOption(Map options, String name, String defaultValue) { + String ret = options != null && name != null ? options.get(name) : null; + + if(ret == null) { + ret = defaultValue; + } + + return ret; + } + + public static boolean getBooleanOption(Map options, String name, boolean defaultValue) { + String val = getOption(options, name, null); + + return val == null ? defaultValue : Boolean.parseBoolean(val); + } + + public static char getCharOption(Map options, String name, char defaultValue) { + String val = getOption(options, name, null); + + return StringUtils.isEmpty(val) ? defaultValue : val.charAt(0); + } + + public static RangerServiceDef normalizeAccessTypeDefs(RangerServiceDef serviceDef, final String componentType) { + + if (serviceDef != null && StringUtils.isNotBlank(componentType)) { + + List accessTypeDefs = serviceDef.getAccessTypes(); + + if (CollectionUtils.isNotEmpty(accessTypeDefs)) { + + String prefix = componentType + RangerAtlasConstants.COMPONENT_ACCESSTYPE_SEPARATOR; + + List unneededAccessTypeDefs = null; + + for (RangerServiceDef.RangerAccessTypeDef accessTypeDef : accessTypeDefs) { + + String accessType = accessTypeDef.getName(); + + if (StringUtils.startsWith(accessType, prefix)) { + + String newAccessType = StringUtils.removeStart(accessType, prefix); + + accessTypeDef.setName(newAccessType); + + Collection impliedGrants = accessTypeDef.getImpliedGrants(); + + if (CollectionUtils.isNotEmpty(impliedGrants)) { + + Collection newImpliedGrants = null; + + for (String impliedGrant : impliedGrants) { + + if (StringUtils.startsWith(impliedGrant, prefix)) { + + String newImpliedGrant = StringUtils.removeStart(impliedGrant, prefix); + + if (newImpliedGrants == null) { + newImpliedGrants = new ArrayList<>(); + } + + newImpliedGrants.add(newImpliedGrant); + } + } + accessTypeDef.setImpliedGrants(newImpliedGrants); + + } + } else if (StringUtils.contains(accessType, RangerAtlasConstants.COMPONENT_ACCESSTYPE_SEPARATOR)) { + if(unneededAccessTypeDefs == null) { + unneededAccessTypeDefs = new ArrayList<>(); + } + + unneededAccessTypeDefs.add(accessTypeDef); + } + } + + if(unneededAccessTypeDefs != null) { + accessTypeDefs.removeAll(unneededAccessTypeDefs); + } + } + } + + return serviceDef; + } + + private static void normalizeDataMaskDef(RangerServiceDef serviceDef) { + if(serviceDef != null && serviceDef.getDataMaskDef() != null) { + List dataMaskResources = serviceDef.getDataMaskDef().getResources(); + List dataMaskAccessTypes = serviceDef.getDataMaskDef().getAccessTypes(); + + if(CollectionUtils.isNotEmpty(dataMaskResources)) { + List resources = serviceDef.getResources(); + List processedDefs = new ArrayList(dataMaskResources.size()); + + for(RangerResourceDef dataMaskResource : dataMaskResources) { + RangerResourceDef processedDef = dataMaskResource; + + for(RangerResourceDef resourceDef : resources) { + if(StringUtils.equals(resourceDef.getName(), dataMaskResource.getName())) { + processedDef = ServiceDefUtil.mergeResourceDef(resourceDef, dataMaskResource); + break; + } + } + + processedDefs.add(processedDef); + } + + serviceDef.getDataMaskDef().setResources(processedDefs); + } + + if(CollectionUtils.isNotEmpty(dataMaskAccessTypes)) { + List accessTypes = serviceDef.getAccessTypes(); + List processedDefs = new ArrayList(accessTypes.size()); + + for(RangerAccessTypeDef dataMaskAccessType : dataMaskAccessTypes) { + RangerAccessTypeDef processedDef = dataMaskAccessType; + + for(RangerAccessTypeDef accessType : accessTypes) { + if(StringUtils.equals(accessType.getName(), dataMaskAccessType.getName())) { + processedDef = ServiceDefUtil.mergeAccessTypeDef(accessType, dataMaskAccessType); + break; + } + } + + processedDefs.add(processedDef); + } + + serviceDef.getDataMaskDef().setAccessTypes(processedDefs); + } + } + } + + private static void normalizeRowFilterDef(RangerServiceDef serviceDef) { + if(serviceDef != null && serviceDef.getRowFilterDef() != null) { + List rowFilterResources = serviceDef.getRowFilterDef().getResources(); + List rowFilterAccessTypes = serviceDef.getRowFilterDef().getAccessTypes(); + + if(CollectionUtils.isNotEmpty(rowFilterResources)) { + List resources = serviceDef.getResources(); + List processedDefs = new ArrayList(rowFilterResources.size()); + + for(RangerResourceDef rowFilterResource : rowFilterResources) { + RangerResourceDef processedDef = rowFilterResource; + + for(RangerResourceDef resourceDef : resources) { + if(StringUtils.equals(resourceDef.getName(), rowFilterResource.getName())) { + processedDef = ServiceDefUtil.mergeResourceDef(resourceDef, rowFilterResource); + break; + } + } + + processedDefs.add(processedDef); + } + + serviceDef.getRowFilterDef().setResources(processedDefs); + } + + if(CollectionUtils.isNotEmpty(rowFilterAccessTypes)) { + List accessTypes = serviceDef.getAccessTypes(); + List processedDefs = new ArrayList(accessTypes.size()); + + for(RangerAccessTypeDef rowFilterAccessType : rowFilterAccessTypes) { + RangerAccessTypeDef processedDef = rowFilterAccessType; + + for(RangerAccessTypeDef accessType : accessTypes) { + if(StringUtils.equals(accessType.getName(), rowFilterAccessType.getName())) { + processedDef = ServiceDefUtil.mergeAccessTypeDef(accessType, rowFilterAccessType); + break; + } + } + + processedDefs.add(processedDef); + } + + serviceDef.getRowFilterDef().setAccessTypes(processedDefs); + } + } + } + + private static RangerResourceDef mergeResourceDef(RangerResourceDef base, RangerResourceDef delta) { + RangerResourceDef ret = new RangerResourceDef(base); + + // retain base values for: itemId, name, type, level, parent, lookupSupported + + if(Boolean.TRUE.equals(delta.getMandatory())) + ret.setMandatory(delta.getMandatory()); + + if(delta.getRecursiveSupported() != null) + ret.setRecursiveSupported(delta.getRecursiveSupported()); + + if(delta.getExcludesSupported() != null) + ret.setExcludesSupported(delta.getExcludesSupported()); + + if(StringUtils.isNotEmpty(delta.getMatcher())) + ret.setMatcher(delta.getMatcher()); + + if(MapUtils.isNotEmpty(delta.getMatcherOptions())) { + if(ret.getMatcherOptions() == null) { + ret.setMatcherOptions(new HashMap()); + } + + for(Map.Entry e : delta.getMatcherOptions().entrySet()) { + ret.getMatcherOptions().put(e.getKey(), e.getValue()); + } + } + + if(StringUtils.isNotEmpty(delta.getValidationRegEx())) + ret.setValidationRegEx(delta.getValidationRegEx()); + + if(StringUtils.isNotEmpty(delta.getValidationMessage())) + ret.setValidationMessage(delta.getValidationMessage()); + + ret.setUiHint(delta.getUiHint()); + + if(StringUtils.isNotEmpty(delta.getLabel())) + ret.setLabel(delta.getLabel()); + + if(StringUtils.isNotEmpty(delta.getDescription())) + ret.setDescription(delta.getDescription()); + + if(StringUtils.isNotEmpty(delta.getRbKeyLabel())) + ret.setRbKeyLabel(delta.getRbKeyLabel()); + + if(StringUtils.isNotEmpty(delta.getRbKeyDescription())) + ret.setRbKeyDescription(delta.getRbKeyDescription()); + + if(StringUtils.isNotEmpty(delta.getRbKeyValidationMessage())) + ret.setRbKeyValidationMessage(delta.getRbKeyValidationMessage()); + + if(CollectionUtils.isNotEmpty(delta.getAccessTypeRestrictions())) + ret.setAccessTypeRestrictions(delta.getAccessTypeRestrictions()); + + boolean copyLeafValue = false; + if (ret.getIsValidLeaf() != null) { + if (!ret.getIsValidLeaf().equals(delta.getIsValidLeaf())) { + copyLeafValue = true; + } + } else { + if (delta.getIsValidLeaf() != null) { + copyLeafValue = true; + } + } + if (copyLeafValue) + ret.setIsValidLeaf(delta.getIsValidLeaf()); + + return ret; + } + + private static RangerAccessTypeDef mergeAccessTypeDef(RangerAccessTypeDef base, RangerAccessTypeDef delta) { + RangerAccessTypeDef ret = new RangerAccessTypeDef(base); + + // retain base values for: itemId, name, impliedGrants + + if(StringUtils.isNotEmpty(delta.getLabel())) + ret.setLabel(delta.getLabel()); + + if(StringUtils.isNotEmpty(delta.getRbKeyLabel())) + ret.setRbKeyLabel(delta.getRbKeyLabel()); + + return ret; + } + + private static boolean getBooleanValue(Map map, String elementName, boolean defaultValue) { + boolean ret = defaultValue; + + if(MapUtils.isNotEmpty(map) && map.containsKey(elementName)) { + String elementValue = map.get(elementName); + + if(StringUtils.isNotEmpty(elementValue)) { + ret = Boolean.valueOf(elementValue.toString()); + } + } + + return ret; + } + + public static Map> getExpandedImpliedGrants(RangerServiceDef serviceDef) { + Map> ret = new HashMap<>(); + + if(serviceDef != null && !CollectionUtils.isEmpty(serviceDef.getAccessTypes())) { + for(RangerAccessTypeDef accessTypeDef : serviceDef.getAccessTypes()) { + if(!CollectionUtils.isEmpty(accessTypeDef.getImpliedGrants())) { + + Collection impliedAccessGrants = ret.get(accessTypeDef.getName()); + + if(impliedAccessGrants == null) { + impliedAccessGrants = new HashSet<>(); + + ret.put(accessTypeDef.getName(), impliedAccessGrants); + } + + impliedAccessGrants.addAll(accessTypeDef.getImpliedGrants()); + impliedAccessGrants.add(accessTypeDef.getName()); + } else { + ret.put(accessTypeDef.getName(), new HashSet<>(Collections.singleton(accessTypeDef.getName()))); + } + } + } + return ret; + } + +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/ServicePolicies.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/ServicePolicies.java new file mode 100644 index 00000000000..829efa115d0 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/ServicePolicies.java @@ -0,0 +1,587 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.apache.atlas.authorizer.store.PoliciesStore; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicyDelta; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngine; +import org.apache.atlas.plugin.policyengine.RangerPolicyEngineImpl; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class ServicePolicies implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private static final Log LOG = LogFactory.getLog(ServicePolicies.class); + private static final PoliciesStore policiesStore = PoliciesStore.getInstance(); + + private String serviceName; + private String serviceId; + private Long policyVersion; + private Date policyUpdateTime; + private List policies; + private RangerServiceDef serviceDef; + private String auditMode = RangerPolicyEngine.AUDIT_DEFAULT; + private TagPolicies tagPolicies; + private ABACPolicies abacPolicies; + private Map securityZones; + private List policyDeltas; + private Map serviceConfig; + + /** + * @return the serviceName + */ + public String getServiceName() { + return serviceName; + } + /** + * @param serviceName the serviceName to set + */ + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + /** + * @return the serviceId + */ + public String getServiceId() { + return serviceId; + } + /** + * @param serviceId the serviceId to set + */ + public void setServiceId(String serviceId) { + this.serviceId = serviceId; + } + /** + * @return the policyVersion + */ + public Long getPolicyVersion() { + return policyVersion; + } + /** + * @param policyVersion the policyVersion to set + */ + public void setPolicyVersion(Long policyVersion) { + this.policyVersion = policyVersion; + } + /** + * @return the policyUpdateTime + */ + public Date getPolicyUpdateTime() { + return policyUpdateTime; + } + /** + * @param policyUpdateTime the policyUpdateTime to set + */ + public void setPolicyUpdateTime(Date policyUpdateTime) { + this.policyUpdateTime = policyUpdateTime; + } + + public Map getServiceConfig() { + return serviceConfig; + } + public void setServiceConfig(Map serviceConfig) { + this.serviceConfig = serviceConfig; + } + + /** + * @return the policies + */ + public List getPolicies() { + return policies; + } + /** + * @param policies the policies to set + */ + public void setPolicies(List policies) { + this.policies = policies; + } + /** + * @return the serviceDef + */ + public RangerServiceDef getServiceDef() { + return serviceDef; + } + /** + * @param serviceDef the serviceDef to set + */ + public void setServiceDef(RangerServiceDef serviceDef) { + this.serviceDef = serviceDef; + } + + public String getAuditMode() { + return auditMode; + } + + public void setAuditMode(String auditMode) { + this.auditMode = auditMode; + } + /** + * @return the tagPolicies + */ + public TagPolicies getTagPolicies() { + return tagPolicies; + } + /** + * @param tagPolicies the tagPolicies to set + */ + public void setTagPolicies(TagPolicies tagPolicies) { + this.tagPolicies = tagPolicies; + } + + public ABACPolicies getAbacPolicies() { + return abacPolicies; + } + + public void setAbacPolicies(ABACPolicies abacPolicies) { + this.abacPolicies = abacPolicies; + } + + public Map getSecurityZones() { return securityZones; } + + public void setSecurityZones(Map securityZones) { + this.securityZones = securityZones; + } + + @Override + public String toString() { + return "serviceName=" + serviceName + ", " + + "serviceId=" + serviceId + ", " + + "policyVersion=" + policyVersion + ", " + + "policyUpdateTime=" + policyUpdateTime + ", " + + "policies=" + policies + ", " + + "tagPolicies=" + tagPolicies + ", " + + "policyDeltas=" + policyDeltas + ", " + + "serviceDef=" + serviceDef + ", " + + "auditMode=" + auditMode + ", " + + "securityZones=" + securityZones + ; + } + + public List getPolicyDeltas() { return this.policyDeltas; } + + public void setPolicyDeltas(List policyDeltas) { this.policyDeltas = policyDeltas; } + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class TagPolicies implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String serviceName; + private String serviceId; + private Long policyVersion; + private Date policyUpdateTime; + private List policies; + private RangerServiceDef serviceDef; + private String auditMode = RangerPolicyEngine.AUDIT_DEFAULT; + private Map serviceConfig; + + /** + * @return the serviceName + */ + public String getServiceName() { + return serviceName; + } + /** + * @param serviceName the serviceName to set + */ + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + /** + * @return the serviceId + */ + public String getServiceId() { + return serviceId; + } + /** + * @param serviceId the serviceId to set + */ + public void setServiceId(String serviceId) { + this.serviceId = serviceId; + } + /** + * @return the policyVersion + */ + public Long getPolicyVersion() { + return policyVersion; + } + /** + * @param policyVersion the policyVersion to set + */ + public void setPolicyVersion(Long policyVersion) { + this.policyVersion = policyVersion; + } + /** + * @return the policyUpdateTime + */ + public Date getPolicyUpdateTime() { + return policyUpdateTime; + } + /** + * @param policyUpdateTime the policyUpdateTime to set + */ + public void setPolicyUpdateTime(Date policyUpdateTime) { + this.policyUpdateTime = policyUpdateTime; + } + /** + * @return the policies + */ + public List getPolicies() { + return policies; + } + /** + * @param policies the policies to set + */ + public void setPolicies(List policies) { + this.policies = policies; + } + /** + * @return the serviceDef + */ + public RangerServiceDef getServiceDef() { + return serviceDef; + } + /** + * @param serviceDef the serviceDef to set + */ + public void setServiceDef(RangerServiceDef serviceDef) { + this.serviceDef = serviceDef; + } + + public String getAuditMode() { + return auditMode; + } + + public void setAuditMode(String auditMode) { + this.auditMode = auditMode; + } + + public Map getServiceConfig() { + return serviceConfig; + } + + public void setServiceConfig(Map serviceConfig) { + this.serviceConfig = serviceConfig; + } + + @Override + public String toString() { + return "serviceName=" + serviceName + ", " + + "serviceId=" + serviceId + ", " + + "policyVersion=" + policyVersion + ", " + + "policyUpdateTime=" + policyUpdateTime + ", " + + "policies=" + policies + ", " + + "serviceDef=" + serviceDef + ", " + + "auditMode=" + auditMode + + "serviceConfig=" + serviceConfig + ; + } + } + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class ABACPolicies implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String serviceName; + private String serviceId; + private Long policyVersion; + private Date policyUpdateTime; + private List policies; + private RangerServiceDef serviceDef; + private String auditMode = RangerPolicyEngine.AUDIT_DEFAULT; + private Map serviceConfig; + + public ABACPolicies(String abacServiceName, String serviceId) { + this.setServiceName(abacServiceName); + this.setPolicyUpdateTime(new Date()); + this.setPolicyVersion(-1L); + this.setServiceId(serviceId); + } + + public ABACPolicies() {} + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public String getServiceId() { + return serviceId; + } + + public void setServiceId(String serviceId) { + this.serviceId = serviceId; + } + + public Long getPolicyVersion() { + return policyVersion; + } + + public void setPolicyVersion(Long policyVersion) { + this.policyVersion = policyVersion; + } + + public Date getPolicyUpdateTime() { + return policyUpdateTime; + } + + public void setPolicyUpdateTime(Date policyUpdateTime) { + this.policyUpdateTime = policyUpdateTime; + } + + public List getPolicies() { + return policies == null ? new ArrayList<>() : policies; + } + + public void setPolicies(List policies) { + this.policies = policies; + } + + public RangerServiceDef getServiceDef() { + return serviceDef; + } + + public void setServiceDef(RangerServiceDef serviceDef) { + this.serviceDef = serviceDef; + } + + public String getAuditMode() { + return auditMode; + } + + public void setAuditMode(String auditMode) { + this.auditMode = auditMode; + } + + public Map getServiceConfig() { + return serviceConfig; + } + + public void setServiceConfig(Map serviceConfig) { + this.serviceConfig = serviceConfig; + } + + @Override + public String toString() { + return "serviceName=" + serviceName + ", " + + "serviceId=" + serviceId + ", " + + "policyVersion=" + policyVersion + ", " + + "policyUpdateTime=" + policyUpdateTime + ", " + + "policies=" + policies + ", " + + "serviceDef=" + serviceDef + ", " + + "auditMode=" + auditMode + + "serviceConfig=" + serviceConfig + ; + } + } + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class SecurityZoneInfo implements java.io.Serializable { + private static final long serialVersionUID = 1L; + private String zoneName; + private List>> resources; + private List policies; + private List policyDeltas; + private Boolean containsAssociatedTagService; + + public String getZoneName() { + return zoneName; + } + + public List>> getResources() { + return resources; + } + + public List getPolicies() { + return policies; + } + + public List getPolicyDeltas() { return policyDeltas; } + + public Boolean getContainsAssociatedTagService() { return containsAssociatedTagService; } + + public void setZoneName(String zoneName) { + this.zoneName = zoneName; + } + + public void setResources(List>> resources) { + this.resources = resources; + } + + public void setPolicies(List policies) { + this.policies = policies; + } + + public void setPolicyDeltas(List policyDeltas) { this.policyDeltas = policyDeltas; } + + public void setContainsAssociatedTagService(Boolean containsAssociatedTagService) { this.containsAssociatedTagService = containsAssociatedTagService; } + + @Override + public String toString() { + return "zoneName=" + zoneName + ", " + + "resources=" + resources + ", " + + "policies=" + policies + ", " + + "policyDeltas=" + policyDeltas + ", " + + "containsAssociatedTagService=" + containsAssociatedTagService + ; + } + } + + static public ServicePolicies copyHeader(ServicePolicies source) { + ServicePolicies ret = new ServicePolicies(); + + ret.setServiceName(source.getServiceName()); + ret.setServiceId(source.getServiceId()); + ret.setPolicyVersion(source.getPolicyVersion()); + ret.setAuditMode(source.getAuditMode()); + ret.setServiceDef(source.getServiceDef()); + ret.setPolicyUpdateTime(source.getPolicyUpdateTime()); + ret.setSecurityZones(source.getSecurityZones()); + ret.setPolicies(Collections.emptyList()); + ret.setPolicyDeltas(null); + if (source.getTagPolicies() != null) { + TagPolicies tagPolicies = copyHeader(source.getTagPolicies(), source.getServiceDef().getName()); + ret.setTagPolicies(tagPolicies); + } + + if (source.getAbacPolicies() != null) { + ABACPolicies abacPolicies = copyHeader(source.getAbacPolicies(), null); + ret.setAbacPolicies(abacPolicies); + } + + return ret; + } + + static public ABACPolicies copyHeader(ABACPolicies source, String componentServiceName) { + ABACPolicies ret = new ABACPolicies(); + + ret.setServiceName(source.getServiceName()); + ret.setServiceId(source.getServiceId()); + ret.setPolicyVersion(source.getPolicyVersion()); + ret.setAuditMode(source.getAuditMode()); + ret.setPolicyUpdateTime(source.getPolicyUpdateTime()); + ret.setPolicies(new ArrayList<>()); + + if (componentServiceName != null) { + ret.setServiceDef(ServiceDefUtil.normalizeAccessTypeDefs(source.getServiceDef(), componentServiceName)); + } + + return ret; + } + + static public TagPolicies copyHeader(TagPolicies source, String componentServiceName) { + TagPolicies ret = new TagPolicies(); + + ret.setServiceName(source.getServiceName()); + ret.setServiceId(source.getServiceId()); + ret.setPolicyVersion(source.getPolicyVersion()); + ret.setAuditMode(source.getAuditMode()); + ret.setServiceDef(ServiceDefUtil.normalizeAccessTypeDefs(source.getServiceDef(), componentServiceName)); + ret.setPolicyUpdateTime(source.getPolicyUpdateTime()); + ret.setPolicies(Collections.emptyList()); + + return ret; + } + + private static Map fetchDeletedDeltaMap(List deltas) { + Map ret = new HashMap<>(); + for (RangerPolicyDelta delta : deltas) { + if (delta.getChangeType() == RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE || delta.getChangeType() == RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE) { + ret.put(delta.getPolicyAtlasGuid(), delta); + } + } + return ret; + } + + public static ServicePolicies applyDelta(final ServicePolicies servicePolicies, RangerPolicyEngineImpl policyEngine) { + ServicePolicies ret = copyHeader(servicePolicies); + + List oldResourcePolicies = policyEngine.getResourcePolicies(); + List oldTagPolicies = policyEngine.getTagPolicies(); + Map deletedDeltaMap = fetchDeletedDeltaMap(servicePolicies.getPolicyDeltas()); + + List resourcePoliciesAfterDelete = + RangerPolicyDeltaUtil.deletePoliciesByDelta(oldResourcePolicies, deletedDeltaMap); + List newResourcePolicies = + RangerPolicyDeltaUtil.applyDeltas(resourcePoliciesAfterDelete, servicePolicies.getPolicyDeltas(), servicePolicies.getServiceDef().getName(), servicePolicies.getServiceName()); + + ret.setPolicies(newResourcePolicies); + + List newTagPolicies; + if (servicePolicies.getTagPolicies() != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("applyingDeltas for tag policies"); + } + List tagPoliciesAfterDelete = + RangerPolicyDeltaUtil.deletePoliciesByDelta(oldTagPolicies, deletedDeltaMap); + newTagPolicies = RangerPolicyDeltaUtil.applyDeltas(tagPoliciesAfterDelete, servicePolicies.getPolicyDeltas(), servicePolicies.getTagPolicies().getServiceDef().getName(), servicePolicies.getTagPolicies().getServiceName()); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("No need to apply deltas for tag policies"); + } + newTagPolicies = oldTagPolicies; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("New tag policies: " + newTagPolicies); + } + + if (ret.getTagPolicies() != null) { + ret.getTagPolicies().setPolicies(newTagPolicies); + } + + if (servicePolicies.getAbacPolicies() != null ) { + List oldAbacPolicies = policiesStore.getAbacPolicies() != null ? policiesStore.getAbacPolicies() : new ArrayList<>();; + List abacPoliciesAfterDelete = + RangerPolicyDeltaUtil.deletePoliciesByDelta(oldAbacPolicies, deletedDeltaMap); + List newAbacPolicies = + RangerPolicyDeltaUtil.applyDeltas(abacPoliciesAfterDelete, servicePolicies.getPolicyDeltas(), servicePolicies.getAbacPolicies().getServiceName(), servicePolicies.getAbacPolicies().getServiceName()); + ret.getAbacPolicies().setPolicies(newAbacPolicies); + } + + return ret; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/ServiceTags.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/ServiceTags.java new file mode 100644 index 00000000000..3118534e9a6 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/ServiceTags.java @@ -0,0 +1,207 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + + + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.apache.atlas.plugin.model.RangerServiceResource; +import org.apache.atlas.plugin.model.RangerTag; +import org.apache.atlas.plugin.model.RangerTagDef; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class ServiceTags implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + public static final String OP_ADD_OR_UPDATE = "add_or_update"; + public static final String OP_DELETE = "delete"; + public static final String OP_REPLACE = "replace"; + + public enum TagsChangeExtent { NONE, TAGS, SERVICE_RESOURCE, ALL } + public enum TagsChangeType { NONE, SERVICE_RESOURCE_UPDATE, TAG_UPDATE, TAG_RESOURCE_MAP_UPDATE, RANGER_ADMIN_START, INVALIDATE_TAG_DELTAS, ALL } + + private String op = OP_ADD_OR_UPDATE; + private String serviceName; + private Long tagVersion; + private Date tagUpdateTime; + private Map tagDefinitions; + private Map tags; + private List serviceResources; + private Map> resourceToTagIds; + private Boolean isDelta; + private TagsChangeExtent tagsChangeExtent; + + public ServiceTags() { + this(OP_ADD_OR_UPDATE, null, 0L, null, null, null, null, null); + } + + public ServiceTags(String op, String serviceName, Long tagVersion, Date tagUpdateTime, Map tagDefinitions, + Map tags, List serviceResources, Map> resourceToTagIds) { + this(op, serviceName, tagVersion, tagUpdateTime, tagDefinitions, tags, serviceResources, resourceToTagIds, false, TagsChangeExtent.ALL); + } + public ServiceTags(String op, String serviceName, Long tagVersion, Date tagUpdateTime, Map tagDefinitions, + Map tags, List serviceResources, Map> resourceToTagIds, Boolean isDelta, TagsChangeExtent tagsChangeExtent) { + setOp(op); + setServiceName(serviceName); + setTagVersion(tagVersion); + setTagUpdateTime(tagUpdateTime); + setTagDefinitions(tagDefinitions); + setTags(tags); + setServiceResources(serviceResources); + setResourceToTagIds(resourceToTagIds); + setIsDelta(isDelta); + setTagsChangeExtent(tagsChangeExtent); + } + /** + * @return the op + */ + public String getOp() { + return op; + } + + /** + * @return the serviceName + */ + public String getServiceName() { + return serviceName; + } + + /** + * @param op the op to set + */ + public void setOp(String op) { + this.op = op; + } + + /** + * @param serviceName the serviceName to set + */ + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + /** + * @return the tagVersion + */ + public Long getTagVersion() { + return tagVersion; + } + + /** + * @param tagVersion the version to set + */ + public void setTagVersion(Long tagVersion) { + this.tagVersion = tagVersion; + } + + /** + * @return the tagUpdateTime + */ + public Date getTagUpdateTime() { + return tagUpdateTime; + } + + /** + * @param tagUpdateTime the tagUpdateTime to set + */ + public void setTagUpdateTime(Date tagUpdateTime) { + this.tagUpdateTime = tagUpdateTime; + } + + public Map getTagDefinitions() { + return tagDefinitions; + } + + public void setTagDefinitions(Map tagDefinitions) { + this.tagDefinitions = tagDefinitions == null ? new HashMap() : tagDefinitions; + } + + public Map getTags() { + return tags; + } + + public void setTags(Map tags) { + this.tags = tags == null ? new HashMap() : tags; + } + + public List getServiceResources() { + return serviceResources; + } + + public void setServiceResources(List serviceResources) { + this.serviceResources = serviceResources == null ? new ArrayList() : serviceResources; + } + + public Map> getResourceToTagIds() { + return resourceToTagIds; + } + + public void setResourceToTagIds(Map> resourceToTagIds) { + this.resourceToTagIds = resourceToTagIds == null ? new HashMap>() : resourceToTagIds; + } + + public Boolean getIsDelta() { + return isDelta == null ? Boolean.FALSE : isDelta; + } + + public void setIsDelta(Boolean isDelta) { + this.isDelta = isDelta; + } + + public TagsChangeExtent getTagsChangeExtent() { + return tagsChangeExtent; + } + + public void setTagsChangeExtent(TagsChangeExtent tagsChangeExtent) { + this.tagsChangeExtent = tagsChangeExtent; + } + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("ServiceTags={") + .append("op=").append(op).append(", ") + .append("serviceName=").append(serviceName).append(", ") + .append("tagVersion=").append(tagVersion).append(", ") + .append("tagUpdateTime={").append(tagUpdateTime).append("}") + .append("isDelta={").append(isDelta).append("}") + .append("tagsChangeExtent={").append(tagsChangeExtent).append("}") + .append("}"); + + return sb; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/StringTokenReplacer.java b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/StringTokenReplacer.java new file mode 100644 index 00000000000..54fdc989032 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/plugin/util/StringTokenReplacer.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import java.util.Map; + +public class StringTokenReplacer { + private final char startChar; + private final char endChar; + private final char escapeChar; + private final String tokenPrefix; + + public StringTokenReplacer(char startChar, char endChar, char escapeChar, String tokenPrefix) { + this.startChar = startChar; + this.endChar = endChar; + this.escapeChar = escapeChar; + this.tokenPrefix = tokenPrefix; + } + + public String replaceTokens(String value, Map tokens) { + if(tokens == null || tokens.size() < 1 || value == null || value.length() < 1 || + (value.indexOf(startChar) == -1 && value.indexOf(endChar) == -1 && value.indexOf(escapeChar) == -1)) { + return value; + } + + StringBuilder ret = new StringBuilder(); + StringBuilder token = null; + + for(int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + + if(c == escapeChar) { + i++; + if(i < value.length()) { + c = value.charAt(i); + if (token != null) { + // if next char is not the escape char or endChar, retain the escapeChar + if (c != escapeChar && c != endChar) { + token.append(escapeChar); + } + token.append(c); + } else { + // if next char is not the escape char or startChar, retain the escapeChar + if (c != escapeChar && c != startChar) { + ret.append(escapeChar); + } + ret.append(c); + } + } else { + if (token != null) { + token.append(escapeChar); + } else { + ret.append(escapeChar); + } + } + continue; + } + + if(token == null) { // not in token + if(c == startChar) { + token = new StringBuilder(); + } else { + ret.append(c); + } + } else { // in token + if(c == endChar) { + String rawToken = token.toString(); + if (tokenPrefix.length() == 0 || rawToken.startsWith(tokenPrefix)) { + Object replaced = RangerAccessRequestUtil.getTokenFromContext(tokens, rawToken.substring(tokenPrefix.length())); + if (replaced != null) { + ret.append(replaced.toString()); + } else { + ret.append(startChar).append(token).append(endChar); + } + } else { + ret.append(startChar).append(token).append(endChar); + } + token = null; + } else { + token.append(c); + } + } + } + + if(token != null) { // if no endChar is found + ret.append(startChar).append(token); + } + + return ret.toString(); + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/AbstractCachePolicyTransformer.java b/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/AbstractCachePolicyTransformer.java new file mode 100644 index 00000000000..8d44160ab36 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/AbstractCachePolicyTransformer.java @@ -0,0 +1,51 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.policytransformer; + +import org.apache.atlas.exception.AtlasBaseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Map; + +public abstract class AbstractCachePolicyTransformer implements CachePolicyTransformer { + + private static final Logger LOG = LoggerFactory.getLogger(AbstractCachePolicyTransformer.class); + + public static final String PLACEHOLDER_ENTITY = "{entity}"; + public static final String PLACEHOLDER_ENTITY_TYPE = "{entity-type}"; + public static final String PLACEHOLDER_FILTER_CRITERIA = "{criteria}"; + public static final String PLACEHOLDER_FILTER_ENTITY_CRITERIA = "{entity-criteria}"; + public static final String PLACEHOLDER_TAG = "{tag}"; + + private static Map TEMPLATES = new HashMap<>(); + + public PolicyTransformerTemplate getTemplate(String fileSuffix) throws AtlasBaseException { + if (!TEMPLATES.containsKey(fileSuffix)) { + try { + TEMPLATES.put(fileSuffix, CacheTransformerTemplateHelper.getTemplate(fileSuffix)); + } catch (AtlasBaseException e) { + LOG.error("Failed to load template for policies: {}", fileSuffix); + throw e; + } + } + + return TEMPLATES.get(fileSuffix); + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/CachePolicyTransformer.java b/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/CachePolicyTransformer.java new file mode 100644 index 00000000000..b18311f034e --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/CachePolicyTransformer.java @@ -0,0 +1,27 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.policytransformer; + +import org.apache.atlas.model.instance.AtlasEntityHeader; + +import java.util.List; + +public interface CachePolicyTransformer { + + List transform(AtlasEntityHeader atlasPolicy); +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/CachePolicyTransformerImpl.java b/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/CachePolicyTransformerImpl.java new file mode 100644 index 00000000000..bf5d6662564 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/CachePolicyTransformerImpl.java @@ -0,0 +1,809 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.policytransformer; + +import org.apache.atlas.AtlasException; +import org.apache.atlas.RequestContext; +import org.apache.atlas.discovery.EntityDiscoveryService; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.audit.EntityAuditEventV2; +import org.apache.atlas.model.audit.EntityAuditEventV2.EntityAuditActionV2; +import org.apache.atlas.model.discovery.AtlasSearchResult; +import org.apache.atlas.model.discovery.IndexSearchParams; +import org.apache.atlas.model.instance.AtlasEntityHeader; +import org.apache.atlas.model.instance.AtlasStruct; +import org.apache.atlas.plugin.model.RangerPolicyDelta; +import org.apache.atlas.plugin.util.ServicePolicies; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.model.RangerPolicy.RangerDataMaskPolicyItem; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItem; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemAccess; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemCondition; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyItemDataMaskInfo; +import org.apache.atlas.plugin.model.RangerPolicy.RangerPolicyResource; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerValiditySchedule; +import org.apache.atlas.plugin.util.ServicePolicies.TagPolicies; +import org.apache.atlas.repository.graphdb.AtlasGraph; +import org.apache.atlas.repository.graphdb.janus.AtlasJanusGraph; +import org.apache.atlas.repository.store.graph.v2.EntityGraphRetriever; +import org.apache.atlas.repository.store.graph.v2.tags.TagDAO; +import org.apache.atlas.repository.store.graph.v2.tags.TagDAOCassandraImpl; +import org.apache.atlas.type.AtlasType; +import org.apache.atlas.type.AtlasTypeRegistry; +import org.apache.atlas.utils.AtlasPerfMetrics; +import org.apache.atlas.v1.model.instance.Id; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.apache.atlas.repository.Constants.NAME; +import static org.apache.atlas.repository.Constants.QUALIFIED_NAME; +import static org.apache.atlas.repository.Constants.SERVICE_ENTITY_TYPE; +import static org.apache.atlas.repository.Constants.POLICY_ENTITY_TYPE; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_CATEGORY; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_CONNECTION_QN; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_FILTER_CRITERIA; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_IS_ENABLED; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_PRIORITY; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_SERVICE_NAME; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_SUB_CATEGORY; +import static org.apache.atlas.repository.util.AccessControlUtils.POLICY_CATEGORY_DATAMESH; +import static org.apache.atlas.repository.util.AccessControlUtils.POLICY_CATEGORY_PERSONA; +import static org.apache.atlas.repository.util.AccessControlUtils.POLICY_CATEGORY_PURPOSE; +import static org.apache.atlas.repository.util.AccessControlUtils.POLICY_SERVICE_NAME_ABAC; +import static org.apache.atlas.repository.util.AccessControlUtils.getIsPolicyEnabled; +import static org.apache.atlas.repository.util.AccessControlUtils.getPolicyCategory; +import static org.apache.atlas.repository.util.AccessControlUtils.getPolicyFilterCriteria; +import static org.apache.atlas.repository.util.AccessControlUtils.getPolicyResourceCategory; + +@Component +public class CachePolicyTransformerImpl { + private static final Logger LOG = LoggerFactory.getLogger(CachePolicyTransformerImpl.class); + + private static final String RESOURCES_SPLITTER = ":"; + + static final String ATTR_QUALIFIED_NAME = "qualifiedName"; + static final String ATTR_NAME = "name"; + + public static final String ATTR_POLICY_ACTIONS = "policyActions"; + public static final String ATTR_POLICY_TYPE = "policyType"; + public static final String ATTR_POLICY_RESOURCES = "policyResources"; + + public static final String ATTR_SERVICE_SERVICE_TYPE = "authServiceType"; + public static final String ATTR_SERVICE_TAG_SERVICE = "tagService"; + public static final String ATTR_SERVICE_ABAC_SERVICE = "abacService"; + public static final String ATTR_SERVICE_IS_ENABLED = "authServiceIsEnabled"; + public static final String ATTR_SERVICE_LAST_SYNC = "authServicePolicyLastSync"; + + private static final String ATTR_POLICY_RESOURCES_CATEGORY = "policyResourceCategory"; + private static final String ATTR_POLICY_GROUPS = "policyGroups"; + private static final String ATTR_POLICY_USERS = "policyUsers"; + private static final String ATTR_POLICY_ROLES = "policyRoles"; + public static final String ATTR_POLICY_VALIDITY = "policyValiditySchedule"; + public static final String ATTR_POLICY_CONDITIONS = "policyConditions"; + public static final String ATTR_POLICY_MASK_TYPE = "policyMaskType"; + + private static final String RESOURCE_SERVICE_DEF_PATH = "/service-defs/"; + private static final String RESOURCE_SERVICE_DEF_PATTERN = RESOURCE_SERVICE_DEF_PATH + "atlas-servicedef-%s.json"; + public static final int POLICY_BATCH_SIZE = 250; + + private EntityDiscoveryService discoveryService; + private AtlasGraph graph; + private EntityGraphRetriever entityRetriever; + + private PersonaCachePolicyTransformer personaTransformer; + private PurposeCachePolicyTransformer purposeTransformer; + + private AtlasEntityHeader service; + private Map services; + + private final Map auditEventToDeltaChangeType; + + @Inject + public CachePolicyTransformerImpl(AtlasTypeRegistry typeRegistry) throws AtlasBaseException { + this.graph = new AtlasJanusGraph(); + this.entityRetriever = new EntityGraphRetriever(graph, typeRegistry); + + personaTransformer = new PersonaCachePolicyTransformer(entityRetriever); + purposeTransformer = new PurposeCachePolicyTransformer(entityRetriever); + + try { + this.discoveryService = new EntityDiscoveryService(typeRegistry, graph, null, null, null, null, entityRetriever); + } catch (AtlasException e) { + LOG.error("Failed to initialize discoveryService"); + throw new AtlasBaseException(e.getCause()); + } + + this.auditEventToDeltaChangeType = new HashMap<>(); + this.auditEventToDeltaChangeType.put(EntityAuditActionV2.ENTITY_CREATE, RangerPolicyDelta.CHANGE_TYPE_POLICY_CREATE); + this.auditEventToDeltaChangeType.put(EntityAuditActionV2.ENTITY_UPDATE, RangerPolicyDelta.CHANGE_TYPE_POLICY_UPDATE); + this.auditEventToDeltaChangeType.put(EntityAuditActionV2.ENTITY_DELETE, RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE); + this.auditEventToDeltaChangeType.put(EntityAuditActionV2.ENTITY_PURGE, RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE); + + this.services = new HashMap<>(); + } + + public AtlasEntityHeader getService() { + return service; + } + + public ServicePolicies getPoliciesDelta(String serviceName, Map policyChanges, long lastAuditEventTime) { + AtlasPerfMetrics.MetricRecorder recorder = RequestContext.get().startMetricRecord("CachePolicyTransformerImpl.getPoliciesDelta." + serviceName); + + ServicePolicies servicePolicies = new ServicePolicies(); + + try { + service = getServiceEntity(serviceName); + servicePolicies.setServiceName(serviceName); + servicePolicies.setPolicyVersion(-1L); + + Date policyUpdateTime = lastAuditEventTime > 0 ? new Date(lastAuditEventTime) : new Date(); + servicePolicies.setPolicyUpdateTime(policyUpdateTime); + + if (service != null) { + servicePolicies.setServiceName(serviceName); + servicePolicies.setServiceId(service.getGuid()); + + String serviceDefName = String.format(RESOURCE_SERVICE_DEF_PATTERN, serviceName); + servicePolicies.setServiceDef(getResourceAsObject(serviceDefName, RangerServiceDef.class)); + + ArrayList policyGuids = new ArrayList<>(policyChanges.keySet()); + List allAtlasPolicies = getAtlasPolicies(serviceName, POLICY_BATCH_SIZE, policyGuids); + Date latestUpdateTime = allAtlasPolicies.stream().map(AtlasEntityHeader::getUpdateTime).max(Date::compareTo).orElse(null); + servicePolicies.setPolicyUpdateTime(latestUpdateTime); + + List atlasServicePolicies = allAtlasPolicies.stream().filter(x -> serviceName.equals(x.getAttribute(ATTR_POLICY_SERVICE_NAME))).collect(Collectors.toList()); + List policiesDelta = getRangerPolicyDelta(service, policyChanges, atlasServicePolicies); + + // Process tag based policies + String tagServiceName = (String) service.getAttribute(ATTR_SERVICE_TAG_SERVICE); + if (StringUtils.isNotEmpty(tagServiceName)) { + AtlasEntityHeader tagService = getServiceEntity(tagServiceName); + if (tagService != null) { + TagPolicies tagPolicies = new TagPolicies(); + tagPolicies.setServiceName(tagServiceName); + tagPolicies.setPolicyUpdateTime(new Date()); + tagPolicies.setServiceId(tagService.getGuid()); + tagPolicies.setPolicyVersion(-1L); + + String tagServiceDefName = String.format(RESOURCE_SERVICE_DEF_PATTERN, tagService.getAttribute(NAME)); + tagPolicies.setServiceDef(getResourceAsObject(tagServiceDefName, RangerServiceDef.class)); + servicePolicies.setTagPolicies(tagPolicies); + + // filter and set tag policies + List tagServicePolicies = allAtlasPolicies.stream().filter(x -> tagServiceName.equals(x.getAttribute(ATTR_POLICY_SERVICE_NAME))).collect(Collectors.toList()); + List tagPoliciesDelta = getRangerPolicyDelta(tagService, policyChanges, tagServicePolicies); + policiesDelta.addAll(tagPoliciesDelta); + } + } + + // Process abac policies + String abacServiceName = (String) service.getAttribute(ATTR_SERVICE_ABAC_SERVICE); + if (StringUtils.isNotEmpty(abacServiceName)) { + AtlasEntityHeader abacService = services.get(abacServiceName); + if (abacService == null) { + abacService = getServiceEntity(abacServiceName); + services.put(abacServiceName, abacService); + LOG.info("PolicyDelta: {}: ABAC_AUTH: fetched abac service type={}", serviceName, abacService != null ? abacService.getTypeName() : null); + } + + // filter and set abac policies + if (abacService != null) { + ServicePolicies.ABACPolicies abacPolicies = new ServicePolicies.ABACPolicies(abacServiceName, abacService.getGuid()); + servicePolicies.setAbacPolicies(abacPolicies); // this only sets the service name for abac policies, the actual policies will be added to main delta.policies itself + + List abacServicePolicies = allAtlasPolicies.stream().filter(x -> abacServiceName.equals(x.getAttribute(ATTR_POLICY_SERVICE_NAME))).collect(Collectors.toList()); + List abacPoliciesDelta = getRangerPolicyDelta(abacService, policyChanges, abacServicePolicies); + policiesDelta.addAll(abacPoliciesDelta); + LOG.info("PolicyDelta: {}: ABAC_AUTH: abac policies found={} delta created={}", serviceName, abacServicePolicies.size(), abacPoliciesDelta.size()); + } else { + LOG.error("PolicyDelta: {}: ABAC_AUTH: abac policy service not found", serviceName); + } + } + + servicePolicies.setPolicyDeltas(policiesDelta); + LOG.info("PolicyDelta: {}: ABAC_AUTH: Found total delta={}", serviceName, policiesDelta.size()); + } + + } catch (Exception e) { + LOG.error("PolicyDelta: {}: ABAC_AUTH: ERROR in getPoliciesDelta: {}", serviceName, e.getMessage(), e); + return null; + } + + RequestContext.get().endMetricRecord(recorder); + return servicePolicies; + } + + + public ServicePolicies getPoliciesAll(String serviceName, String pluginId, Long lastUpdatedTime) { + //TODO: return only if updated + AtlasPerfMetrics.MetricRecorder recorder = RequestContext.get().startMetricRecord("CachePolicyTransformerImpl.getPolicies." + serviceName); + + ServicePolicies servicePolicies = new ServicePolicies(); + + try { + servicePolicies.setServiceName(serviceName); + + service = getServiceEntity(serviceName); + servicePolicies.setPolicyVersion(-1L); + servicePolicies.setPolicyUpdateTime(new Date()); + + if (service != null) { + List allPolicies = getServicePolicies(service, POLICY_BATCH_SIZE); + servicePolicies.setServiceName(serviceName); + servicePolicies.setServiceId(service.getGuid()); + + String serviceDefName = String.format(RESOURCE_SERVICE_DEF_PATTERN, serviceName); + servicePolicies.setServiceDef(getResourceAsObject(serviceDefName, RangerServiceDef.class)); + + + //Process tag based policies + String tagServiceName = (String) service.getAttribute(ATTR_SERVICE_TAG_SERVICE); + if (StringUtils.isNotEmpty(tagServiceName)) { + AtlasEntityHeader tagService = getServiceEntity(tagServiceName); + + if (tagService != null) { + allPolicies.addAll(getServicePolicies(tagService, 0)); + + TagPolicies tagPolicies = new TagPolicies(); + + tagPolicies.setServiceName(tagServiceName); + tagPolicies.setPolicyUpdateTime(new Date()); + tagPolicies.setServiceId(tagService.getGuid()); + tagPolicies.setPolicyVersion(-1L); + + String tagServiceDefName = String.format(RESOURCE_SERVICE_DEF_PATTERN, tagService.getAttribute(NAME)); + tagPolicies.setServiceDef(getResourceAsObject(tagServiceDefName, RangerServiceDef.class)); + + servicePolicies.setTagPolicies(tagPolicies); + } + } + + //Process abac based policies + String abacServiceName = (String) service.getAttribute(ATTR_SERVICE_ABAC_SERVICE); + + if (StringUtils.isNotEmpty(abacServiceName)) { + AtlasEntityHeader abacService = getServiceEntity(abacServiceName); + if (abacService != null) { + allPolicies.addAll(getServicePolicies(abacService, 0)); + ServicePolicies.ABACPolicies abacPolicies = new ServicePolicies.ABACPolicies(abacServiceName, abacService.getGuid()); + + servicePolicies.setAbacPolicies(abacPolicies); + } + } + + AtlasPerfMetrics.MetricRecorder recorderFilterPolicies = RequestContext.get().startMetricRecord("filterPolicies"); + + //filter out policies based on serviceName + List policiesA = allPolicies.stream().filter(x -> serviceName.equals(x.getService())).collect(Collectors.toList()); + List policiesB = allPolicies.stream().filter(x -> tagServiceName.equals(x.getService())).collect(Collectors.toList()); + + List policiesC = new ArrayList<>(0); + if (StringUtils.isNotEmpty(abacServiceName)) { + policiesC = allPolicies.stream().filter(x -> abacServiceName.equals(x.getService())).collect(Collectors.toList()); + } + + servicePolicies.setPolicies(policiesA); + servicePolicies.getTagPolicies().setPolicies(policiesB); + + if (servicePolicies.getAbacPolicies() == null) { + servicePolicies.setAbacPolicies(new ServicePolicies.ABACPolicies()); + } + servicePolicies.getAbacPolicies().setPolicies(policiesC); + + RequestContext.get().endMetricRecord(recorderFilterPolicies); + + LOG.info("Found {} policies ({}) and {} ({}) and {} ({}) policies", + servicePolicies.getPolicies().size(), serviceName, + servicePolicies.getTagPolicies().getPolicies().size(), tagServiceName, + servicePolicies.getAbacPolicies().getPolicies().size(), abacServiceName); + } + + } catch (Exception e) { + LOG.error("ERROR in getPolicies: ", e); + return null; + } + + RequestContext.get().endMetricRecord(recorder); + return servicePolicies; + } + + private List getServicePolicies(AtlasEntityHeader service, int batchSize) throws AtlasBaseException, IOException { + + List servicePolicies = new ArrayList<>(); + + String serviceName = (String) service.getAttribute("name"); + String serviceType = (String) service.getAttribute("authServiceType"); + List atlasPolicies = getAtlasPolicies(serviceName, batchSize, new ArrayList<>()); + + if (CollectionUtils.isNotEmpty(atlasPolicies)) { + //transform policies + servicePolicies = transformAtlasPoliciesToRangerPolicies(atlasPolicies, serviceType, serviceName); + } + return servicePolicies; + } + + private List getRangerPolicyDelta(AtlasEntityHeader service, Map policyChanges, List atlasPolicies) throws AtlasBaseException, IOException { + String serviceName = (String) service.getAttribute("name"); + String serviceType = (String) service.getAttribute("authServiceType"); + AtlasPerfMetrics.MetricRecorder recorder = RequestContext.get().startMetricRecord("CachePolicyTransformerImpl.getRangerPolicyDelta." + serviceName); + + List policyDeltas = new ArrayList<>(); + if (policyChanges.isEmpty()) { + return policyDeltas; + } + + ArrayList policyGuids = new ArrayList<>(policyChanges.keySet()); + + List rangerPolicies = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(atlasPolicies)) { + rangerPolicies = transformAtlasPoliciesToRangerPolicies(atlasPolicies, serviceType, serviceName); + } + + for (RangerPolicy policy : rangerPolicies) { + Integer changeType = auditEventToDeltaChangeType.get(policyChanges.get(policy.getAtlasGuid())); + if (changeType == null) { + LOG.warn("PolicyDelta: {}: No change type found for policy guid={} audit_event={}", serviceName, policy.getAtlasGuid(), policyChanges.get(policy.getAtlasGuid())); + continue; + } + RangerPolicyDelta delta = new RangerPolicyDelta(policy.getId(), changeType, policy.getVersion(), policy); + policyDeltas.add(delta); + } + + // handle delete changes separately as they won't be present in atlas policies + List deletedPolicyDeltas = new ArrayList<>(); + for (String policyGuid : policyGuids) { + Integer deltaChangeType = auditEventToDeltaChangeType.get(policyChanges.get(policyGuid)); + if (deltaChangeType == RangerPolicyDelta.CHANGE_TYPE_POLICY_DELETE) { + RangerPolicy deletedPolicy = new RangerPolicy(); + deletedPolicy.setGuid(policyGuid); + deletedPolicy.setService(serviceName); + deletedPolicy.setServiceType(serviceType); + RangerPolicyDelta deletedPolicyDelta = new RangerPolicyDelta( + deletedPolicy.getId(), + deltaChangeType, + deletedPolicy.getVersion(), + deletedPolicy + ); + deletedPolicyDeltas.add(deletedPolicyDelta); + } + } + + policyDeltas.addAll(deletedPolicyDeltas); + + LOG.info("PolicyDelta: {}: atlas policies found={}, delta created={}, including deleted policies={}", + serviceName, atlasPolicies.size(), policyDeltas.size(), deletedPolicyDeltas.size()); + RequestContext.get().endMetricRecord(recorder); + + return policyDeltas; + } + + public Map createPolicyChangeMap(String serviceName, List events) { + Map policyChanges = new HashMap<>(); + for (EntityAuditEventV2 event : events) { + if (POLICY_ENTITY_TYPE.equals(event.getTypeName()) && !policyChanges.containsKey(event.getEntityId())) { + policyChanges.put(event.getEntityId(), event.getAction()); + } + } + + LOG.info("PolicyDelta: {}: Found {} policy changes in {} policies", serviceName, events.size(), policyChanges.size()); + + return policyChanges; + } + + private List transformAtlasPoliciesToRangerPolicies(List atlasPolicies, + String serviceType, + String serviceName) throws IOException, AtlasBaseException { + AtlasPerfMetrics.MetricRecorder recorder = RequestContext.get().startMetricRecord("CachePolicyTransformerImpl."+serviceName+".transformAtlasPoliciesToRangerPolicies"); + + List rangerPolicies = new ArrayList<>(); + try { + for (AtlasEntityHeader atlasPolicy : atlasPolicies) { + + String policyCategory = getPolicyCategory(atlasPolicy); + if (POLICY_CATEGORY_PERSONA.equals(policyCategory)) { + + List transformedAtlasPolicies = personaTransformer.transform(atlasPolicy); + for (AtlasEntityHeader transformedPolicy : transformedAtlasPolicies) { + rangerPolicies.add(toRangerPolicy(transformedPolicy, serviceType)); + } + + } else if (POLICY_CATEGORY_PURPOSE.equals(policyCategory)) { + List transformedAtlasPolicies = purposeTransformer.transform(atlasPolicy); + + for (AtlasEntityHeader transformedPolicy : transformedAtlasPolicies) { + rangerPolicies.add(toRangerPolicy(transformedPolicy, serviceType)); + } + + } + else if (POLICY_CATEGORY_DATAMESH.equals(policyCategory)) { + RangerPolicy rangerPolicy = getRangerPolicy(atlasPolicy, serviceType); + + //GET policy Item + setPolicyItems(rangerPolicy, atlasPolicy); + + //GET policy Resources + setPolicyResourcesForDatameshPolicies(rangerPolicy, atlasPolicy); + + rangerPolicies.add(rangerPolicy); + + } else { + rangerPolicies.add(toRangerPolicy(atlasPolicy, serviceType)); + } + } + + } finally { + RequestContext.get().endMetricRecord(recorder); + } + + return rangerPolicies; + } + + private RangerPolicy toRangerPolicy(AtlasEntityHeader atlasPolicy, String serviceType) throws AtlasBaseException, IOException { + RangerPolicy rangerPolicy = getRangerPolicy(atlasPolicy, serviceType); + + //GET policy Item + setPolicyItems(rangerPolicy, atlasPolicy); + + //GET policy Resources + setPolicyResources(rangerPolicy, atlasPolicy); + + return rangerPolicy; + } + + private void setPolicyResources(RangerPolicy rangerPolicy, AtlasEntityHeader atlasPolicy) throws IOException { + rangerPolicy.setResources(getFinalResources(atlasPolicy)); + } + + private void setPolicyResourcesForDatameshPolicies(RangerPolicy rangerPolicy, AtlasEntityHeader atlasPolicy) { + Map resources = getFinalResources(atlasPolicy); + + if (!resources.containsKey("entity-classification")) { + RangerPolicyResource resource = new RangerPolicyResource(Arrays.asList("*"), false, false); + resources.put("entity-classification", resource); + } + + if (!resources.containsKey("entity-type")) { + RangerPolicyResource resource = new RangerPolicyResource(Arrays.asList("*"), false, false); + resources.put("entity-type", resource); + } + + rangerPolicy.setResources(resources); + } + + private Map getFinalResources(AtlasEntityHeader atlasPolicy) { + List atlasResources = (List) atlasPolicy.getAttribute("policyResources"); + + Map> resourceValuesMap = new HashMap<>(); + + for (String atlasResource : atlasResources) { + String resourceName = atlasResource.split(RESOURCES_SPLITTER)[0]; + + if (!resourceValuesMap.containsKey(resourceName)) { + String resourceNameFinal = resourceName + ":"; + List applicables = atlasResources.stream().filter(x -> x.startsWith(resourceNameFinal)).collect(Collectors.toList()); + List values = applicables.stream().map(x -> x.substring(resourceNameFinal.length())).collect(Collectors.toList()); + resourceValuesMap.put(resourceName, values); + } + } + + Map resources = new HashMap<>(); + for (String key : resourceValuesMap.keySet()) { + RangerPolicyResource resource = new RangerPolicyResource(resourceValuesMap.get(key), false, false); + resources.put(key, resource); + } + + return resources; + } + + private T getResourceAsObject(String resourceName, Class clazz) throws IOException { + InputStream stream = getClass().getResourceAsStream(resourceName); + return AtlasType.fromJson(stream, clazz); + } + + private void setPolicyItems(RangerPolicy rangerPolicy, AtlasEntityHeader atlasPolicy) throws AtlasBaseException { + + String policyType = (String) atlasPolicy.getAttribute("policyType"); + + List users = (List) atlasPolicy.getAttribute("policyUsers"); + List groups = (List) atlasPolicy.getAttribute("policyGroups"); + List roles = (List) atlasPolicy.getAttribute("policyRoles"); + + List accesses = new ArrayList<>(); + List actions = (List) atlasPolicy.getAttribute("policyActions"); + + actions.forEach(action -> accesses.add(new RangerPolicyItemAccess(action))); + + + if ("allow".equals(policyType)) { + RangerPolicyItem item = new RangerPolicyItem(); + item.setUsers(users); + item.setGroups(groups); + item.setRoles(roles); + item.setAccesses(accesses); + + rangerPolicy.setPolicyItems(Collections.singletonList(item)); + rangerPolicy.setPolicyType(RangerPolicy.POLICY_TYPE_ACCESS); + + } else if ("deny".equals(policyType)) { + RangerPolicyItem item = new RangerPolicyItem(); + item.setUsers(users); + item.setGroups(groups); + item.setRoles(roles); + item.setAccesses(accesses); + + rangerPolicy.setDenyPolicyItems(Collections.singletonList(item)); + rangerPolicy.setPolicyType(RangerPolicy.POLICY_TYPE_ACCESS); + + } else if ("allowExceptions".equals(policyType)) { + RangerPolicyItem item = new RangerPolicyItem(); + item.setUsers(users); + item.setGroups(groups); + item.setRoles(roles); + item.setAccesses(accesses); + + rangerPolicy.setAllowExceptions(Collections.singletonList(item)); + rangerPolicy.setPolicyType(RangerPolicy.POLICY_TYPE_ACCESS); + + } else if ("denyExceptions".equals(policyType)) { + RangerPolicyItem item = new RangerPolicyItem(); + item.setUsers(users); + item.setGroups(groups); + item.setRoles(roles); + item.setAccesses(accesses); + + rangerPolicy.setDenyExceptions(Collections.singletonList(item)); + rangerPolicy.setPolicyType(RangerPolicy.POLICY_TYPE_ACCESS); + + } else if ("dataMask".equals(policyType)) { + + rangerPolicy.setPolicyType(RangerPolicy.POLICY_TYPE_DATAMASK); + + RangerDataMaskPolicyItem item = new RangerDataMaskPolicyItem(); + item.setUsers(users); + item.setGroups(groups); + item.setRoles(roles); + item.setAccesses(accesses); + + String maskType = (String) atlasPolicy.getAttribute(ATTR_POLICY_MASK_TYPE); + + if (StringUtils.isEmpty(maskType)) { + LOG.error("MASK type not found"); + throw new AtlasBaseException("MASK type not found"); + } + + RangerPolicyItemDataMaskInfo dataMaskInfo = new RangerPolicyItemDataMaskInfo(maskType, null, null); + item.setDataMaskInfo(dataMaskInfo); + + rangerPolicy.setDataMaskPolicyItems(Collections.singletonList(item)); + + } else if ("rowFilter".equals(policyType)) { + rangerPolicy.setPolicyType(RangerPolicy.POLICY_TYPE_ROWFILTER); + //TODO + } + } + + private List getPolicyConditions(AtlasEntityHeader atlasPolicy) { + List ret = new ArrayList<>(); + + if (!atlasPolicy.hasAttribute(ATTR_POLICY_CONDITIONS) || atlasPolicy.getAttribute(ATTR_POLICY_CONDITIONS) == null) { + return null; + } + + List conditions = (List) atlasPolicy.getAttribute(ATTR_POLICY_CONDITIONS); + + for (AtlasStruct condition : conditions) { + RangerPolicyItemCondition rangerCondition = new RangerPolicyItemCondition(); + + rangerCondition.setType((String) condition.getAttribute("policyConditionType")); + rangerCondition.setValues((List) condition.getAttribute("policyConditionValues")); + + ret.add(rangerCondition); + } + return ret; + } + + private List getPolicyValiditySchedule(AtlasEntityHeader atlasPolicy) { + List ret = new ArrayList<>(); + + if (!atlasPolicy.hasAttribute("policyValiditySchedule")) { + return null; + } + + List> validitySchedules = (List>) atlasPolicy.getAttribute("policyValiditySchedule"); + + + for (HashMap validitySchedule : validitySchedules) { + RangerValiditySchedule rangerValiditySchedule = new RangerValiditySchedule(); + + rangerValiditySchedule.setStartTime(validitySchedule.get("policyValidityScheduleStartTime")); + rangerValiditySchedule.setEndTime(validitySchedule.get("policyValidityScheduleEndTime")); + rangerValiditySchedule.setTimeZone(validitySchedule.get("policyValidityScheduleTimezone")); + + ret.add(rangerValiditySchedule); + } + return ret; + } + + private List getAtlasPolicies(String serviceName, int batchSize, List policyGuids) throws AtlasBaseException { + AtlasPerfMetrics.MetricRecorder recorder = RequestContext.get().startMetricRecord("CachePolicyTransformerImpl."+service+".getAtlasPolicies"); + + List ret = new ArrayList<>(); + try { + IndexSearchParams indexSearchParams = new IndexSearchParams(); + indexSearchParams.setExcludeClassifications(true); + + Set attributes = new HashSet<>(); + attributes.add(NAME); + attributes.add(ATTR_POLICY_CATEGORY); + attributes.add(ATTR_POLICY_SUB_CATEGORY); + attributes.add(ATTR_POLICY_FILTER_CRITERIA); + attributes.add(ATTR_POLICY_TYPE); + attributes.add(ATTR_POLICY_SERVICE_NAME); + attributes.add(ATTR_POLICY_USERS); + attributes.add(ATTR_POLICY_GROUPS); + attributes.add(ATTR_POLICY_ROLES); + attributes.add(ATTR_POLICY_ACTIONS); + attributes.add(ATTR_POLICY_RESOURCES); + attributes.add(ATTR_POLICY_RESOURCES_CATEGORY); + attributes.add(ATTR_POLICY_MASK_TYPE); + attributes.add(ATTR_POLICY_PRIORITY); + attributes.add(ATTR_POLICY_VALIDITY); + attributes.add(ATTR_POLICY_CONDITIONS); + attributes.add(ATTR_POLICY_IS_ENABLED); + attributes.add(ATTR_POLICY_CONNECTION_QN); + + Map dsl = getMap("size", 0); + + List> mustClauseList = new ArrayList<>(); + + mustClauseList.add(getMap("match", getMap("__state", Id.EntityState.ACTIVE))); + + if (!policyGuids.isEmpty()) { + mustClauseList.add(getMap("terms", getMap("__guid", policyGuids))); + } else { + mustClauseList.add(getMap("term", getMap(ATTR_POLICY_SERVICE_NAME, serviceName))); + mustClauseList.add(getMap("term", getMap(ATTR_POLICY_IS_ENABLED, true))); + } + + dsl.put("query", getMap("bool", getMap("must", mustClauseList))); + + List sortList = new ArrayList<>(0); + sortList.add(getMap("__timestamp", getMap("order", "asc"))); + sortList.add(getMap("__guid", getMap("order", "asc"))); + dsl.put("sort", sortList); + + indexSearchParams.setDsl(dsl); + indexSearchParams.setAttributes(attributes); + + int from = 0; + int size = 100; + + if (batchSize > 0) { + size = batchSize; + } + boolean found = true; + + do { + dsl.put("from", from); + dsl.put("size", size); + indexSearchParams.setDsl(dsl); + + List headers = discoveryService.directIndexSearch(indexSearchParams).getEntities(); + if (headers != null) { + ret.addAll(headers); + } else { + found = false; + } + + from += size; + + } while (found && ret.size() % size == 0); + + } finally { + RequestContext.get().endMetricRecord(recorder); + } + + return ret; + } + + private AtlasEntityHeader getServiceEntity(String serviceName) throws AtlasBaseException { + IndexSearchParams indexSearchParams = new IndexSearchParams(); + indexSearchParams.setExcludeClassifications(true); + + Set attributes = new HashSet<>(); + attributes.add(NAME); + attributes.add(ATTR_SERVICE_SERVICE_TYPE); + attributes.add(ATTR_SERVICE_TAG_SERVICE); + attributes.add(ATTR_SERVICE_ABAC_SERVICE); + attributes.add(ATTR_SERVICE_IS_ENABLED); + + Map dsl = getMap("size", 1); + + List> mustClauseList = new ArrayList<>(); + mustClauseList.add(getMap("term", getMap("__typeName.keyword", SERVICE_ENTITY_TYPE))); + mustClauseList.add(getMap("term", getMap("name.keyword", serviceName))); + mustClauseList.add(getMap("match", getMap("__state", Id.EntityState.ACTIVE))); + + dsl.put("query", getMap("bool", getMap("must", mustClauseList))); + + indexSearchParams.setDsl(dsl); + indexSearchParams.setAttributes(attributes); + + AtlasSearchResult searchResult = discoveryService.directIndexSearch(indexSearchParams); + + if (searchResult.getEntities() != null) { + return searchResult.getEntities().get(0); + } + + return null; + } + + private Map getMap(String key, Object value) { + Map map = new HashMap<>(); + map.put(key, value); + return map; + } + + private RangerPolicy getRangerPolicy(AtlasEntityHeader atlasPolicy, String serviceType) { + RangerPolicy policy = new RangerPolicy(); + + policy.setName((String) atlasPolicy.getAttribute(QUALIFIED_NAME)); + policy.setService((String) atlasPolicy.getAttribute(ATTR_POLICY_SERVICE_NAME)); + policy.setServiceType(serviceType); + policy.setGuid(atlasPolicy.getGuid()); + policy.setCreatedBy(atlasPolicy.getCreatedBy()); + policy.setCreateTime(atlasPolicy.getCreateTime()); + policy.setUpdatedBy(atlasPolicy.getUpdatedBy()); + policy.setUpdateTime(atlasPolicy.getUpdateTime()); + policy.setIsEnabled(getIsPolicyEnabled(atlasPolicy)); + policy.setPolicyResourceCategory(getPolicyResourceCategory(atlasPolicy)); + + policy.setConditions(getPolicyConditions(atlasPolicy)); + policy.setValiditySchedules(getPolicyValiditySchedule(atlasPolicy)); + + if (atlasPolicy.hasAttribute(ATTR_POLICY_PRIORITY)) { + policy.setPolicyPriority((Integer) atlasPolicy.getAttribute(ATTR_POLICY_PRIORITY)); + } + + if (POLICY_SERVICE_NAME_ABAC.equals(atlasPolicy.getAttribute(ATTR_POLICY_SERVICE_NAME))) { + String policyFilterCriteria = getPolicyFilterCriteria(atlasPolicy); + policy.setPolicyFilterCriteria(policyFilterCriteria); + } + + return policy; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/CacheTransformerTemplateHelper.java b/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/CacheTransformerTemplateHelper.java new file mode 100644 index 00000000000..075f0c7b575 --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/CacheTransformerTemplateHelper.java @@ -0,0 +1,49 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.policytransformer; + +import org.apache.atlas.exception.AtlasBaseException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +import static org.apache.atlas.repository.Constants.getStaticFileAsString; + +public class CacheTransformerTemplateHelper { + private static final Logger LOG = LoggerFactory.getLogger(CacheTransformerTemplateHelper.class); + + static final String RESOURCE_POLICY_TRANSFORMER = "templates/policy_cache_transformer_%s.json"; + + public static PolicyTransformerTemplate getTemplate(String fileSuffix) throws AtlasBaseException { + PolicyTransformerTemplate templates; + String jsonTemplate = null; + String fileName = String.format(RESOURCE_POLICY_TRANSFORMER, fileSuffix); + + try { + jsonTemplate = getStaticFileAsString(fileName); + } catch (IOException e) { + LOG.error("Failed to load template for policies: {}", RESOURCE_POLICY_TRANSFORMER); + throw new AtlasBaseException(e); + } + templates = new PolicyTransformerTemplate(); + templates.fromJsonString(jsonTemplate); + + return templates; + } +} diff --git a/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/PersonaCachePolicyTransformer.java b/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/PersonaCachePolicyTransformer.java new file mode 100644 index 00000000000..ef13f716b7d --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/PersonaCachePolicyTransformer.java @@ -0,0 +1,204 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.policytransformer; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.apache.atlas.RequestContext; +import org.apache.atlas.authorizer.JsonToElasticsearchQuery; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.instance.AtlasEntity; +import org.apache.atlas.model.instance.AtlasEntityHeader; +import org.apache.atlas.model.instance.AtlasStruct; +import org.apache.atlas.repository.store.graph.v2.EntityGraphRetriever; +import org.apache.atlas.utils.AtlasPerfMetrics; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +import static org.apache.atlas.policytransformer.CachePolicyTransformerImpl.ATTR_NAME; +import static org.apache.atlas.policytransformer.CachePolicyTransformerImpl.ATTR_POLICY_RESOURCES; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_ACTIONS; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_FILTER_CRITERIA; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_IS_ENABLED; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_RESOURCES_CATEGORY; +import static org.apache.atlas.repository.util.AccessControlUtils.POLICY_SERVICE_NAME_ABAC; +import static org.apache.atlas.repository.util.AccessControlUtils.POLICY_SUB_CATEGORY_DATA; +import static org.apache.atlas.repository.util.AccessControlUtils.POLICY_SUB_CATEGORY_METADATA; +import static org.apache.atlas.repository.util.AccessControlUtils.RESOURCES_ENTITY; +import static org.apache.atlas.repository.util.AccessControlUtils.RESOURCES_ENTITY_TYPE; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_CONDITIONS; +import static org.apache.atlas.repository.util.AccessControlUtils.POLICY_FILTER_CRITERIA_ENTITY; +import static org.apache.atlas.repository.util.AccessControlUtils.getEntityByQualifiedName; +import static org.apache.atlas.repository.util.AccessControlUtils.getFilteredPolicyResources; +import static org.apache.atlas.repository.util.AccessControlUtils.getIsPolicyEnabled; +import static org.apache.atlas.repository.util.AccessControlUtils.getPolicyActions; +import static org.apache.atlas.repository.util.AccessControlUtils.getPolicyConnectionQN; +import static org.apache.atlas.repository.util.AccessControlUtils.getPolicyFilterCriteria; +import static org.apache.atlas.repository.util.AccessControlUtils.getPolicyResources; +import static org.apache.atlas.repository.util.AccessControlUtils.getPolicyServiceName; +import static org.apache.atlas.repository.util.AccessControlUtils.getPolicySubCategory; + +public class PersonaCachePolicyTransformer extends AbstractCachePolicyTransformer { + private static final Logger LOG = LoggerFactory.getLogger(PersonaCachePolicyTransformer.class); + private static final ObjectMapper mapper = new ObjectMapper(); + + private final static String TEMPLATE_SUFFIX = "persona"; + + private EntityGraphRetriever entityRetriever = null; + private PolicyTransformerTemplate personaTemplate; + + public PersonaCachePolicyTransformer(EntityGraphRetriever entityRetriever) throws AtlasBaseException { + personaTemplate = getTemplate(TEMPLATE_SUFFIX); + this.entityRetriever = entityRetriever; + } + + public List transform(AtlasEntityHeader atlasPolicy) { + AtlasPerfMetrics.MetricRecorder recorder = RequestContext.get().startMetricRecord("PersonaCachePolicyTransformer.transform"); + List ret = new ArrayList<>(); + + List atlasActions = getPolicyActions(atlasPolicy); + List atlasResources = getPolicyResources(atlasPolicy); + List entityResources = getFilteredPolicyResources(atlasResources, RESOURCES_ENTITY); + List typeResources = getFilteredPolicyResources(atlasResources, RESOURCES_ENTITY_TYPE); + + String policyServiceName = getPolicyServiceName(atlasPolicy); + String policyFilterCriteria = getPolicyFilterCriteria(atlasPolicy); + + int index = 0; + for (String atlasAction : atlasActions) { + List currentTemplates = personaTemplate.getTemplate(personaTemplate.getTemplateKey(atlasAction, policyServiceName)); + + if (CollectionUtils.isEmpty(currentTemplates)) { + LOG.warn("PolicyTransformerImpl: Skipping unknown action {} while transforming policy {}", atlasAction, atlasPolicy.getGuid()); + continue; + } + + for (PolicyTransformerTemplate.TemplatePolicy templatePolicy : currentTemplates) { + AtlasEntityHeader header = new AtlasEntityHeader(atlasPolicy); + + header.setGuid(atlasPolicy.getGuid() + "-" + index++); + + header.setAttribute(ATTR_POLICY_ACTIONS, templatePolicy.getActions()); + header.setAttribute(ATTR_POLICY_RESOURCES_CATEGORY, templatePolicy.getPolicyResourceCategory()); + header.setAttribute(ATTR_POLICY_IS_ENABLED, getIsPolicyEnabled(atlasPolicy)); + header.setAttribute(ATTR_NAME, "transformed_policy_persona"); + + header.setAttribute(ATTR_POLICY_CONDITIONS, buildPolicyConditions(atlasPolicy, templatePolicy)); + + if (POLICY_SERVICE_NAME_ABAC.equals(policyServiceName)) { + String templateFilterCriteria = templatePolicy.getPolicyFilterCriteria(); + JsonNode entityCriteria = JsonToElasticsearchQuery.parseFilterJSON(policyFilterCriteria, POLICY_FILTER_CRITERIA_ENTITY); + if (entityCriteria != null && StringUtils.isNotEmpty(templateFilterCriteria)) { + templateFilterCriteria = templateFilterCriteria.replace(PLACEHOLDER_FILTER_CRITERIA, policyFilterCriteria); + templateFilterCriteria = templateFilterCriteria.replace(PLACEHOLDER_FILTER_ENTITY_CRITERIA, entityCriteria.toString()); + header.setAttribute(ATTR_POLICY_FILTER_CRITERIA, templateFilterCriteria); + header.setAttribute(ATTR_POLICY_RESOURCES, new ArrayList<>(0)); + } + } else { + String subCategory = getPolicySubCategory(atlasPolicy); + + List finalResources = new ArrayList<>(); + + for (String templateResource : templatePolicy.getResources()) { + if (templateResource.contains(PLACEHOLDER_ENTITY)) { + for (String entityResource : entityResources) { + finalResources.add(templateResource.replace(PLACEHOLDER_ENTITY, entityResource)); + } + + } else if (templateResource.contains(PLACEHOLDER_ENTITY_TYPE)) { + + if (CollectionUtils.isNotEmpty(typeResources)) { + typeResources.forEach(x -> finalResources.add(templateResource.replace(PLACEHOLDER_ENTITY_TYPE, x))); + } else { + boolean isConnection = false; + + if (POLICY_SUB_CATEGORY_METADATA.equals(subCategory) || POLICY_SUB_CATEGORY_DATA.equals(subCategory)) { + isConnection = isConnectionPolicy(entityResources, atlasPolicy); + } + + if (isConnection) { + finalResources.add(templateResource.replace(PLACEHOLDER_ENTITY_TYPE, "*")); + } else { + finalResources.add(templateResource.replace(PLACEHOLDER_ENTITY_TYPE, "Process")); + finalResources.add(templateResource.replace(PLACEHOLDER_ENTITY_TYPE, "Catalog")); + } + } + } else { + finalResources.add(templateResource); + } + } + header.setAttribute(ATTR_POLICY_RESOURCES, finalResources); + } + ret.add(header); + } + } + + RequestContext.get().endMetricRecord(recorder); + return ret; + } + + private boolean isConnectionPolicy(List assets, AtlasEntityHeader atlasPolicy) { + + if (assets.size() == 1) { + String connQNAttr = getPolicyConnectionQN(atlasPolicy); + + if (StringUtils.isNotEmpty(connQNAttr)) { + return connQNAttr.equals(assets.get(0)); + } else { + AtlasEntity connection; + try { + connection = getEntityByQualifiedName(entityRetriever, assets.get(0)); + } catch (AtlasBaseException abe) { + return false; + } + return connection != null; + } + } + + return false; + } + + private List buildPolicyConditions(AtlasEntityHeader atlasPolicy, PolicyTransformerTemplate.TemplatePolicy templatePolicy) { + List combinedConditions = new ArrayList<>(); + + try { + List atlasConditions = (List) atlasPolicy.getAttribute(ATTR_POLICY_CONDITIONS); + if (CollectionUtils.isNotEmpty(atlasConditions)) { + combinedConditions.addAll(atlasConditions); + } + + List templateConditions = templatePolicy.getPolicyConditions(); + if (CollectionUtils.isNotEmpty(templateConditions)) { + combinedConditions.addAll(templateConditions); + } + + } catch (Exception e) { + LOG.warn("Error processing policy conditions: {}", e.getMessage()); + LOG.warn("Exception while processing policy conditions", e); + } + + return combinedConditions; + } +} \ No newline at end of file diff --git a/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/PolicyTransformerTemplate.java b/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/PolicyTransformerTemplate.java new file mode 100644 index 00000000000..778e800cfaf --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/PolicyTransformerTemplate.java @@ -0,0 +1,158 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.policytransformer; + +import org.apache.atlas.model.instance.AtlasStruct; +import org.apache.atlas.type.AtlasType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.apache.atlas.repository.util.AccessControlUtils.POLICY_SERVICE_NAME_ABAC; + +public class PolicyTransformerTemplate { + private static final Logger LOG = LoggerFactory.getLogger(PolicyTransformerTemplate.class); + private static final String ABAC_TEMPLATE_KEY_SUFFIX = "abac"; + + private Map> actionToPoliciesMap = new HashMap<>(); + + public PolicyTransformerTemplate() { + } + + public List getTemplate(String action) { + return actionToPoliciesMap.get(action); + } + + public Set getTemplateActions() { + return new HashSet<>(actionToPoliciesMap.keySet()); + } + + public String getTemplateKey(String action, String service) { + if (POLICY_SERVICE_NAME_ABAC.equals(service)) { + return action + "-" + ABAC_TEMPLATE_KEY_SUFFIX; + } + return action; + } + + public void fromJsonString(String json) { + + Map> templates = AtlasType.fromJson(json, Map.class); + + for (String customAction : templates.keySet()) { + List templatePolicies = templates.get(customAction); + List policies = new ArrayList<>(); + + for (Map policy: templatePolicies) { + TemplatePolicy templatePolicy = new TemplatePolicy(); + + templatePolicy.setActions((List) policy.get("actions")); + templatePolicy.setResources((List) policy.get("resources")); + templatePolicy.setPolicyType((String) policy.get("policyType")); + templatePolicy.setPolicyResourceCategory((String) policy.get("policyResourceCategory")); + templatePolicy.setPolicyServiceName((String) policy.get("policyServiceName")); + templatePolicy.setPolicyConditions((List) policy.get("policyConditions")); + + Object filterCriteria = policy.get("policyFilterCriteria"); + if (filterCriteria != null) { + templatePolicy.setPolicyFilterCriteria((String) filterCriteria); + } + + policies.add(templatePolicy); + } + + this.actionToPoliciesMap.put(customAction, policies); + } + } + + class TemplatePolicy { + private String policyServiceName; + private String policyType; + private List resources; + private List actions; + private String policyResourceCategory; + private List policyConditions = new ArrayList<>(); + private String policyFilterCriteria; + + public String getPolicyServiceName() { + return policyServiceName; + } + + public void setPolicyServiceName(String policyServiceName) { + this.policyServiceName = policyServiceName; + } + + public String getPolicyType() { + return policyType; + } + + public void setPolicyType(String policyType) { + this.policyType = policyType; + } + + public String getPolicyResourceCategory() { + return policyResourceCategory; + } + + public void setPolicyResourceCategory(String category) { + this.policyResourceCategory = category; + } + + public List getResources() { + return resources; + } + + public void setResources(List resources) { + this.resources = resources; + } + + public List getActions() { + return actions; + } + + public void setActions(List actions) { + this.actions = actions; + } + + public List getPolicyConditions() { + return policyConditions; + } + + public void setPolicyConditions(List policyConditions) { + if (policyConditions != null) { + for (Map condition: policyConditions) { + this.policyConditions.add(new AtlasStruct(condition)); + } + } + } + + public String getPolicyFilterCriteria() { + return policyFilterCriteria; + } + + public void setPolicyFilterCriteria(String policyFilterCriteria) { + this.policyFilterCriteria = policyFilterCriteria; + } + } +} \ No newline at end of file diff --git a/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/PurposeCachePolicyTransformer.java b/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/PurposeCachePolicyTransformer.java new file mode 100644 index 00000000000..943a0d3220c --- /dev/null +++ b/auth-agents-common/src/main/java/org/apache/atlas/policytransformer/PurposeCachePolicyTransformer.java @@ -0,0 +1,121 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.policytransformer; + +import org.apache.atlas.RequestContext; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.instance.AtlasEntityHeader; +import org.apache.atlas.repository.store.graph.v2.EntityGraphRetriever; +import org.apache.atlas.utils.AtlasPerfMetrics; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import static org.apache.atlas.policytransformer.CachePolicyTransformerImpl.ATTR_POLICY_RESOURCES; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_ACTIONS; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_IS_ENABLED; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_RESOURCES_CATEGORY; +import static org.apache.atlas.repository.util.AccessControlUtils.ATTR_POLICY_SERVICE_NAME; +import static org.apache.atlas.repository.util.AccessControlUtils.RESOURCES_TAG; +import static org.apache.atlas.repository.util.AccessControlUtils.getFilteredPolicyResources; +import static org.apache.atlas.repository.util.AccessControlUtils.getIsPolicyEnabled; +import static org.apache.atlas.repository.util.AccessControlUtils.getPolicyActions; +import static org.apache.atlas.repository.util.AccessControlUtils.getPolicyResources; + +public class PurposeCachePolicyTransformer extends AbstractCachePolicyTransformer { + private static final Logger LOG = LoggerFactory.getLogger(PurposeCachePolicyTransformer.class); + + private final static String TEMPLATE_SUFFIX = "purpose"; + + private EntityGraphRetriever entityRetriever = null; + private PolicyTransformerTemplate purposeTemplate; + + public PurposeCachePolicyTransformer(EntityGraphRetriever entityRetriever) throws AtlasBaseException { + purposeTemplate = getTemplate(TEMPLATE_SUFFIX); + this.entityRetriever = entityRetriever; + } + + public List transform(AtlasEntityHeader atlasPolicy) { + AtlasPerfMetrics.MetricRecorder recorder = RequestContext.get().startMetricRecord("PurposeCachePolicyTransformer.transform"); + List ret = new ArrayList<>(); + + List atlasActions = getPolicyActions(atlasPolicy); + List atlasResources = getPolicyResources(atlasPolicy); + List tags = getFilteredPolicyResources(atlasResources, RESOURCES_TAG); + + int index = 0; + Set templateActions = purposeTemplate.getTemplateActions(); + List transformableActions = (List) CollectionUtils.intersection(atlasActions, templateActions); + + + for (String atlasAction : transformableActions) { + List currentTemplates = purposeTemplate.getTemplate(atlasAction); + + if (CollectionUtils.isEmpty(currentTemplates)) { + LOG.warn("PurposeCachePolicyTransformer: Skipping unknown action {} while transforming policy {}", atlasAction, atlasPolicy.getGuid()); + continue; + } + + for (PolicyTransformerTemplate.TemplatePolicy templatePolicy : currentTemplates) { + AtlasEntityHeader header = new AtlasEntityHeader(atlasPolicy); + + header.setGuid(atlasPolicy.getGuid() + "-" + index++); + + header.setAttribute(ATTR_POLICY_ACTIONS, templatePolicy.getActions()); + header.setAttribute(ATTR_POLICY_RESOURCES_CATEGORY, templatePolicy.getPolicyResourceCategory()); + header.setAttribute(ATTR_POLICY_IS_ENABLED, getIsPolicyEnabled(atlasPolicy)); + + if (StringUtils.isNotEmpty(templatePolicy.getPolicyServiceName())) { + header.setAttribute(ATTR_POLICY_SERVICE_NAME, templatePolicy.getPolicyServiceName()); + } + + List finalResources = new ArrayList<>(); + + for (String templateResource : templatePolicy.getResources()) { + if (templateResource.contains(PLACEHOLDER_TAG)) { + tags.forEach(tag -> finalResources.add(templateResource.replace(PLACEHOLDER_TAG, tag))); + } else { + finalResources.add(templateResource); + } + } + header.setAttribute(ATTR_POLICY_RESOURCES, finalResources); + + ret.add(header); + } + } + + //prepare a policy for all non-transformable actions + //this will help to reduce number of overall transformed policies + List nonTransformableActions = (List) CollectionUtils.subtract(atlasActions, templateActions); + + if (CollectionUtils.isNotEmpty(nonTransformableActions)) { + AtlasEntityHeader header = new AtlasEntityHeader(atlasPolicy); + header.setGuid(atlasPolicy.getGuid() + "-" + index); + header.setAttribute(ATTR_POLICY_ACTIONS, nonTransformableActions); + ret.add(header); + } + + RequestContext.get().endMetricRecord(recorder); + return ret; + } +} diff --git a/auth-audits/pom.xml b/auth-audits/pom.xml new file mode 100644 index 00000000000..baf8c28a9bf --- /dev/null +++ b/auth-audits/pom.xml @@ -0,0 +1,97 @@ + + + + + apache-atlas + org.apache.atlas + 3.0.0-SNAPSHOT + + 4.0.0 + + auth-audits + + + 17 + 17 + + + + + org.elasticsearch.client + elasticsearch-rest-high-level-client + ${elasticsearch.version} + + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.databind.version} + + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + + org.apache.commons + commons-lang3 + 3.4 + + + + ch.qos.logback + logback-classic + + + + ch.qos.logback + logback-core + + + + + io.opentelemetry + opentelemetry-sdk + 1.42.0 + + + io.opentelemetry + opentelemetry-exporter-otlp + 1.42.0 + + + + io.opentelemetry.semconv + opentelemetry-semconv + 1.27.0-alpha + + + + io.opentelemetry.instrumentation + opentelemetry-logback-appender-1.0 + 2.10.0-alpha + + + + + \ No newline at end of file diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/destination/AuditDestination.java b/auth-audits/src/main/java/org/apache/atlas/audit/destination/AuditDestination.java new file mode 100644 index 00000000000..d0b2b7d2a94 --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/destination/AuditDestination.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.destination; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.audit.provider.BaseAuditHandler; + +import java.util.Properties; + +/** + * This class needs to be extended by anyone who wants to build custom + * destination + */ +public abstract class AuditDestination extends BaseAuditHandler { + private static final Log logger = LogFactory.getLog(AuditDestination.class); + + public AuditDestination() { + logger.info("AuditDestination() enter"); + } + + /* + * (non-Javadoc) + * + * @see + * org.apache.ranger.audit.provider.AuditProvider#init(java.util.Properties, + * java.lang.String) + */ + @Override + public void init(Properties prop, String basePropertyName) { + super.init(prop, basePropertyName); + } + + /* + * (non-Javadoc) + * + * @see org.apache.ranger.audit.provider.AuditProvider#flush() + */ + @Override + public void flush() { + + } + + @Override + public void start() { + + } + + @Override + public void stop() { + + } + + @Override + public void waitToComplete() { + + } + + @Override + public void waitToComplete(long timeout) { + + } + +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/destination/ElasticSearchAuditDestination.java b/auth-audits/src/main/java/org/apache/atlas/audit/destination/ElasticSearchAuditDestination.java new file mode 100644 index 00000000000..d28464ed83c --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/destination/ElasticSearchAuditDestination.java @@ -0,0 +1,291 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.destination; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.HttpHost; +import org.apache.http.client.CredentialsProvider; +import org.apache.atlas.audit.model.AuditEventBase; +import org.apache.atlas.audit.model.AuthzAuditEvent; +import org.apache.atlas.audit.provider.MiscUtil; +import org.apache.atlas.audit.utils.CredentialsProviderUtil; +import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; +import org.elasticsearch.action.bulk.BulkItemResponse; +import org.elasticsearch.action.bulk.BulkRequest; +import org.elasticsearch.action.bulk.BulkResponse; +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.client.RequestOptions; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.client.RestHighLevelClient; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +public class ElasticSearchAuditDestination extends AuditDestination { + private static final Log LOG = LogFactory.getLog(ElasticSearchAuditDestination.class); + + public static final String CONFIG_URLS = "urls"; + public static final String CONFIG_PORT = "port"; + public static final String CONFIG_USER = "user"; + public static final String CONFIG_PWRD = "password"; + public static final String CONFIG_PROTOCOL = "protocol"; + public static final String CONFIG_INDEX = "index"; + public static final String CONFIG_PREFIX = "ranger.audit.elasticsearch"; + public static final String DEFAULT_INDEX = "ranger-audit"; + + private String index = "index"; + private volatile RestHighLevelClient client = null; + private String protocol; + private String user; + private int port; + private String password; + private String hosts; + + public ElasticSearchAuditDestination() { + propPrefix = CONFIG_PREFIX; + } + + + @Override + public void init(Properties props, String propPrefix) { + super.init(props, propPrefix); + this.protocol = getStringProperty(props, propPrefix + "." + CONFIG_PROTOCOL, "http"); + this.user = getStringProperty(props, propPrefix + "." + CONFIG_USER, ""); + this.password = getStringProperty(props, propPrefix + "." + CONFIG_PWRD, ""); + this.port = MiscUtil.getIntProperty(props, propPrefix + "." + CONFIG_PORT, 9200); + this.index = getStringProperty(props, propPrefix + "." + CONFIG_INDEX, DEFAULT_INDEX); + this.hosts = getHosts(); + LOG.info("Connecting to ElasticSearch: " + connectionString()); + getClient(); // Initialize client + } + + private String connectionString() { + return String.format(Locale.ROOT, "User:%s, %s://%s:%s/%s", user, protocol, hosts, port, index); + } + + @Override + public void stop() { + super.stop(); + logStatus(); + } + + @Override + public boolean log(Collection events) { + boolean ret = false; + try { + logStatusIfRequired(); + addTotalCount(events.size()); + + RestHighLevelClient client = getClient(); + if (null == client) { + // ElasticSearch is still not initialized. So need return error + addDeferredCount(events.size()); + return ret; + } + + ArrayList eventList = new ArrayList<>(events); + BulkRequest bulkRequest = new BulkRequest(); + try { + for (AuditEventBase event : eventList) { + AuthzAuditEvent authzEvent = (AuthzAuditEvent) event; + String id = authzEvent.getEventId(); + Map doc = toDoc(authzEvent); + bulkRequest.add(new IndexRequest(index).id(id).source(doc)); + } + } catch (Exception ex) { + addFailedCount(eventList.size()); + logFailedEvent(eventList, ex); + } + BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT); + if (response.status().getStatus() >= 400) { + addFailedCount(eventList.size()); + logFailedEvent(eventList, "HTTP " + response.status().getStatus()); + } else { + BulkItemResponse[] items = response.getItems(); + for (int i = 0; i < items.length; i++) { + AuditEventBase itemRequest = eventList.get(i); + BulkItemResponse itemResponse = items[i]; + if (itemResponse.isFailed()) { + addFailedCount(1); + logFailedEvent(Arrays.asList(itemRequest), itemResponse.getFailureMessage()); + } else { + if(LOG.isDebugEnabled()) { + LOG.debug(String.format("Indexed %s", itemRequest.getEventKey())); + } + addSuccessCount(1); + ret = true; + } + } + } + } catch (Throwable t) { + addDeferredCount(events.size()); + logError("Error sending message to ElasticSearch", t); + } + return ret; + } + + /* + * (non-Javadoc) + * + * @see org.apache.ranger.audit.provider.AuditProvider#flush() + */ + @Override + public void flush() { + + } + + public boolean isAsync() { + return true; + } + + synchronized RestHighLevelClient getClient() { + if (client == null) { + synchronized (ElasticSearchAuditDestination.class) { + if (client == null) { + client = newClient(); + } + } + } + return client; + } + + private final AtomicLong lastLoggedAt = new AtomicLong(0); + + public static RestClientBuilder getRestClientBuilder(String urls, String protocol, String user, String password, int port) { + RestClientBuilder restClientBuilder = RestClient.builder( + MiscUtil.toArray(urls, ",").stream() + .map(x -> new HttpHost(x, port, protocol)) + .toArray(i -> new HttpHost[i]) + ); + if (StringUtils.isNotBlank(user) && StringUtils.isNotBlank(password) && !user.equalsIgnoreCase("NONE") && !password.equalsIgnoreCase("NONE")) { + + final CredentialsProvider credentialsProvider = + CredentialsProviderUtil.getBasicCredentials(user, password); + restClientBuilder.setHttpClientConfigCallback(clientBuilder -> + clientBuilder.setDefaultCredentialsProvider(credentialsProvider)); + + } else { + LOG.error("ElasticSearch Credentials not provided!!"); + final CredentialsProvider credentialsProvider = null; + restClientBuilder.setHttpClientConfigCallback(clientBuilder -> + clientBuilder.setDefaultCredentialsProvider(credentialsProvider)); + } + return restClientBuilder; + } + + private RestHighLevelClient newClient() { + try { + RestClientBuilder restClientBuilder = + getRestClientBuilder(hosts, protocol, user, password, port); + RestHighLevelClient restHighLevelClient = new RestHighLevelClient(restClientBuilder); + if (LOG.isDebugEnabled()) { + LOG.debug("Initialized client"); + } + boolean exits = false; + try { + exits = restHighLevelClient.indices().open(new OpenIndexRequest(this.index), RequestOptions.DEFAULT).isShardsAcknowledged(); + } catch (Exception e) { + LOG.warn("Error validating index " + this.index); + } + if(exits) { + if (LOG.isDebugEnabled()) { + LOG.debug("Index exists"); + } + } else { + LOG.info("Index does not exist"); + } + return restHighLevelClient; + } catch (Throwable t) { + lastLoggedAt.updateAndGet(lastLoggedAt -> { + long now = System.currentTimeMillis(); + long elapsed = now - lastLoggedAt; + if (elapsed > TimeUnit.MINUTES.toMillis(1)) { + LOG.fatal("Can't connect to ElasticSearch server: " + connectionString(), t); + return now; + } else { + return lastLoggedAt; + } + }); + return null; + } + } + + private String getHosts() { + String urls = MiscUtil.getStringProperty(props, propPrefix + "." + CONFIG_URLS); + if (urls != null) { + urls = urls.trim(); + } + if ("NONE".equalsIgnoreCase(urls)) { + urls = null; + } + return urls; + } + + private String getStringProperty(Properties props, String propName, String defaultValue) { + String value = MiscUtil.getStringProperty(props, propName); + if (null == value) { + return defaultValue; + } + return value; + } + + Map toDoc(AuthzAuditEvent auditEvent) { + Map doc = new HashMap(); + doc.put("id", auditEvent.getEventId()); + doc.put("access", auditEvent.getAccessType()); + doc.put("enforcer", auditEvent.getAclEnforcer()); + doc.put("agent", auditEvent.getAgentId()); + doc.put("repo", auditEvent.getRepositoryName()); + doc.put("sess", auditEvent.getSessionId()); + doc.put("reqUser", auditEvent.getUser()); + doc.put("reqEntityGuid", auditEvent.getEntityGuid()); + doc.put("reqData", auditEvent.getRequestData()); + doc.put("resource", auditEvent.getResourcePath()); + doc.put("cliIP", auditEvent.getClientIP()); + doc.put("logType", auditEvent.getLogType()); + doc.put("result", auditEvent.getAccessResult()); + doc.put("policyId", auditEvent.getPolicyId()); + doc.put("repoType", auditEvent.getRepositoryType()); + doc.put("resType", auditEvent.getResourceType()); + doc.put("reason", auditEvent.getResultReason()); + doc.put("action", auditEvent.getAction()); + doc.put("evtTime", auditEvent.getEventTime()); + doc.put("seq_num", auditEvent.getSeqNum()); + doc.put("event_count", auditEvent.getEventCount()); + doc.put("event_dur_ms", auditEvent.getEventDurationMS()); + doc.put("tags", auditEvent.getTags()); + doc.put("cluster", auditEvent.getClusterName()); + doc.put("zoneName", auditEvent.getZoneName()); + doc.put("agentHost", auditEvent.getAgentHostname()); + doc.put("policyVersion", auditEvent.getPolicyVersion()); + return doc; + } + +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/destination/Log4JAuditDestination.java b/auth-audits/src/main/java/org/apache/atlas/audit/destination/Log4JAuditDestination.java new file mode 100644 index 00000000000..a0af313788e --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/destination/Log4JAuditDestination.java @@ -0,0 +1,167 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.destination; + +import org.apache.atlas.audit.model.AuditEventBase; +import org.apache.atlas.audit.model.AuthzAuditEvent; +import org.apache.atlas.audit.provider.MiscUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import java.util.Collection; +import java.util.Properties; + +public class Log4JAuditDestination extends AuditDestination { + private static final Logger logger = LoggerFactory + .getLogger(Log4JAuditDestination.class); + + private static Logger auditLogger = null; + + public static final String PROP_LOG4J_LOGGER = "logger"; + public static final String DEFAULT_LOGGER_PREFIX = "ranger.audit"; + private String loggerName = null; + private static final String AUTH_AUDIT_USER = "reqUser"; + private static final String AUTH_AUDIT_ACTION = "action"; + private static final String AUTH_AUDIT_ENTITY_GUID = "entityGuid"; + private static final String AUTH_AUDIT_POLICY_ID = "policyId"; + private static final String AUTH_AUDIT_RESULT = "result"; + private static final String AUTH_AUDIT_RESOURCE= "resource"; + private static final String AUTH_AUDIT_CLIENT_IP = "cliIP"; + private static final String AUTH_AUDIT_AGENT = "agent"; + + + public Log4JAuditDestination() { + logger.info("Log4JAuditDestination() called."); + + } + + @Override + public void init(Properties prop, String propPrefix) { + super.init(prop, propPrefix); + loggerName = MiscUtil.getStringProperty(props, propPrefix + "." + + PROP_LOG4J_LOGGER); + if (loggerName == null || loggerName.isEmpty()) { + loggerName = DEFAULT_LOGGER_PREFIX + "." + getName(); + logger.info("Logger property " + propPrefix + "." + + PROP_LOG4J_LOGGER + " was not set. Constructing default=" + + loggerName); + } + logger.info("Logger name for " + getName() + " is " + loggerName); + auditLogger = LoggerFactory.getLogger(loggerName); + logger.info("Done initializing logger for audit. name=" + getName() + + ", loggerName=" + loggerName); + } + + + @Override + public void stop() { + super.stop(); + logStatus(); + } + + @Override + public boolean log(AuditEventBase event) { + if (!auditLogger.isInfoEnabled()) { + logStatusIfRequired(); + addTotalCount(1); + return true; + } + + if (event != null) { + recordLogAttributes(event); + String eventStr = MiscUtil.stringify(event); + logJSON(eventStr); + clearLogAttributes(event); + } + return true; + } + + private void recordLogAttributes(AuditEventBase eventBase) { + if (eventBase instanceof AuthzAuditEvent) { + AuthzAuditEvent event = (AuthzAuditEvent) eventBase; + MDC.put(AUTH_AUDIT_USER, event.getUser()); + MDC.put(AUTH_AUDIT_ACTION, event.getAction()); + MDC.put(AUTH_AUDIT_ENTITY_GUID, event.getEntityGuid()); + MDC.put(AUTH_AUDIT_POLICY_ID, event.getPolicyId()); + MDC.put(AUTH_AUDIT_RESOURCE, event.getResourcePath()); + MDC.put(AUTH_AUDIT_RESULT, String.valueOf(event.getAccessResult())); + MDC.put(AUTH_AUDIT_CLIENT_IP, event.getClientIP()); + MDC.put(AUTH_AUDIT_AGENT, event.getAgentId()); + } + } + + private void clearLogAttributes(AuditEventBase event) { + if (event instanceof AuthzAuditEvent) { + MDC.remove(AUTH_AUDIT_USER); + MDC.remove(AUTH_AUDIT_ACTION); + MDC.remove(AUTH_AUDIT_ENTITY_GUID); + MDC.remove(AUTH_AUDIT_POLICY_ID); + MDC.remove(AUTH_AUDIT_RESOURCE); + MDC.remove(AUTH_AUDIT_RESULT); + MDC.remove(AUTH_AUDIT_CLIENT_IP); + MDC.remove(AUTH_AUDIT_AGENT); + } + } + + @Override + public boolean log(Collection events) { + if (!auditLogger.isInfoEnabled()) { + logStatusIfRequired(); + addTotalCount(events.size()); + return true; + } + + for (AuditEventBase event : events) { + log(event); + } + return true; + } + + @Override + public boolean logJSON(String event) { + logStatusIfRequired(); + addTotalCount(1); + if (!auditLogger.isInfoEnabled()) { + return true; + } + + if (event != null) { + auditLogger.info(event); + addSuccessCount(1); + } + return true; + } + + @Override + public boolean logJSON(Collection events) { + if (!auditLogger.isInfoEnabled()) { + logStatusIfRequired(); + addTotalCount(events.size()); + return true; + } + + for (String event : events) { + logJSON(event); + } + return false; + } + +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/model/AuditEventBase.java b/auth-audits/src/main/java/org/apache/atlas/audit/model/AuditEventBase.java new file mode 100644 index 00000000000..2d9fa2f9460 --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/model/AuditEventBase.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.model; + +import java.util.Date; + +public abstract class AuditEventBase { + + protected AuditEventBase() { + } + + public abstract String getEventKey(); + public abstract Date getEventTime (); + public abstract void setEventCount(long eventCount); + public abstract void setEventDurationMS(long eventDurationMS); +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/model/AuthzAuditEvent.java b/auth-audits/src/main/java/org/apache/atlas/audit/model/AuthzAuditEvent.java new file mode 100644 index 00000000000..b0eda51b9af --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/model/AuthzAuditEvent.java @@ -0,0 +1,585 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.commons.lang3.StringUtils; + +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +public class AuthzAuditEvent extends AuditEventBase { + protected static String FIELD_SEPARATOR = ";"; + + protected static final int MAX_ACTION_FIELD_SIZE = 1800; + protected static final int MAX_REQUEST_DATA_FIELD_SIZE = 1800; + + @JsonProperty("repoType") + protected int repositoryType = 0; + + @JsonProperty("repo") + protected String repositoryName = null; + + @JsonProperty("reqUser") + protected String user = null; + + @JsonProperty("reqEntityGuid") + protected String entityGuid = null; + + @JsonProperty("evtTime") + protected Date eventTime = new Date(); + + @JsonProperty("access") + protected String accessType = null; + + @JsonProperty("resource") + protected String resourcePath = null; + + @JsonProperty("resType") + protected String resourceType = null; + + @JsonProperty("action") + protected String action = null; + + @JsonProperty("result") + protected short accessResult = 0; // 0 - DENIED; 1 - ALLOWED; HTTP return + // code + + @JsonProperty("agent") + protected String agentId = null; + + @JsonProperty("policyId") + protected String policyId = "-1"; + + @JsonProperty("reason") + protected String resultReason = null; + + @JsonProperty("enforcer") + protected String aclEnforcer = null; + + @JsonProperty("sess") + protected String sessionId = null; + + @JsonProperty("cliType") + protected String clientType = null; + + @JsonProperty("cliIP") + protected String clientIP = null; + + @JsonProperty("reqData") + protected String requestData = null; + + @JsonProperty("agentHost") + protected String agentHostname = null; + + @JsonProperty("logType") + protected String logType = null; + + @JsonProperty("id") + protected String eventId = null; + + /** + * This to ensure order within a session. Order not guaranteed across + * processes and hosts + */ + @JsonProperty("seq_num") + protected long seqNum = 0; + + @JsonProperty("event_count") + protected long eventCount = 1; + + @JsonProperty("event_dur_ms") + protected long eventDurationMS = 0; + + @JsonProperty("tags") + protected Set tags = new HashSet<>(); + + @JsonProperty("additional_info") + protected String additionalInfo; + + @JsonProperty("cluster_name") + protected String clusterName; + + @JsonProperty("zone_name") + protected String zoneName; + + @JsonProperty("policy_version") + protected Long policyVersion; + + public AuthzAuditEvent() { + super(); + + this.repositoryType = 0; + } + + public AuthzAuditEvent(int repositoryType, String repositoryName, + String user, Date eventTime, String accessType, + String resourcePath, String resourceType, String action, + short accessResult, String agentId, String policyId, + String resultReason, String aclEnforcer, String sessionId, + String clientType, String clientIP, String requestData, String clusterName) { + this(repositoryType, repositoryName, user, eventTime, accessType, resourcePath, resourceType, action, accessResult, agentId, + policyId, resultReason, aclEnforcer, sessionId, clientType, clientIP, requestData, clusterName, null); + } + + public AuthzAuditEvent(int repositoryType, String repositoryName, + String user, Date eventTime, String accessType, + String resourcePath, String resourceType, String action, + short accessResult, String agentId, String policyId, + String resultReason, String aclEnforcer, String sessionId, + String clientType, String clientIP, String requestData, String clusterName, String zoneName) { + this(repositoryType, repositoryName, user, eventTime, accessType, resourcePath, resourceType, action, accessResult, agentId, + policyId, resultReason, aclEnforcer, sessionId, clientType, clientIP, requestData, clusterName, zoneName, null); + + } + + public AuthzAuditEvent(int repositoryType, String repositoryName, + String user, Date eventTime, String accessType, + String resourcePath, String resourceType, String action, + short accessResult, String agentId, String policyId, + String resultReason, String aclEnforcer, String sessionId, + String clientType, String clientIP, String requestData, String clusterName, String zoneName, Long policyVersion) { + this.repositoryType = repositoryType; + this.repositoryName = repositoryName; + this.user = user; + this.eventTime = eventTime; + this.accessType = accessType; + this.resourcePath = resourcePath; + this.resourceType = resourceType; + this.action = action; + this.accessResult = accessResult; + this.agentId = agentId; + this.policyId = policyId; + this.resultReason = resultReason; + this.aclEnforcer = aclEnforcer; + this.sessionId = sessionId; + this.clientType = clientType; + this.clientIP = clientIP; + this.requestData = requestData; + this.clusterName = clusterName; + this.zoneName = zoneName; + this.policyVersion = policyVersion; + } + + /** + * @return the repositoryType + */ + public int getRepositoryType() { + return repositoryType; + } + + /** + * @param repositoryType + * the repositoryType to set + */ + public void setRepositoryType(int repositoryType) { + this.repositoryType = repositoryType; + } + + /** + * @return the repositoryName + */ + public String getRepositoryName() { + return repositoryName; + } + + /** + * @param repositoryName + * the repositoryName to set + */ + public void setRepositoryName(String repositoryName) { + this.repositoryName = repositoryName; + } + + /** + * @return the user + */ + public String getUser() { + return user; + } + + /** + * @param user + * the user to set + */ + public void setUser(String user) { + this.user = user; + } + + public String getEntityGuid() { + return entityGuid; + } + + public void setEntityGuid(String entityGuid) { + this.entityGuid = entityGuid; + } + + /** + * @return the timeStamp + */ + public Date getEventTime() { + return eventTime; + } + + /** + * @param eventTime + * the eventTime to set + */ + public void setEventTime(Date eventTime) { + this.eventTime = eventTime; + } + + /** + * @return the accessType + */ + public String getAccessType() { + return accessType; + } + + /** + * @param accessType + * the accessType to set + */ + public void setAccessType(String accessType) { + this.accessType = accessType; + } + + /** + * @return the resourcePath + */ + public String getResourcePath() { + return resourcePath; + } + + /** + * @param resourcePath + * the resourcePath to set + */ + public void setResourcePath(String resourcePath) { + this.resourcePath = resourcePath; + } + + /** + * @return the resourceType + */ + public String getResourceType() { + return resourceType; + } + + /** + * @param resourceType + * the resourceType to set + */ + public void setResourceType(String resourceType) { + this.resourceType = resourceType; + } + + /** + * @return the action + */ + public String getAction() { return action; } + + /** + * @param action + * the action to set + */ + public void setAction(String action) { + this.action = action; + } + + /** + * @return the accessResult + */ + public short getAccessResult() { + return accessResult; + } + + /** + * @param accessResult + * the accessResult to set + */ + public void setAccessResult(short accessResult) { + this.accessResult = accessResult; + } + + /** + * @return the agentId + */ + public String getAgentId() { + return agentId; + } + + /** + * @param agentId + * the agentId to set + */ + public void setAgentId(String agentId) { + this.agentId = agentId; + } + + /** + * @return the policyId + */ + public String getPolicyId() { + return policyId; + } + + /** + * @param policyId + * the policyId to set + */ + public void setPolicyId(String policyId) { + this.policyId = policyId; + } + + /** + * @return the resultReason + */ + public String getResultReason() { + return resultReason; + } + + /** + * @param resultReason + * the resultReason to set + */ + public void setResultReason(String resultReason) { + this.resultReason = resultReason; + } + + /** + * @return the aclEnforcer + */ + public String getAclEnforcer() { + return aclEnforcer; + } + + /** + * @param aclEnforcer + * the aclEnforcer to set + */ + public void setAclEnforcer(String aclEnforcer) { + this.aclEnforcer = aclEnforcer; + } + + /** + * @return the sessionId + */ + public String getSessionId() { + return sessionId; + } + + /** + * @param sessionId + * the sessionId to set + */ + public void setSessionId(String sessionId) { + this.sessionId = sessionId; + } + + /** + * @return the clientType + */ + public String getClientType() { + return clientType; + } + + /** + * @param clientType + * the clientType to set + */ + public void setClientType(String clientType) { + this.clientType = clientType; + } + + /** + * @return the clientIP + */ + public String getClientIP() { + return clientIP; + } + + /** + * @param clientIP + * the clientIP to set + */ + public void setClientIP(String clientIP) { + this.clientIP = clientIP; + } + + /** + * @return the requestData + */ + public String getRequestData() { return requestData; } + + /** + * @param requestData + * the requestData to set + */ + public void setRequestData(String requestData) { + this.requestData = requestData; + } + + public String getAgentHostname() { + return agentHostname; + } + + public void setAgentHostname(String agentHostname) { + this.agentHostname = agentHostname; + } + + public String getLogType() { + return logType; + } + + public void setLogType(String logType) { + this.logType = logType; + } + + public String getEventId() { + return eventId; + } + + public void setEventId(String eventId) { + this.eventId = eventId; + } + + public long getSeqNum() { + return seqNum; + } + + public void setSeqNum(long seqNum) { + this.seqNum = seqNum; + } + + public long getEventCount() { + return eventCount; + } + + public void setEventCount(long frequencyCount) { + this.eventCount = frequencyCount; + } + + public long getEventDurationMS() { + return eventDurationMS; + } + + public Set getTags() { + return tags; + } + + public void setEventDurationMS(long frequencyDurationMS) { + this.eventDurationMS = frequencyDurationMS; + } + + public void setTags(Set tags) { + this.tags = tags; + } + + public String getClusterName() { + return clusterName; + } + + public void setZoneName(String zoneName) { + this.zoneName = zoneName; + } + + public String getZoneName() { + return zoneName; + } + + public void setPolicyVersion(Long policyVersion) { + this.policyVersion = policyVersion; + } + + public Long getPolicyVersion() { + return policyVersion; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public String getAdditionalInfo() { return this.additionalInfo; } + + public void setAdditionalInfo(String additionalInfo) { this.additionalInfo = additionalInfo; } + + @Override + public String getEventKey() { + String key = user + "^" + accessType + "^" + resourcePath + "^" + + resourceType + "^" + action + "^" + accessResult + "^" + + sessionId + "^" + clientIP; + return key; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append("AuthzAuditEvent{"); + toString(sb); + sb.append("}"); + + return sb.toString(); + } + + protected StringBuilder toString(StringBuilder sb) { + sb.append("repositoryType=").append(repositoryType) + .append(FIELD_SEPARATOR).append("repositoryName=") + .append(repositoryName).append(FIELD_SEPARATOR).append("user=") + .append(user).append(FIELD_SEPARATOR).append("eventTime=") + .append(eventTime).append(FIELD_SEPARATOR) + .append("accessType=").append(accessType) + .append(FIELD_SEPARATOR).append("resourcePath=") + .append(resourcePath).append(FIELD_SEPARATOR) + .append("resourceType=").append(resourceType) + .append(FIELD_SEPARATOR).append("action=").append(action) + .append(FIELD_SEPARATOR).append("accessResult=") + .append(accessResult).append(FIELD_SEPARATOR) + .append("agentId=").append(agentId).append(FIELD_SEPARATOR) + .append("policyId=").append(policyId).append(FIELD_SEPARATOR) + .append("resultReason=").append(resultReason) + .append(FIELD_SEPARATOR).append("aclEnforcer=") + .append(aclEnforcer).append(FIELD_SEPARATOR) + .append("sessionId=").append(sessionId).append(FIELD_SEPARATOR) + .append("clientType=").append(clientType) + .append(FIELD_SEPARATOR).append("clientIP=").append(clientIP) + .append(FIELD_SEPARATOR).append("requestData=") + .append(requestData).append(FIELD_SEPARATOR) + .append("agentHostname=").append(agentHostname) + .append(FIELD_SEPARATOR).append("logType=").append(logType) + .append(FIELD_SEPARATOR).append("eventId=").append(eventId) + .append(FIELD_SEPARATOR).append("seq_num=").append(seqNum) + .append(FIELD_SEPARATOR).append("event_count=") + .append(eventCount).append(FIELD_SEPARATOR) + .append("event_dur_ms=").append(eventDurationMS) + .append(FIELD_SEPARATOR) + .append("tags=").append("[") + .append(StringUtils.join(tags, ", ")) + .append("]") + .append(FIELD_SEPARATOR).append("clusterName=").append(clusterName) + .append(FIELD_SEPARATOR).append("zoneName=").append(zoneName) + .append(FIELD_SEPARATOR).append("policyVersion=").append(policyVersion) + .append(FIELD_SEPARATOR).append("additionalInfo=").append(additionalInfo); + + return sb; + } +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/provider/AsyncAuditProvider.java b/auth-audits/src/main/java/org/apache/atlas/audit/provider/AsyncAuditProvider.java new file mode 100644 index 00000000000..33fee12141d --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/provider/AsyncAuditProvider.java @@ -0,0 +1,289 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.provider; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.audit.model.AuditEventBase; + +import java.util.Properties; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +public class AsyncAuditProvider extends MultiDestAuditProvider implements + Runnable { + + private static final Log LOG = LogFactory.getLog(AsyncAuditProvider.class); + + private static int sThreadCount = 0; + + private BlockingQueue mQueue = null; + private Thread mThread = null; + private String mName = null; + private int mMaxQueueSize = 10 * 1024; + private int mMaxFlushInterval = 5000; // 5 seconds + + private static final int mStopLoopIntervalSecs = 1; // 1 second + private static final int mWaitToCompleteLoopIntervalSecs = 1; // 1 second + + // Summary of logs handled + private AtomicLong lifeTimeInLogCount = new AtomicLong(0); // Total count, including drop count + private AtomicLong lifeTimeOutLogCount = new AtomicLong(0); + private AtomicLong lifeTimeDropCount = new AtomicLong(0); + private AtomicLong intervalInLogCount = new AtomicLong(0); + private AtomicLong intervalOutLogCount = new AtomicLong(0); + private AtomicLong intervalDropCount = new AtomicLong(0); + private long lastIntervalLogTime = System.currentTimeMillis(); + private int intervalLogDurationMS = 60000; + private long lastFlushTime = System.currentTimeMillis(); + + public AsyncAuditProvider(String name, int maxQueueSize, int maxFlushInterval) { + LOG.info("AsyncAuditProvider(" + name + "): creating.."); + + if(maxQueueSize < 1) { + LOG.warn("AsyncAuditProvider(" + name + "): invalid maxQueueSize=" + maxQueueSize + ". will use default " + mMaxQueueSize); + + maxQueueSize = mMaxQueueSize; + } + + mName = name; + mMaxQueueSize = maxQueueSize; + mMaxFlushInterval = maxFlushInterval; + + mQueue = new ArrayBlockingQueue(mMaxQueueSize); + } + + public AsyncAuditProvider(String name, int maxQueueSize, int maxFlushInterval, AuditHandler provider) { + this(name, maxQueueSize, maxFlushInterval); + + addAuditProvider(provider); + } + + @Override + public void init(Properties props) { + LOG.info("AsyncAuditProvider(" + mName + ").init()"); + + super.init(props); + } + + public int getIntervalLogDurationMS() { + return intervalLogDurationMS; + } + + public void setIntervalLogDurationMS(int intervalLogDurationMS) { + this.intervalLogDurationMS = intervalLogDurationMS; + } + + @Override + public boolean log(AuditEventBase event) { + LOG.debug("AsyncAuditProvider.logEvent(AuditEventBase)"); + + queueEvent(event); + return true; + } + + @Override + public void start() { + mThread = new Thread(this, "AsyncAuditProvider" + (++sThreadCount)); + + mThread.setDaemon(true); + mThread.start(); + + super.start(); + } + + @Override + public void stop() { + LOG.info("==> AsyncAuditProvider.stop()"); + try { + LOG.info("Interrupting child thread of " + mName + "..." ); + mThread.interrupt(); + while (mThread.isAlive()) { + try { + LOG.info(String.format("Waiting for child thread of %s to exit. Sleeping for %d secs", mName, mStopLoopIntervalSecs)); + mThread.join(mStopLoopIntervalSecs * 1000); + } catch (InterruptedException e) { + LOG.warn("Interrupted while waiting for child thread to join! Proceeding with stop", e); + break; + } + } + + super.stop(); + } finally { + LOG.info("<== AsyncAuditProvider.stop()"); + } + } + + @Override + public void waitToComplete() { + waitToComplete(0); + + super.waitToComplete(); + } + + @Override + public void run() { + LOG.info("==> AsyncAuditProvider.run()"); + + while (true) { + AuditEventBase event = null; + try { + event = dequeueEvent(); + + if (event != null) { + super.log(event); + } else { + lastFlushTime = System.currentTimeMillis(); + flush(); + } + } catch (InterruptedException excp) { + LOG.info("AsyncAuditProvider.run - Interrupted! Breaking out of while loop."); + break; + } catch (Exception excp) { + logFailedEvent(event, excp); + } + } + + try { + lastFlushTime = System.currentTimeMillis(); + flush(); + } catch (Exception excp) { + LOG.error("AsyncAuditProvider.run()", excp); + } + + LOG.info("<== AsyncAuditProvider.run()"); + } + + private void queueEvent(AuditEventBase event) { + // Increase counts + lifeTimeInLogCount.incrementAndGet(); + intervalInLogCount.incrementAndGet(); + + if(! mQueue.offer(event)) { + lifeTimeDropCount.incrementAndGet(); + intervalDropCount.incrementAndGet(); + } + } + + private AuditEventBase dequeueEvent() throws InterruptedException { + AuditEventBase ret = mQueue.poll(); + + while(ret == null) { + logSummaryIfRequired(); + + if (mMaxFlushInterval > 0 ) { + long timeTillNextFlush = getTimeTillNextFlush(); + + if (timeTillNextFlush <= 0) { + break; // force flush + } + + ret = mQueue.poll(timeTillNextFlush, TimeUnit.MILLISECONDS); + } else { + // Let's wake up for summary logging + long waitTime = intervalLogDurationMS - (System.currentTimeMillis() - lastIntervalLogTime); + waitTime = waitTime <= 0 ? intervalLogDurationMS : waitTime; + + ret = mQueue.poll(waitTime, TimeUnit.MILLISECONDS); + } + } + + if(ret != null) { + lifeTimeOutLogCount.incrementAndGet(); + intervalOutLogCount.incrementAndGet(); + } + + logSummaryIfRequired(); + + return ret; + } + + private void logSummaryIfRequired() { + long intervalSinceLastLog = System.currentTimeMillis() - lastIntervalLogTime; + + if (intervalSinceLastLog > intervalLogDurationMS) { + if (intervalInLogCount.get() > 0 || intervalOutLogCount.get() > 0 ) { + long queueSize = mQueue.size(); + + LOG.info("AsyncAuditProvider-stats:" + mName + ": past " + formatIntervalForLog(intervalSinceLastLog) + + ": inLogs=" + intervalInLogCount.get() + + ", outLogs=" + intervalOutLogCount.get() + + ", dropped=" + intervalDropCount.get() + + ", currentQueueSize=" + queueSize); + + LOG.info("AsyncAuditProvider-stats:" + mName + ": process lifetime" + + ": inLogs=" + lifeTimeInLogCount.get() + + ", outLogs=" + lifeTimeOutLogCount.get() + + ", dropped=" + lifeTimeDropCount.get()); + } + + lastIntervalLogTime = System.currentTimeMillis(); + intervalInLogCount.set(0); + intervalOutLogCount.set(0); + intervalDropCount.set(0); + } + } + + private boolean isEmpty() { + return mQueue.isEmpty(); + } + + public void waitToComplete(long maxWaitSeconds) { + LOG.debug("==> AsyncAuditProvider.waitToComplete()"); + + try { + for (long waitTime = 0; !isEmpty() + && (maxWaitSeconds <= 0 || maxWaitSeconds > waitTime); waitTime += mWaitToCompleteLoopIntervalSecs) { + try { + LOG.info(String.format("%d messages yet to be flushed by %s. Sleeoping for %d sec", mQueue.size(), mName, mWaitToCompleteLoopIntervalSecs)); + Thread.sleep(mWaitToCompleteLoopIntervalSecs * 1000); + } catch (InterruptedException excp) { + // someone really wants service to exit, abandon unwritten audits and exit. + LOG.warn("Caught interrupted exception! " + mQueue.size() + " messages still unflushed! Won't wait for queue to flush, exiting...", excp); + break; + } + } + } finally { + LOG.debug("<== AsyncAuditProvider.waitToComplete()"); + } + } + + private long getTimeTillNextFlush() { + long timeTillNextFlush = mMaxFlushInterval; + + if (mMaxFlushInterval > 0) { + + if (lastFlushTime != 0) { + long timeSinceLastFlush = System.currentTimeMillis() + - lastFlushTime; + + if (timeSinceLastFlush >= mMaxFlushInterval) { + timeTillNextFlush = 0; + } else { + timeTillNextFlush = mMaxFlushInterval - timeSinceLastFlush; + } + } + } + + return timeTillNextFlush; + } +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/provider/AuditFileCacheProvider.java b/auth-audits/src/main/java/org/apache/atlas/audit/provider/AuditFileCacheProvider.java new file mode 100644 index 00000000000..3d6499d13c9 --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/provider/AuditFileCacheProvider.java @@ -0,0 +1,123 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.provider; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.audit.model.AuditEventBase; +import org.apache.atlas.audit.queue.AuditFileCacheProviderSpool; + +import java.util.Collection; +import java.util.Properties; + +/* + AuditFileCacheProvider class does the work of stashing the audit logs into Local Filesystem before sending it to the AuditBatchQueue Consumer +*/ + +public class AuditFileCacheProvider extends BaseAuditHandler { + private static final Log logger = LogFactory.getLog(AuditFileCacheProvider.class); + + AuditFileCacheProviderSpool fileSpooler = null; + AuditHandler consumer = null; + + AuditFileCacheProvider(AuditHandler consumer) { + this.consumer = consumer; + } + + public void init(Properties prop, String basePropertyName) { + String propPrefix = "xasecure.audit.filecache"; + if (basePropertyName != null) { + propPrefix = basePropertyName; + } + super.init(prop, propPrefix); + //init Consumer + if (consumer != null) { + consumer.init(prop, propPrefix); + } + //init AuditFileCacheSpooler + fileSpooler = new AuditFileCacheProviderSpool(consumer); + fileSpooler.init(prop,propPrefix); + } + @Override + public boolean log(AuditEventBase event) { + boolean ret = false; + if ( event != null) { + fileSpooler.stashLogs(event); + if ( fileSpooler.isSpoolingSuccessful()) { + ret = true; + } + } + return ret; + } + + @Override + public boolean log(Collection events) { + boolean ret = true; + if ( events != null) { + for (AuditEventBase event : events) { + ret = log(event); + } + } + return ret; + } + + @Override + public void start() { + // Start the consumer thread + if (consumer != null) { + consumer.start(); + } + if (fileSpooler != null) { + // start AuditFileSpool thread + fileSpooler.start(); + } + } + + @Override + public void stop() { + logger.info("Stop called. name=" + getName()); + if (consumer != null) { + consumer.stop(); + } + } + + @Override + public void waitToComplete() { + logger.info("waitToComplete called. name=" + getName()); + if ( consumer != null) { + consumer.waitToComplete(); + } + } + + @Override + public void waitToComplete(long timeout) { + logger.info("waitToComplete called. name=" + getName()); + if ( consumer != null) { + consumer.waitToComplete(timeout); + } + } + + @Override + public void flush() { + logger.info("waitToComplete. name=" + getName()); + if ( consumer != null) { + consumer.flush(); + } + } +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/provider/AuditHandler.java b/auth-audits/src/main/java/org/apache/atlas/audit/provider/AuditHandler.java new file mode 100644 index 00000000000..ed4feb18bf1 --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/provider/AuditHandler.java @@ -0,0 +1,48 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.provider; + +import org.apache.atlas.audit.model.AuditEventBase; + +import java.io.File; +import java.util.Collection; +import java.util.Properties; + +public interface AuditHandler { + boolean log(AuditEventBase event); + boolean log(Collection events); + + boolean logJSON(String event); + boolean logJSON(Collection events); + boolean logFile(File file); + + void init(Properties prop); + void init(Properties prop, String basePropertyName); + void start(); + void stop(); + void waitToComplete(); + void waitToComplete(long timeout); + + /** + * Name for this provider. Used only during logging. Uniqueness is not guaranteed + */ + String getName(); + + void flush(); +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/provider/AuditProviderFactory.java b/auth-audits/src/main/java/org/apache/atlas/audit/provider/AuditProviderFactory.java new file mode 100644 index 00000000000..376e9eecdc7 --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/provider/AuditProviderFactory.java @@ -0,0 +1,454 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.provider; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.audit.destination.*; +import org.apache.atlas.audit.queue.AuditAsyncQueue; +import org.apache.atlas.audit.queue.AuditBatchQueue; +import org.apache.atlas.audit.queue.AuditFileQueue; +import org.apache.atlas.audit.queue.AuditQueue; +import org.apache.atlas.audit.queue.AuditSummaryQueue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +/* + * TODO: + * 1) Flag to enable/disable audit logging + * 2) Failed path to be recorded + * 3) Repo name, repo type from configuration + */ + +public class AuditProviderFactory { + private static final Log LOG = LogFactory + .getLog(AuditProviderFactory.class); + + public static final String AUDIT_IS_ENABLED_PROP = "xasecure.audit.is.enabled"; + public static final String AUDIT_HDFS_IS_ENABLED_PROP = "xasecure.audit.hdfs.is.enabled"; + public static final String AUDIT_LOG4J_IS_ENABLED_PROP = "xasecure.audit.log4j.is.enabled"; + public static final String AUDIT_KAFKA_IS_ENABLED_PROP = "xasecure.audit.kafka.is.enabled"; + public static final String AUDIT_SOLR_IS_ENABLED_PROP = "xasecure.audit.solr.is.enabled"; + + public static final String AUDIT_DEST_BASE = "xasecure.audit.destination"; + public static final String AUDIT_SHUTDOWN_HOOK_MAX_WAIT_SEC = "xasecure.audit.shutdown.hook.max.wait.seconds"; + public static final String AUDIT_IS_FILE_CACHE_PROVIDER_ENABLE_PROP = "xasecure.audit.provider.filecache.is.enabled"; + public static final String FILE_QUEUE_TYPE = "filequeue"; + public static final String DEFAULT_QUEUE_TYPE = "memoryqueue"; + public static final int AUDIT_SHUTDOWN_HOOK_MAX_WAIT_SEC_DEFAULT = 30; + + public static final int AUDIT_ASYNC_MAX_QUEUE_SIZE_DEFAULT = 10 * 1024; + public static final int AUDIT_ASYNC_MAX_FLUSH_INTERVAL_DEFAULT = 5 * 1000; + + private static final int RANGER_AUDIT_SHUTDOWN_HOOK_PRIORITY = 30; + + private volatile static AuditProviderFactory sFactory = null; + + private AuditHandler mProvider = null; + private String componentAppType = ""; + private boolean mInitDone = false; + private JVMShutdownHook jvmShutdownHook = null; + private ArrayList hbaseAppTypes = new ArrayList<>(Arrays.asList("hbaseMaster","hbaseRegional")); + + public AuditProviderFactory() { + LOG.info("AuditProviderFactory: creating.."); + + mProvider = getDefaultProvider(); + } + + public static AuditProviderFactory getInstance() { + AuditProviderFactory ret = sFactory; + if(ret == null) { + synchronized(AuditProviderFactory.class) { + ret = sFactory; + if(ret == null) { + ret = sFactory = new AuditProviderFactory(); + } + } + } + + return ret; + } + + public AuditHandler getAuditProvider() { + return mProvider; + } + + public boolean isInitDone() { + return mInitDone; + } + + /** + * call shutdown hook to provide a way to + * shutdown gracefully in addition to the ShutdownHook mechanism + */ + public void shutdown() { + if (isInitDone() && jvmShutdownHook != null) { + jvmShutdownHook.run(); + } + } + + public synchronized void init(Properties props, String appType) { + LOG.info("AuditProviderFactory: initializing.."); + + if (mInitDone) { + LOG.warn("AuditProviderFactory.init(): already initialized! Will try to re-initialize"); + } + mInitDone = true; + componentAppType = appType; + MiscUtil.setApplicationType(appType); + + boolean isEnabled = MiscUtil.getBooleanProperty(props, + AUDIT_IS_ENABLED_PROP, true); + if (!isEnabled) { + LOG.info("AuditProviderFactory: Audit not enabled.."); + mProvider = getDefaultProvider(); + return; + } + + boolean isAuditToLog4jEnabled = MiscUtil.getBooleanProperty(props, + AUDIT_LOG4J_IS_ENABLED_PROP, false); + + boolean isAuditFileCacheProviderEnabled = MiscUtil.getBooleanProperty(props, + AUDIT_IS_FILE_CACHE_PROVIDER_ENABLE_PROP, false); + + List providers = new ArrayList(); + + for (Object propNameObj : props.keySet()) { + if (LOG.isDebugEnabled()){ + LOG.debug("AUDIT PROPERTY: " + propNameObj.toString() + "=" + + props.getProperty(propNameObj.toString())); + } + } + + // Process new audit configurations + List destNameList = new ArrayList(); + + for (Object propNameObj : props.keySet()) { + String propName = propNameObj.toString(); + if (!propName.startsWith(AUDIT_DEST_BASE)) { + continue; + } + String destName = propName.substring(AUDIT_DEST_BASE.length() + 1); + List splits = MiscUtil.toArray(destName, "."); + if (splits.size() > 1) { + continue; + } + String value = props.getProperty(propName); + if (value.equalsIgnoreCase("enable") + || value.equalsIgnoreCase("enabled") + || value.equalsIgnoreCase("true")) { + destNameList.add(destName); + LOG.info("Audit destination " + propName + " is set to " + + value); + } + } + + for (String destName : destNameList) { + String destPropPrefix = AUDIT_DEST_BASE + "." + destName; + AuditHandler destProvider = getProviderFromConfig(props, + destPropPrefix, destName, null); + + if (destProvider != null) { + destProvider.init(props, destPropPrefix); + + String queueName = MiscUtil.getStringProperty(props, + destPropPrefix + "." + AuditQueue.PROP_QUEUE); + if (queueName == null || queueName.isEmpty()) { + LOG.info(destPropPrefix + "." + AuditQueue.PROP_QUEUE + + " is not set. Setting queue to batch for " + + destName); + queueName = "batch"; + } + LOG.info("queue for " + destName + " is " + queueName); + if (queueName != null && !queueName.isEmpty() + && !queueName.equalsIgnoreCase("none")) { + String queuePropPrefix = destPropPrefix + "." + queueName; + AuditHandler queueProvider = getProviderFromConfig(props, + queuePropPrefix, queueName, destProvider); + if (queueProvider != null) { + if (queueProvider instanceof AuditQueue) { + AuditQueue qProvider = (AuditQueue) queueProvider; + qProvider.init(props, queuePropPrefix); + providers.add(queueProvider); + } else { + LOG.fatal("Provider queue doesn't extend AuditQueue. Destination=" + + destName + + " can't be created. queueName=" + + queueName); + } + } else { + LOG.fatal("Queue provider for destination " + destName + + " can't be created. queueName=" + queueName); + } + } else { + LOG.info("Audit destination " + destProvider.getName() + + " added to provider list"); + providers.add(destProvider); + } + } + } + if (providers.size() > 0) { + LOG.info("Using v3 audit configuration"); + AuditHandler consumer = providers.get(0); + + // Possible pipeline is: + // async_queue -> summary_queue -> multidestination -> batch_queue + // -> hdfs_destination + // -> batch_queue -> solr_destination + // -> batch_queue -> kafka_destination + // Above, up to multidestination, the providers are same, then it + // branches out in parallel. + + // Set the providers in the reverse order e.g. + + if (providers.size() > 1) { + // If there are more than one destination, then we need multi + // destination to process it in parallel + LOG.info("MultiDestAuditProvider is used. Destination count=" + + providers.size()); + MultiDestAuditProvider multiDestProvider = new MultiDestAuditProvider(); + multiDestProvider.init(props); + multiDestProvider.addAuditProviders(providers); + consumer = multiDestProvider; + } + + // Let's see if Summary is enabled, then summarize before sending it + // downstream + String propPrefix = BaseAuditHandler.PROP_DEFAULT_PREFIX; + boolean summaryEnabled = MiscUtil.getBooleanProperty(props, + propPrefix + "." + "summary" + "." + "enabled", false); + AuditSummaryQueue summaryQueue = null; + if (summaryEnabled) { + LOG.info("AuditSummaryQueue is enabled"); + summaryQueue = new AuditSummaryQueue(consumer); + summaryQueue.init(props, propPrefix); + consumer = summaryQueue; + } else { + LOG.info("AuditSummaryQueue is disabled"); + } + + if (!isAuditFileCacheProviderEnabled) { + // Create the AsysnQueue + AuditAsyncQueue asyncQueue = new AuditAsyncQueue(consumer); + propPrefix = BaseAuditHandler.PROP_DEFAULT_PREFIX + "." + "async"; + asyncQueue.init(props, propPrefix); + asyncQueue.setParentPath(componentAppType); + mProvider = asyncQueue; + LOG.info("Starting audit queue " + mProvider.getName()); + mProvider.start(); + } else { + // Assign AsyncQueue to AuditFileCacheProvider + AuditFileCacheProvider auditFileCacheProvider = new AuditFileCacheProvider(consumer); + propPrefix = BaseAuditHandler.PROP_DEFAULT_PREFIX + "." + "filecache"; + auditFileCacheProvider.init(props, propPrefix); + auditFileCacheProvider.setParentPath(componentAppType); + mProvider = auditFileCacheProvider; + LOG.info("Starting Audit File Cache Provider " + mProvider.getName()); + mProvider.start(); + } + } else { + LOG.info("No v3 audit configuration found. Trying v2 audit configurations"); + if (!isEnabled || !(isAuditToLog4jEnabled || providers.size() == 0)) { + LOG.info("AuditProviderFactory: Audit not enabled.."); + + mProvider = getDefaultProvider(); + + return; + } + + if (providers.size() == 0) { + mProvider = getDefaultProvider(); + } else if (providers.size() == 1) { + mProvider = providers.get(0); + } else { + MultiDestAuditProvider multiDestProvider = new MultiDestAuditProvider(); + + multiDestProvider.addAuditProviders(providers); + + mProvider = multiDestProvider; + } + + mProvider.init(props); + mProvider.start(); + } + + installJvmSutdownHook(props); + } + + private AuditHandler getProviderFromConfig(Properties props, + String propPrefix, String providerName, AuditHandler consumer) { + AuditHandler provider = null; + String className = MiscUtil.getStringProperty(props, propPrefix + "." + + BaseAuditHandler.PROP_CLASS_NAME); + if (className != null && !className.isEmpty()) { + try { + Class handlerClass = Class.forName(className); + if (handlerClass.isAssignableFrom(AuditQueue.class)) { + // Queue class needs consumer + handlerClass.getDeclaredConstructor(AuditHandler.class) + .newInstance(consumer); + } else { + provider = (AuditHandler) Class.forName(className) + .newInstance(); + } + } catch (Exception e) { + LOG.fatal("Can't instantiate audit class for providerName=" + + providerName + ", className=" + className + + ", propertyPrefix=" + propPrefix, e); + } + } else { + if (providerName.equalsIgnoreCase("elasticsearch")) { + provider = new ElasticSearchAuditDestination(); + } else if (providerName.equalsIgnoreCase("log4j")) { + provider = new Log4JAuditDestination(); + } else if (providerName.equalsIgnoreCase("batch")) { + provider = getAuditProvider(props, propPrefix, consumer); + } else if (providerName.equalsIgnoreCase("async")) { + provider = new AuditAsyncQueue(consumer); + } else { + LOG.error("Provider name doesn't have any class associated with it. providerName=" + + providerName + ", propertyPrefix=" + propPrefix); + } + } + if (provider != null && provider instanceof AuditQueue) { + if (consumer == null) { + LOG.fatal("consumer can't be null for AuditQueue. queue=" + + provider.getName() + ", propertyPrefix=" + propPrefix); + provider = null; + } + } + return provider; + } + + private AuditHandler getAuditProvider(Properties props, String propPrefix, AuditHandler consumer) { + AuditHandler ret = null; + String queueType = MiscUtil.getStringProperty(props, propPrefix + "." + "queuetype", DEFAULT_QUEUE_TYPE); + + if (LOG.isDebugEnabled()) { + LOG.debug("==> AuditProviderFactory.getAuditProvider() propPerfix= " + propPrefix + ", " + " queueType= " + queueType); + } + + if (FILE_QUEUE_TYPE.equalsIgnoreCase(queueType)) { + AuditFileQueue auditFileQueue = new AuditFileQueue(consumer); + String propPrefixFileQueue = propPrefix + "." + FILE_QUEUE_TYPE; + auditFileQueue.init(props, propPrefixFileQueue); + ret = new AuditBatchQueue(auditFileQueue); + } else { + ret = new AuditBatchQueue(consumer); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== AuditProviderFactory.getAuditProvider()"); + } + + return ret; + } + + private AuditHandler getDefaultProvider() { + return new DummyAuditProvider(); + } + + private void installJvmSutdownHook(Properties props) { + int shutdownHookMaxWaitSeconds = MiscUtil.getIntProperty(props, AUDIT_SHUTDOWN_HOOK_MAX_WAIT_SEC, AUDIT_SHUTDOWN_HOOK_MAX_WAIT_SEC_DEFAULT); + jvmShutdownHook = new JVMShutdownHook(mProvider, shutdownHookMaxWaitSeconds); + String appType = this.componentAppType; + if (appType != null && !hbaseAppTypes.contains(appType)) { + Runtime.getRuntime().addShutdownHook(jvmShutdownHook); + } + } + + private static class RangerAsyncAuditCleanup implements Runnable { + + final Semaphore startCleanup; + final Semaphore doneCleanup; + final AuditHandler mProvider; + + RangerAsyncAuditCleanup(AuditHandler provider, Semaphore startCleanup, Semaphore doneCleanup) { + this.startCleanup = startCleanup; + this.doneCleanup = doneCleanup; + this.mProvider = provider; + } + + @Override + public void run() { + while (true) { + LOG.info("RangerAsyncAuditCleanup: Waiting to audit cleanup start signal"); + try { + startCleanup.acquire(); + } catch (InterruptedException e) { + LOG.info("RangerAsyncAuditCleanup: Interrupted while waiting for audit startCleanup signal! Exiting the thread...", e); + break; + } + LOG.info("RangerAsyncAuditCleanup: Starting cleanup"); + mProvider.waitToComplete(); + mProvider.stop(); + doneCleanup.release(); + LOG.info("RangerAsyncAuditCleanup: Done cleanup"); + } + } + } + + private static class JVMShutdownHook extends Thread { + final Semaphore startCleanup = new Semaphore(0); + final Semaphore doneCleanup = new Semaphore(0); + final Thread cleanupThread; + final int maxWait; + final AtomicBoolean done = new AtomicBoolean(false); + + public JVMShutdownHook(AuditHandler provider, int maxWait) { + this.maxWait = maxWait; + Runnable runnable = new RangerAsyncAuditCleanup(provider, startCleanup, doneCleanup); + cleanupThread = new Thread(runnable, "Ranger async Audit cleanup"); + cleanupThread.setDaemon(true); + cleanupThread.start(); + } + + public void run() { + if (!done.compareAndSet(false, true)) { + LOG.info("==> JVMShutdownHook.run() already done by another thread"); + return; + } + LOG.info("==> JVMShutdownHook.run()"); + LOG.info("JVMShutdownHook: Signalling async audit cleanup to start."); + startCleanup.release(); + try { + Long start = System.currentTimeMillis(); + LOG.info("JVMShutdownHook: Waiting up to " + maxWait + " seconds for audit cleanup to finish."); + boolean cleanupFinishedInTime = doneCleanup.tryAcquire(maxWait, TimeUnit.SECONDS); + if (cleanupFinishedInTime) { + LOG.info("JVMShutdownHook: Audit cleanup finished after " + (System.currentTimeMillis() - start) + " milli seconds"); + } else { + LOG.warn("JVMShutdownHook: could not detect finishing of audit cleanup even after waiting for " + maxWait + " seconds!"); + } + } catch (InterruptedException e) { + LOG.info("JVMShutdownHook: Interrupted while waiting for completion of Async executor!", e); + } + LOG.info("JVMShutdownHook: Interrupting ranger async audit cleanup thread"); + cleanupThread.interrupt(); + LOG.info("<== JVMShutdownHook.run()"); + } + } +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/provider/BaseAuditHandler.java b/auth-audits/src/main/java/org/apache/atlas/audit/provider/BaseAuditHandler.java new file mode 100644 index 00000000000..f68d96f7a3d --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/provider/BaseAuditHandler.java @@ -0,0 +1,464 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.provider; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.audit.model.AuditEventBase; +import org.apache.atlas.audit.model.AuthzAuditEvent; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicLong; + +public abstract class BaseAuditHandler implements AuditHandler { + private static final Log LOG = LogFactory.getLog(BaseAuditHandler.class); + + static final String AUDIT_LOG_FAILURE_REPORT_MIN_INTERVAL_PROP = "xasecure.audit.log.failure.report.min.interval.ms"; + + public static final String PROP_CONFIG = "config"; + + private int mLogFailureReportMinIntervalInMs = 60 * 1000; + + private AtomicLong mFailedLogLastReportTime = new AtomicLong(0); + private AtomicLong mFailedLogCountSinceLastReport = new AtomicLong(0); + private AtomicLong mFailedLogCountLifeTime = new AtomicLong(0); + + public static final String PROP_NAME = "name"; + public static final String PROP_CLASS_NAME = "classname"; + + public static final String PROP_DEFAULT_PREFIX = "xasecure.audit.provider"; + + protected String propPrefix = PROP_DEFAULT_PREFIX; + + protected String providerName = null; + protected String parentPath = null; + + int errorLogIntervalMS = 30 * 1000; // Every 30 seconds + long lastErrorLogMS = 0; + + long totalCount = 0; + long totalSuccessCount = 0; + long totalFailedCount = 0; + long totalStashedCount = 0; + long totalDeferredCount = 0; + + long lastIntervalCount = 0; + long lastIntervalSuccessCount = 0; + long lastIntervalFailedCount = 0; + long lastStashedCount = 0; + long lastDeferredCount = 0; + + long lastStatusLogTime = System.currentTimeMillis(); + long statusLogIntervalMS = 1 * 60 * 1000; + + protected Properties props = null; + protected Map configProps = new HashMap(); + + @Override + public void init(Properties props) { + init(props, null); + } + + @Override + public void init(Properties props, String basePropertyName) { + LOG.info("BaseAuditProvider.init()"); + this.props = props; + if (basePropertyName != null) { + propPrefix = basePropertyName; + } + LOG.info("propPrefix=" + propPrefix); + + String name = MiscUtil.getStringProperty(props, basePropertyName + "." + + PROP_NAME); + if (name != null && !name.isEmpty()) { + setName(name); + } + // Get final token + if (providerName == null) { + List tokens = MiscUtil.toArray(propPrefix, "."); + if (!tokens.isEmpty()) { + String finalToken = tokens.get(tokens.size() - 1); + setName(finalToken); + LOG.info("Using providerName from property prefix. providerName=" + + getName()); + } + } + LOG.info("providerName=" + getName()); + + mLogFailureReportMinIntervalInMs = MiscUtil.getIntProperty(props, + AUDIT_LOG_FAILURE_REPORT_MIN_INTERVAL_PROP, 60 * 1000); + + String configPropsNamePrefix = propPrefix + "." + PROP_CONFIG + "."; + for (Object propNameObj : props.keySet()) { + String propName = propNameObj.toString(); + + if (!propName.startsWith(configPropsNamePrefix)) { + continue; + } + String configName = propName.substring(configPropsNamePrefix.length()); + String configValue = props.getProperty(propName); + configProps.put(configName, configValue); + LOG.info("Found Config property: " + configName + " => " + configValue); + } + } + + /* + * (non-Javadoc) + * + * @see + * org.apache.ranger.audit.provider.AuditProvider#log(org.apache.ranger. + * audit.model.AuditEventBase) + */ + @Override + public boolean log(AuditEventBase event) { + return log(Collections.singletonList(event)); + } + + /* + * (non-Javadoc) + * + * @see + * org.apache.ranger.audit.provider.AuditProvider#logJSON(java.lang.String) + */ + @Override + public boolean logJSON(String event) { + AuditEventBase eventObj = MiscUtil.fromJson(event, + AuthzAuditEvent.class); + return log(eventObj); + } + + /* + * (non-Javadoc) + * + * @see + * org.apache.ranger.audit.provider.AuditProvider#logJSON(java.util.Collection + * ) + */ + @Override + public boolean logJSON(Collection events) { + List eventList = new ArrayList(events.size()); + for (String event : events) { + eventList.add(MiscUtil.fromJson(event, AuthzAuditEvent.class)); + } + return log(eventList); + } + + @Override + public boolean logFile(File file) { + return logFile(file); + } + + public String getParentPath() { + return parentPath; + } + + public void setParentPath(String parentPath) { + this.parentPath = parentPath; + } + + public String getFinalPath() { + return getName(); + } + + public void setName(String name) { + providerName = name; + } + + @Override + public String getName() { + if (parentPath != null) { + return parentPath + "." + providerName; + } + return providerName; + } + + public long addTotalCount(int count) { + totalCount += count; + return totalCount; + } + + public long addSuccessCount(int count) { + totalSuccessCount += count; + return totalSuccessCount; + } + + public long addFailedCount(int count) { + totalFailedCount += count; + return totalFailedCount; + } + + public long addStashedCount(int count) { + totalStashedCount += count; + return totalStashedCount; + } + + public long addDeferredCount(int count) { + totalDeferredCount += count; + return totalDeferredCount; + } + + public long getTotalCount() { + return totalCount; + } + + public long getTotalSuccessCount() { + return totalSuccessCount; + } + + public long getTotalFailedCount() { + return totalFailedCount; + } + + public long getTotalStashedCount() { + return totalStashedCount; + } + + public long getLastStashedCount() { + return lastStashedCount; + } + + public long getTotalDeferredCount() { + return totalDeferredCount; + } + + public long getLastDeferredCount() { + return lastDeferredCount; + } + + public void logStatusIfRequired() { + long currTime = System.currentTimeMillis(); + if ((currTime - lastStatusLogTime) > statusLogIntervalMS) { + logStatus(); + } + } + + public void logStatus() { + try { + long currTime = System.currentTimeMillis(); + + long diffTime = currTime - lastStatusLogTime; + lastStatusLogTime = currTime; + + long diffCount = totalCount - lastIntervalCount; + long diffSuccess = totalSuccessCount - lastIntervalSuccessCount; + long diffFailed = totalFailedCount - lastIntervalFailedCount; + long diffStashed = totalStashedCount - lastStashedCount; + long diffDeferred = totalDeferredCount - lastDeferredCount; + + if (diffCount == 0 && diffSuccess == 0 && diffFailed == 0 + && diffStashed == 0 && diffDeferred == 0) { + return; + } + + lastIntervalCount = totalCount; + lastIntervalSuccessCount = totalSuccessCount; + lastIntervalFailedCount = totalFailedCount; + lastStashedCount = totalStashedCount; + lastDeferredCount = totalDeferredCount; + + String finalPath = ""; + String tFinalPath = getFinalPath(); + if (!getName().equals(tFinalPath)) { + finalPath = ", finalDestination=" + tFinalPath; + } + + String msg = "Audit Status Log: name=" + + getName() + + finalPath + + ", interval=" + + formatIntervalForLog(diffTime) + + ", events=" + + diffCount + + (diffSuccess > 0 ? (", succcessCount=" + diffSuccess) + : "") + + (diffFailed > 0 ? (", failedCount=" + diffFailed) : "") + + (diffStashed > 0 ? (", stashedCount=" + diffStashed) : "") + + (diffDeferred > 0 ? (", deferredCount=" + diffDeferred) + : "") + + ", totalEvents=" + + totalCount + + (totalSuccessCount > 0 ? (", totalSuccessCount=" + totalSuccessCount) + : "") + + (totalFailedCount > 0 ? (", totalFailedCount=" + totalFailedCount) + : "") + + (totalStashedCount > 0 ? (", totalStashedCount=" + totalStashedCount) + : "") + + (totalDeferredCount > 0 ? (", totalDeferredCount=" + totalDeferredCount) + : ""); + LOG.info(msg); + } catch (Throwable t) { + LOG.error("Error while printing stats. auditProvider=" + getName()); + } + } + + public void logError(String msg) { + long currTimeMS = System.currentTimeMillis(); + if (currTimeMS - lastErrorLogMS > errorLogIntervalMS) { + LOG.error(msg); + lastErrorLogMS = currTimeMS; + } + } + + public void logError(String msg, Throwable ex) { + long currTimeMS = System.currentTimeMillis(); + if (currTimeMS - lastErrorLogMS > errorLogIntervalMS) { + LOG.error(msg, ex); + lastErrorLogMS = currTimeMS; + } + } + + public String getTimeDiffStr(long time1, long time2) { + long timeInMs = Math.abs(time1 - time2); + return formatIntervalForLog(timeInMs); + } + + public String formatIntervalForLog(long timeInMs) { + long hours = timeInMs / (60 * 60 * 1000); + long minutes = (timeInMs / (60 * 1000)) % 60; + long seconds = (timeInMs % (60 * 1000)) / 1000; + long mSeconds = (timeInMs % (1000)); + + if (hours > 0) + return String.format("%02d:%02d:%02d.%03d hours", hours, minutes, + seconds, mSeconds); + else if (minutes > 0) + return String.format("%02d:%02d.%03d minutes", minutes, seconds, + mSeconds); + else if (seconds > 0) + return String.format("%02d.%03d seconds", seconds, mSeconds); + else + return String.format("%03d milli-seconds", mSeconds); + } + + public void logFailedEvent(AuditEventBase event) { + logFailedEvent(event, ""); + } + + public void logFailedEvent(AuditEventBase event, Throwable excp) { + long now = System.currentTimeMillis(); + + long timeSinceLastReport = now - mFailedLogLastReportTime.get(); + long countSinceLastReport = mFailedLogCountSinceLastReport + .incrementAndGet(); + long countLifeTime = mFailedLogCountLifeTime.incrementAndGet(); + + if (timeSinceLastReport >= mLogFailureReportMinIntervalInMs) { + mFailedLogLastReportTime.set(now); + mFailedLogCountSinceLastReport.set(0); + + if (excp != null) { + LOG.warn( + "failed to log audit event: " + + MiscUtil.stringify(event), excp); + } else { + LOG.warn("failed to log audit event: " + + MiscUtil.stringify(event)); + } + + if (countLifeTime > 1) { // no stats to print for the 1st failure + LOG.warn("Log failure count: " + countSinceLastReport + + " in past " + + formatIntervalForLog(timeSinceLastReport) + "; " + + countLifeTime + " during process lifetime"); + } + } + } + + public void logFailedEvent(Collection events) { + logFailedEvent(events, ""); + } + + public void logFailedEvent(Collection events, Throwable excp) { + for (AuditEventBase event : events) { + logFailedEvent(event, excp); + } + } + + public void logFailedEvent(AuditEventBase event, String message) { + long now = System.currentTimeMillis(); + + long timeSinceLastReport = now - mFailedLogLastReportTime.get(); + long countSinceLastReport = mFailedLogCountSinceLastReport + .incrementAndGet(); + long countLifeTime = mFailedLogCountLifeTime.incrementAndGet(); + + if (timeSinceLastReport >= mLogFailureReportMinIntervalInMs) { + mFailedLogLastReportTime.set(now); + mFailedLogCountSinceLastReport.set(0); + + LOG.warn("failed to log audit event: " + MiscUtil.stringify(event) + + ", errorMessage=" + message); + + if (countLifeTime > 1) { // no stats to print for the 1st failure + LOG.warn("Log failure count: " + countSinceLastReport + + " in past " + + formatIntervalForLog(timeSinceLastReport) + "; " + + countLifeTime + " during process lifetime"); + } + } + } + + public void logFailedEvent(Collection events, + String errorMessage) { + for (AuditEventBase event : events) { + logFailedEvent(event, errorMessage); + } + } + + public void logFailedEventJSON(String event, Throwable excp) { + long now = System.currentTimeMillis(); + + long timeSinceLastReport = now - mFailedLogLastReportTime.get(); + long countSinceLastReport = mFailedLogCountSinceLastReport + .incrementAndGet(); + long countLifeTime = mFailedLogCountLifeTime.incrementAndGet(); + + if (timeSinceLastReport >= mLogFailureReportMinIntervalInMs) { + mFailedLogLastReportTime.set(now); + mFailedLogCountSinceLastReport.set(0); + + if (excp != null) { + LOG.warn("failed to log audit event: " + event, excp); + } else { + LOG.warn("failed to log audit event: " + event); + } + + if (countLifeTime > 1) { // no stats to print for the 1st failure + LOG.warn("Log failure count: " + countSinceLastReport + + " in past " + + formatIntervalForLog(timeSinceLastReport) + "; " + + countLifeTime + " during process lifetime"); + } + } + } + + public void logFailedEventJSON(Collection events, Throwable excp) { + for (String event : events) { + logFailedEventJSON(event, excp); + } + } + +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/provider/DummyAuditProvider.java b/auth-audits/src/main/java/org/apache/atlas/audit/provider/DummyAuditProvider.java new file mode 100644 index 00000000000..fb7631d05ec --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/provider/DummyAuditProvider.java @@ -0,0 +1,115 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.provider; + +import org.apache.atlas.audit.model.AuditEventBase; +import org.apache.atlas.audit.model.AuthzAuditEvent; + +import java.io.File; +import java.util.Collection; +import java.util.Properties; + + +public class DummyAuditProvider implements AuditHandler { + @Override + public void init(Properties prop) { + // intentionally left empty + } + + @Override + public boolean log(AuditEventBase event) { + // intentionally left empty + return true; + } + + @Override + public boolean log(Collection events) { + for (AuditEventBase event : events) { + log(event); + } + return true; + } + + @Override + public boolean logJSON(String event) { + AuditEventBase eventObj = MiscUtil.fromJson(event, + AuthzAuditEvent.class); + return log(eventObj); + } + + @Override + public boolean logJSON(Collection events) { + for (String event : events) { + logJSON(event); + } + return false; + } + + @Override + public void start() { + // intentionally left empty + } + + @Override + public void stop() { + // intentionally left empty + } + + @Override + public void waitToComplete() { + // intentionally left empty + } + + @Override + public void flush() { + // intentionally left empty + } + + /* (non-Javadoc) + * @see org.apache.ranger.audit.provider.AuditProvider#init(java.util.Properties, java.lang.String) + */ + @Override + public void init(Properties prop, String basePropertyName) { + // intentionally left empty + } + + /* (non-Javadoc) + * @see org.apache.ranger.audit.provider.AuditProvider#waitToComplete(long) + */ + @Override + public void waitToComplete(long timeout) { + // intentionally left empty + } + + /* (non-Javadoc) + * @see org.apache.ranger.audit.provider.AuditProvider#getName() + */ + @Override + public String getName() { + return this.getClass().getName(); + } + + /* (non-Javadoc) + * @see org.apache.ranger.audit.provider.AuditProvider#getAuditFileType() + */ + @Override + public boolean logFile(File file) { + return logFile(file); + } + +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/provider/MiscUtil.java b/auth-audits/src/main/java/org/apache/atlas/audit/provider/MiscUtil.java new file mode 100644 index 00000000000..38920904ffe --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/provider/MiscUtil.java @@ -0,0 +1,470 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.atlas.audit.provider; + +import org.apache.atlas.audit.utils.AuthObjectUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.net.InetAddress; +import java.rmi.dgc.VMID; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Random; +import java.util.StringTokenizer; +import java.util.UUID; + + +public class MiscUtil { + private static final Logger logger = LoggerFactory.getLogger(MiscUtil.class); + + public static final String TOKEN_START = "%"; + public static final String TOKEN_END = "%"; + public static final String TOKEN_HOSTNAME = "hostname"; + public static final String TOKEN_APP_TYPE = "app-type"; + public static final String TOKEN_JVM_INSTANCE = "jvm-instance"; + public static final String TOKEN_TIME = "time:"; + public static final String TOKEN_PROPERTY = "property:"; + public static final String TOKEN_ENV = "env:"; + + private static final VMID sJvmID = new VMID(); + + private static String sApplicationType = null; + private static String local_hostname = null; + + private static Map logHistoryList = new Hashtable(); + private static int logInterval = 30000; // 30 seconds + + public static String replaceTokens(String str, long time) { + if (str == null) { + return str; + } + + if (time <= 0) { + time = System.currentTimeMillis(); + } + + for (int startPos = 0; startPos < str.length();) { + int tagStartPos = str.indexOf(TOKEN_START, startPos); + + if (tagStartPos == -1) { + break; + } + + int tagEndPos = str.indexOf(TOKEN_END, + tagStartPos + TOKEN_START.length()); + + if (tagEndPos == -1) { + break; + } + + String tag = str.substring(tagStartPos, + tagEndPos + TOKEN_END.length()); + String token = tag.substring(TOKEN_START.length(), + tag.lastIndexOf(TOKEN_END)); + String val = ""; + + if (token != null) { + if (token.equals(TOKEN_HOSTNAME)) { + val = getHostname(); + } else if (token.equals(TOKEN_APP_TYPE)) { + val = getApplicationType(); + } else if (token.equals(TOKEN_JVM_INSTANCE)) { + val = getJvmInstanceId(); + } else if (token.startsWith(TOKEN_PROPERTY)) { + String propertyName = token.substring(TOKEN_PROPERTY + .length()); + + val = getSystemProperty(propertyName); + } else if (token.startsWith(TOKEN_ENV)) { + String envName = token.substring(TOKEN_ENV.length()); + + val = getEnv(envName); + } else if (token.startsWith(TOKEN_TIME)) { + String dtFormat = token.substring(TOKEN_TIME.length()); + + val = getFormattedTime(time, dtFormat); + } + } + + if (val == null) { + val = ""; + } + + str = str.substring(0, tagStartPos) + val + + str.substring(tagEndPos + TOKEN_END.length()); + startPos = tagStartPos + val.length(); + } + + return str; + } + + public static String getHostname() { + String ret = local_hostname; + + if (ret == null) { + initLocalHost(); + + ret = local_hostname; + + if (ret == null) { + ret = "unknown"; + } + } + + return ret; + } + + public static void setApplicationType(String applicationType) { + sApplicationType = applicationType; + } + + public static String getApplicationType() { + return sApplicationType; + } + + public static String getJvmInstanceId() { + Integer val = Integer.valueOf(sJvmID.toString().hashCode()); + long longVal = val.longValue(); + String ret = Long.toString(Math.abs(longVal)); + + return ret; + } + + public static String getSystemProperty(String propertyName) { + String ret = null; + + try { + ret = propertyName != null ? System.getProperty(propertyName) + : null; + } catch (Exception excp) { + logger.warn("getSystemProperty(" + propertyName + ") failed", excp); + } + + return ret; + } + + public static String getEnv(String envName) { + String ret = null; + + try { + ret = envName != null ? System.getenv(envName) : null; + } catch (Exception excp) { + logger.warn("getenv(" + envName + ") failed", excp); + } + + return ret; + } + + public static String getFormattedTime(long time, String format) { + String ret = null; + + try { + SimpleDateFormat sdf = new SimpleDateFormat(format); + + ret = sdf.format(time); + } catch (Exception excp) { + logger.warn("SimpleDateFormat.format() failed: " + format, excp); + } + + return ret; + } + + public static void createParents(File file) { + if (file != null) { + String parentName = file.getParent(); + + if (parentName != null) { + File parentDir = new File(parentName); + + if (!parentDir.exists()) { + if (!parentDir.mkdirs()) { + logger.warn("createParents(): failed to create " + + parentDir.getAbsolutePath()); + } + } + } + } + } + + public static long getNextRolloverTime(long lastRolloverTime, long interval) { + long now = System.currentTimeMillis() / 1000 * 1000; // round to second + + if (lastRolloverTime <= 0) { + // should this be set to the next multiple-of-the-interval from + // start of the day? + return now + interval; + } else if (lastRolloverTime <= now) { + long nextRolloverTime = now + interval; + + // keep it at 'interval' boundary + long trimInterval = (nextRolloverTime - lastRolloverTime) + % interval; + + return nextRolloverTime - trimInterval; + } else { + return lastRolloverTime; + } + } + + public static long getRolloverStartTime(long nextRolloverTime, long interval) { + return (nextRolloverTime <= interval) ? System.currentTimeMillis() + : nextRolloverTime - interval; + } + + public static int parseInteger(String str, int defValue) { + int ret = defValue; + + if (str != null) { + try { + ret = Integer.parseInt(str); + } catch (Exception excp) { + // ignore + } + } + + return ret; + } + + public static String generateUniqueId() { + return UUID.randomUUID().toString(); + } + + // UUID.randomUUID() uses SecureRandom, which is seen to be slow in some environments; this method uses Random + public static String generateGuid() { + byte[] randomBytes = new byte[16]; + + RandomHolder.random.nextBytes(randomBytes); + + UUID uuid = UUID.nameUUIDFromBytes(randomBytes); + + return uuid.toString(); + } + + public static String stringify(T log) { + String ret = null; + + if (log != null) { + if (log instanceof String) { + ret = (String) log; + } else { + ret = AuthObjectUtil.toJson(log); + } + } + + return ret; + } + + static public T fromJson(String jsonStr, Class clazz) { + return AuthObjectUtil.fromJson(jsonStr, clazz); + } + + public static String getStringProperty(Properties props, String propName) { + String ret = null; + + if (props != null && propName != null) { + String val = props.getProperty(propName); + if (val != null) { + ret = val; + } + } + + return ret; + } + + public static String getStringProperty(Properties props, String propName, String defValue) { + String ret = defValue; + + if (props != null && propName != null) { + String val = props.getProperty(propName); + if (val != null) { + ret = val; + } + } + + return ret; + } + + public static boolean getBooleanProperty(Properties props, String propName, + boolean defValue) { + boolean ret = defValue; + + if (props != null && propName != null) { + String val = props.getProperty(propName); + + if (val != null) { + ret = Boolean.valueOf(val); + } + } + + return ret; + } + + public static int getIntProperty(Properties props, String propName, + int defValue) { + int ret = defValue; + + if (props != null && propName != null) { + String val = props.getProperty(propName); + if (val != null) { + try { + ret = Integer.parseInt(val); + } catch (NumberFormatException excp) { + ret = defValue; + } + } + } + + return ret; + } + + public static long getLongProperty(Properties props, String propName, + long defValue) { + long ret = defValue; + + if (props != null && propName != null) { + String val = props.getProperty(propName); + if (val != null) { + try { + ret = Long.parseLong(val); + } catch (NumberFormatException excp) { + ret = defValue; + } + } + } + + return ret; + } + + public static Map getPropertiesWithPrefix(Properties props, + String prefix) { + Map prefixedProperties = new HashMap(); + + if (props != null && prefix != null) { + for (String key : props.stringPropertyNames()) { + if (key == null) { + continue; + } + + String val = props.getProperty(key); + + if (key.startsWith(prefix)) { + key = key.substring(prefix.length()); + + if (key == null) { + continue; + } + + prefixedProperties.put(key, val); + } + } + } + + return prefixedProperties; + } + + /** + * @param destListStr + * @param delim + * @return + */ + public static List toArray(String destListStr, String delim) { + List list = new ArrayList(); + if (destListStr != null && !destListStr.isEmpty()) { + StringTokenizer tokenizer = new StringTokenizer(destListStr, + delim.trim()); + while (tokenizer.hasMoreTokens()) { + list.add(tokenizer.nextToken()); + } + } + return list; + } + + static public boolean logErrorMessageByInterval(Logger useLogger, + String message) { + return logErrorMessageByInterval(useLogger, message, null); + } + + /** + * @param useLogger + * @param message + * @param e + */ + static public boolean logErrorMessageByInterval(Logger useLogger, + String message, Throwable e) { + if (message == null) { + return false; + } + + LogHistory log = logHistoryList.get(message); + if (log == null) { + log = new LogHistory(); + logHistoryList.put(message, log); + } + if ((System.currentTimeMillis() - log.lastLogTime) > logInterval) { + log.lastLogTime = System.currentTimeMillis(); + int counter = log.counter; + log.counter = 0; + if (counter > 0) { + message += ". Messages suppressed before: " + counter; + } + if (e == null) { + useLogger.error(message); + } else { + useLogger.error(message, e); + } + + return true; + } else { + log.counter++; + } + return false; + + } + + static class LogHistory { + long lastLogTime = 0; + int counter = 0; + } + + private static void initLocalHost() { + if ( logger.isDebugEnabled() ) { + logger.debug("==> MiscUtil.initLocalHost()"); + } + + try { + local_hostname = InetAddress.getLocalHost().getHostName(); + } catch (Throwable excp) { + logger.warn("getHostname()", excp); + } + if ( logger.isDebugEnabled() ) { + logger.debug("<== MiscUtil.initLocalHost()"); + } + } + + // use Holder class to defer initialization until needed + private static class RandomHolder { + static final Random random = new Random(); + } + +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/provider/MultiDestAuditProvider.java b/auth-audits/src/main/java/org/apache/atlas/audit/provider/MultiDestAuditProvider.java new file mode 100644 index 00000000000..91acde58e53 --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/provider/MultiDestAuditProvider.java @@ -0,0 +1,233 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.provider; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.audit.model.AuditEventBase; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Properties; + +public class MultiDestAuditProvider extends BaseAuditHandler { + + private static final Log LOG = LogFactory + .getLog(MultiDestAuditProvider.class); + + protected List mProviders = new ArrayList(); + static final String DEFAULT_NAME = "multi_dest"; + + public MultiDestAuditProvider() { + LOG.info("MultiDestAuditProvider: creating.."); + setName(DEFAULT_NAME); + } + + public MultiDestAuditProvider(AuditHandler provider) { + LOG.info("MultiDestAuditProvider(): provider=" + + (provider == null ? null : provider.getName())); + setName(DEFAULT_NAME); + addAuditProvider(provider); + } + + @Override + public void init(Properties props) { + LOG.info("MultiDestAuditProvider.init()"); + + super.init(props); + + for (AuditHandler provider : mProviders) { + try { + provider.init(props); + } catch (Throwable excp) { + LOG.info("MultiDestAuditProvider.init(): failed " + + provider.getClass().getCanonicalName() + ")", excp); + } + } + } + + @Override + public void setParentPath(String parentPath) { + super.setParentPath(parentPath); + for (AuditHandler provider : mProviders) { + if (provider instanceof BaseAuditHandler) { + BaseAuditHandler baseAuditHander = (BaseAuditHandler) provider; + baseAuditHander.setParentPath(getName()); + } + } + } + + @Override + public void setName(String name) { + super.setName(name); + for (AuditHandler provider : mProviders) { + if (provider instanceof BaseAuditHandler) { + BaseAuditHandler baseAuditHander = (BaseAuditHandler) provider; + baseAuditHander.setParentPath(getName()); + } + } + } + + public void addAuditProvider(AuditHandler provider) { + if (provider != null) { + LOG.info("MultiDestAuditProvider.addAuditProvider(providerType=" + + provider.getClass().getCanonicalName() + ")"); + + mProviders.add(provider); + if (provider instanceof BaseAuditHandler) { + BaseAuditHandler baseAuditHander = (BaseAuditHandler) provider; + baseAuditHander.setParentPath(getName()); + } + } + } + + public void addAuditProviders(List providers) { + if (providers != null) { + for (AuditHandler provider : providers) { + LOG.info("Adding " + provider.getName() + + " as consumer to MultiDestination " + getName()); + addAuditProvider(provider); + } + } + } + + @Override + public boolean log(AuditEventBase event) { + for (AuditHandler provider : mProviders) { + try { + provider.log(event); + } catch (Throwable excp) { + logFailedEvent(event, excp); + } + } + return true; + } + + @Override + public boolean log(Collection events) { + for (AuditHandler provider : mProviders) { + try { + provider.log(events); + } catch (Throwable excp) { + logFailedEvent(events, excp); + } + } + return true; + } + + @Override + public boolean logJSON(String event) { + for (AuditHandler provider : mProviders) { + try { + provider.logJSON(event); + } catch (Throwable excp) { + logFailedEventJSON(event, excp); + } + } + return true; + } + + @Override + public boolean logJSON(Collection events) { + for (AuditHandler provider : mProviders) { + try { + provider.logJSON(events); + } catch (Throwable excp) { + logFailedEventJSON(events, excp); + } + } + return true; + } + + + @Override + public boolean logFile(File file) { + for (AuditHandler provider : mProviders) { + try { + provider.logFile(file); + } catch (Throwable excp) { + logFailedEventJSON(file.getAbsolutePath(), excp); + } + } + return true; + } + + @Override + public void start() { + for (AuditHandler provider : mProviders) { + try { + provider.start(); + } catch (Throwable excp) { + LOG.error("MultiDestAuditProvider.start(): failed for provider { " + + provider.getClass().getName() + " }", excp); + } + } + } + + @Override + public void stop() { + for (AuditHandler provider : mProviders) { + try { + provider.stop(); + } catch (Throwable excp) { + LOG.error("MultiDestAuditProvider.stop(): failed for provider { " + + provider.getClass().getName() + " }", excp); + } + } + } + + @Override + public void waitToComplete() { + for (AuditHandler provider : mProviders) { + try { + provider.waitToComplete(); + } catch (Throwable excp) { + LOG.error( + "MultiDestAuditProvider.waitToComplete(): failed for provider { " + + provider.getClass().getName() + " }", excp); + } + } + } + + @Override + public void waitToComplete(long timeout) { + for (AuditHandler provider : mProviders) { + try { + provider.waitToComplete(timeout); + } catch (Throwable excp) { + LOG.error( + "MultiDestAuditProvider.waitToComplete(): failed for provider { " + + provider.getClass().getName() + " }", excp); + } + } + } + + @Override + public void flush() { + for (AuditHandler provider : mProviders) { + try { + provider.flush(); + } catch (Throwable excp) { + LOG.error("MultiDestAuditProvider.flush(): failed for provider { " + + provider.getClass().getName() + " }", excp); + } + } + } +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditAsyncQueue.java b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditAsyncQueue.java new file mode 100644 index 00000000000..b807f57be57 --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditAsyncQueue.java @@ -0,0 +1,186 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.queue; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +//import org.apache.log4j.MDC; +import org.apache.atlas.audit.model.AuditEventBase; +import org.apache.atlas.audit.provider.AuditHandler; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.concurrent.LinkedBlockingQueue; + +/** + * This is a non-blocking queue with no limit on capacity. + */ +public class AuditAsyncQueue extends AuditQueue implements Runnable { + private static final Log logger = LogFactory.getLog(AuditAsyncQueue.class); + + LinkedBlockingQueue queue = new LinkedBlockingQueue(); + Thread consumerThread = null; + + static final int MAX_DRAIN = 1000; + static int threadCount = 0; + static final String DEFAULT_NAME = "async"; + + public AuditAsyncQueue(AuditHandler consumer) { + super(consumer); + setName(DEFAULT_NAME); + } + + /* + * (non-Javadoc) + * + * @see + * org.apache.ranger.audit.provider.AuditProvider#log(org.apache.ranger. + * audit.model.AuditEventBase) + */ + @Override + public boolean log(AuditEventBase event) { + // Add to the queue and return ASAP + if (queue.size() >= getMaxQueueSize()) { + return false; + } + queue.add(event); + return true; + } + + @Override + public boolean log(Collection events) { + boolean ret = true; + for (AuditEventBase event : events) { + ret = log(event); + if (!ret) { + break; + } + } + return ret; + } + + /* + * (non-Javadoc) + * + * @see org.apache.ranger.audit.provider.AuditProvider#start() + */ + @Override + public void start() { + if (consumer != null) { + consumer.start(); + } else { + logger.error("consumer is not set. Nothing will be sent to any consumer. name=" + + getName()); + } + + consumerThread = new Thread(this, this.getClass().getName() + + (threadCount++)); + consumerThread.setDaemon(true); + consumerThread.start(); + } + + /* + * (non-Javadoc) + * + * @see org.apache.ranger.audit.provider.AuditProvider#stop() + */ + @Override + public void stop() { + logger.info("Stop called. name=" + getName()); + setDrain(true); + try { + if (consumerThread != null) { + logger.info("Interrupting consumerThread. name=" + getName() + + ", consumer=" + + (consumer == null ? null : consumer.getName())); + consumerThread.interrupt(); + } + } catch (Throwable t) { + // ignore any exception + } + consumerThread = null; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + try { + //This is done to clear the MDC context to avoid issue with Ranger Auditing for Knox + //MDC.clear(); + runLogAudit(); + } catch (Throwable t) { + logger.fatal("Exited thread abnormaly. queue=" + getName(), t); + } + } + + public void runLogAudit() { + while (true) { + try { + AuditEventBase event = null; + if (!isDrain()) { + // For Transfer queue take() is blocking + event = queue.take(); + } else { + // For Transfer queue poll() is non blocking + event = queue.poll(); + } + if (event != null) { + Collection eventList = new ArrayList(); + eventList.add(event); + queue.drainTo(eventList, MAX_DRAIN - 1); + consumer.log(eventList); + } + } catch (InterruptedException e) { + logger.info("Caught exception in consumer thread. Shutdown might be in progress"); + } catch (Throwable t) { + logger.error("Caught error during processing request.", t); + } + if (isDrain()) { + if (queue.isEmpty()) { + break; + } + if (isDrainMaxTimeElapsed()) { + logger.warn("Exiting polling loop because max time allowed reached. name=" + + getName() + + ", waited for " + + (stopTime - System.currentTimeMillis()) + " ms"); + } + } + } + logger.info("Exiting polling loop. name=" + getName()); + + try { + // Call stop on the consumer + logger.info("Calling to stop consumer. name=" + getName() + + ", consumer.name=" + consumer.getName()); + + // Call stop on the consumer + consumer.stop(); + } catch (Throwable t) { + logger.error("Error while calling stop on consumer.", t); + } + logger.info("Exiting consumerThread.run() method. name=" + getName()); + } + +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditBatchQueue.java b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditBatchQueue.java new file mode 100644 index 00000000000..b990188675f --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditBatchQueue.java @@ -0,0 +1,364 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.queue; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +//import org.apache.log4j.MDC; +import org.apache.atlas.audit.model.AuditEventBase; +import org.apache.atlas.audit.provider.AuditHandler; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Properties; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; + +public class AuditBatchQueue extends AuditQueue implements Runnable { + private static final Log logger = LogFactory.getLog(AuditBatchQueue.class); + + private BlockingQueue queue = null; + private Collection localBatchBuffer = new ArrayList(); + + Thread consumerThread = null; + static int threadCount = 0; + static final String DEFAULT_NAME = "batch"; + + public AuditBatchQueue(AuditHandler consumer) { + super(consumer); + setName(DEFAULT_NAME); + } + + /* + * (non-Javadoc) + * + * @see + * org.apache.ranger.audit.provider.AuditProvider#log(org.apache.ranger. + * audit.model.AuditEventBase) + */ + @Override + public boolean log(AuditEventBase event) { + // Add to batchQueue. Block if full + queue.add(event); + return true; + } + + @Override + public boolean log(Collection events) { + boolean ret = true; + for (AuditEventBase event : events) { + ret = log(event); + if (!ret) { + break; + } + } + return ret; + } + + @Override + public void init(Properties prop, String basePropertyName) { + String propPrefix = "xasecure.audit.batch"; + if (basePropertyName != null) { + propPrefix = basePropertyName; + } + + super.init(prop, propPrefix); + + } + + /* + * (non-Javadoc) + * + * @see org.apache.ranger.audit.provider.AuditProvider#start() + */ + @Override + synchronized public void start() { + if (consumerThread != null) { + logger.error("Provider is already started. name=" + getName()); + return; + } + logger.info("Creating ArrayBlockingQueue with maxSize=" + + getMaxQueueSize()); + queue = new ArrayBlockingQueue(getMaxQueueSize()); + + // Start the consumer first + consumer.start(); + + // Then the FileSpooler + if (fileSpoolerEnabled) { + fileSpooler.start(); + } + + // Finally the queue listener + consumerThread = new Thread(this, this.getClass().getName() + + (threadCount++)); + consumerThread.setDaemon(true); + consumerThread.start(); + + } + + /* + * (non-Javadoc) + * + * @see org.apache.ranger.audit.provider.AuditProvider#stop() + */ + @Override + public void stop() { + logger.info("Stop called. name=" + getName()); + setDrain(true); + flush(); + try { + if (consumerThread != null) { + logger.info("Interrupting consumerThread. name=" + getName() + + ", consumer=" + + (consumer == null ? null : consumer.getName())); + + consumerThread.interrupt(); + } + } catch (Throwable t) { + // ignore any exception + } + consumerThread = null; + } + + /* + * (non-Javadoc) + * + * @see org.apache.ranger.audit.provider.AuditProvider#waitToComplete() + */ + @Override + public void waitToComplete() { + int defaultTimeOut = -1; + waitToComplete(defaultTimeOut); + consumer.waitToComplete(defaultTimeOut); + } + + @Override + public void waitToComplete(long timeout) { + setDrain(true); + flush(); + long sleepTime = 1000; + long startTime = System.currentTimeMillis(); + int prevQueueSize = -1; + int staticLoopCount = 0; + while ((queue.size() > 0 || localBatchBuffer.size() > 0)) { + if (prevQueueSize == queue.size()) { + logger.error("Queue size is not changing. " + getName() + + ".size=" + queue.size()); + staticLoopCount++; + if (staticLoopCount > 5) { + logger.error("Aborting writing to consumer. Some logs will be discarded." + + getName() + ".size=" + queue.size()); + break; + } + } else { + staticLoopCount = 0; + prevQueueSize = queue.size(); + } + if (consumerThread != null) { + consumerThread.interrupt(); + } + try { + Thread.sleep(sleepTime); + if (timeout > 0 + && (System.currentTimeMillis() - startTime > timeout)) { + break; + } + } catch (InterruptedException e) { + break; + } + } + consumer.waitToComplete(timeout); + } + + /* + * (non-Javadoc) + * + * @see org.apache.ranger.audit.provider.AuditProvider#flush() + */ + @Override + public void flush() { + if (fileSpoolerEnabled) { + fileSpooler.flush(); + } + consumer.flush(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + try { + //This is done to clear the MDC context to avoid issue with Ranger Auditing for Knox + //MDC.clear(); + runLogAudit(); + } catch (Throwable t) { + logger.fatal("Exited thread abnormaly. queue=" + getName(), t); + } + } + + public void runLogAudit() { + long lastDispatchTime = System.currentTimeMillis(); + boolean isDestActive = true; + while (true) { + logStatusIfRequired(); + + // Time to next dispatch + long nextDispatchDuration = lastDispatchTime + - System.currentTimeMillis() + getMaxBatchInterval(); + + boolean isToSpool = false; + boolean fileSpoolDrain = false; + try { + if (fileSpoolerEnabled && fileSpooler.isPending()) { + int percentUsed = queue.size() * 100 + / getMaxQueueSize(); + long lastAttemptDelta = fileSpooler + .getLastAttemptTimeDelta(); + + fileSpoolDrain = lastAttemptDelta > fileSpoolMaxWaitTime; + // If we should even read from queue? + if (!isDrain() && !fileSpoolDrain + && percentUsed < fileSpoolDrainThresholdPercent) { + // Since some files are still under progress and it is + // not in drain mode, lets wait and retry + if (nextDispatchDuration > 0) { + Thread.sleep(nextDispatchDuration); + } + lastDispatchTime = System.currentTimeMillis(); + continue; + } + isToSpool = true; + } + + AuditEventBase event = null; + + if (!isToSpool && !isDrain() && !fileSpoolDrain + && nextDispatchDuration > 0) { + event = queue.poll(nextDispatchDuration, + TimeUnit.MILLISECONDS); + } else { + // For poll() is non blocking + event = queue.poll(); + } + + if (event != null) { + localBatchBuffer.add(event); + if (getMaxBatchSize() >= localBatchBuffer.size()) { + queue.drainTo(localBatchBuffer, getMaxBatchSize() + - localBatchBuffer.size()); + } + } else { + // poll returned due to timeout, so reseting clock + nextDispatchDuration = lastDispatchTime + - System.currentTimeMillis() + + getMaxBatchInterval(); + + lastDispatchTime = System.currentTimeMillis(); + } + } catch (InterruptedException e) { + logger.info("Caught exception in consumer thread. Shutdown might be in progress"); + setDrain(true); + } catch (Throwable t) { + logger.error("Caught error during processing request.", t); + } + + addTotalCount(localBatchBuffer.size()); + if (localBatchBuffer.size() > 0 && isToSpool) { + // Let spool to the file directly + if (isDestActive) { + logger.info("Switching to file spool. Queue=" + getName() + + ", dest=" + consumer.getName()); + } + isDestActive = false; + // Just before stashing + lastDispatchTime = System.currentTimeMillis(); + fileSpooler.stashLogs(localBatchBuffer); + addStashedCount(localBatchBuffer.size()); + localBatchBuffer.clear(); + } else if (localBatchBuffer.size() > 0 + && (isDrain() + || localBatchBuffer.size() >= getMaxBatchSize() || nextDispatchDuration <= 0)) { + if (fileSpoolerEnabled && !isDestActive) { + logger.info("Switching to writing to destination. Queue=" + + getName() + ", dest=" + consumer.getName()); + } + // Reset time just before sending the logs + lastDispatchTime = System.currentTimeMillis(); + boolean ret = consumer.log(localBatchBuffer); + if (!ret) { + if (fileSpoolerEnabled) { + logger.info("Switching to file spool. Queue=" + + getName() + ", dest=" + consumer.getName()); + // Transient error. Stash and move on + fileSpooler.stashLogs(localBatchBuffer); + isDestActive = false; + addStashedCount(localBatchBuffer.size()); + } else { + // We need to drop this event + addFailedCount(localBatchBuffer.size()); + logFailedEvent(localBatchBuffer); + } + } else { + isDestActive = true; + addSuccessCount(localBatchBuffer.size()); + } + localBatchBuffer.clear(); + } + + if (isDrain()) { + if (!queue.isEmpty() || localBatchBuffer.size() > 0) { + logger.info("Queue is not empty. Will retry. queue.size)=" + + queue.size() + ", localBatchBuffer.size()=" + + localBatchBuffer.size()); + } else { + break; + } + if (isDrainMaxTimeElapsed()) { + logger.warn("Exiting polling loop because max time allowed reached. name=" + + getName() + + ", waited for " + + (stopTime - System.currentTimeMillis()) + " ms"); + } + } + } + + logger.info("Exiting consumerThread. Queue=" + getName() + ", dest=" + + consumer.getName()); + try { + // Call stop on the consumer + logger.info("Calling to stop consumer. name=" + getName() + + ", consumer.name=" + consumer.getName()); + + consumer.stop(); + if (fileSpoolerEnabled) { + fileSpooler.stop(); + } + } catch (Throwable t) { + logger.error("Error while calling stop on consumer.", t); + } + logStatus(); + logger.info("Exiting consumerThread.run() method. name=" + getName()); + } +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditFileCacheProviderSpool.java b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditFileCacheProviderSpool.java new file mode 100644 index 00000000000..2107987a034 --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditFileCacheProviderSpool.java @@ -0,0 +1,935 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.queue; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.atlas.audit.utils.AuthObjectUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +//import org.apache.log4j.MDC; +import org.apache.atlas.audit.model.AuditEventBase; +import org.apache.atlas.audit.model.AuthzAuditEvent; +import org.apache.atlas.audit.provider.AuditHandler; +import org.apache.atlas.audit.provider.MiscUtil; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +/** + * This class temporarily stores logs in Local file system before it despatches each logs in file to the AuditBatchQueue Consumer. + * This gets instantiated only when AuditFileCacheProvider is enabled (xasecure.audit.provider.filecache.is.enabled). + * When AuditFileCacheProvider is all the logs are stored in local file system before sent to destination. + */ + +public class AuditFileCacheProviderSpool implements Runnable { + private static final Log logger = LogFactory.getLog(AuditFileCacheProviderSpool.class); + + public enum SPOOL_FILE_STATUS { + pending, write_inprogress, read_inprogress, done + } + + public static final String PROP_FILE_SPOOL_LOCAL_DIR = "filespool.dir"; + public static final String PROP_FILE_SPOOL_LOCAL_FILE_NAME = "filespool.filename.format"; + public static final String PROP_FILE_SPOOL_ARCHIVE_DIR = "filespool.archive.dir"; + public static final String PROP_FILE_SPOOL_ARCHIVE_MAX_FILES_COUNT = "filespool.archive.max.files"; + public static final String PROP_FILE_SPOOL_FILENAME_PREFIX = "filespool.file.prefix"; + public static final String PROP_FILE_SPOOL_FILE_ROLLOVER = "filespool.file.rollover.sec"; + public static final String PROP_FILE_SPOOL_INDEX_FILE = "filespool.index.filename"; + public static final String PROP_FILE_SPOOL_DEST_RETRY_MS = "filespool.destination.retry.ms"; + public static final String PROP_FILE_SPOOL_BATCH_SIZE = "filespool.buffer.size"; + + public static final String AUDIT_IS_FILE_CACHE_PROVIDER_ENABLE_PROP = "xasecure.audit.provider.filecache.is.enabled"; + public static final String FILE_CACHE_PROVIDER_NAME = "AuditFileCacheProviderSpool"; + + AuditHandler consumerProvider = null; + + BlockingQueue indexQueue = new LinkedBlockingQueue(); + List indexRecords = new ArrayList(); + + // Folder and File attributes + File logFolder = null; + String logFileNameFormat = null; + File archiveFolder = null; + String fileNamePrefix = null; + String indexFileName = null; + File indexFile = null; + String indexDoneFileName = null; + File indexDoneFile = null; + int retryDestinationMS = 30 * 1000; // Default 30 seconds + int fileRolloverSec = 24 * 60 * 60; // In seconds + int maxArchiveFiles = 100; + int errorLogIntervalMS = 30 * 1000; // Every 30 seconds + int auditBatchSize = 1000; + long lastErrorLogMS = 0; + boolean isAuditFileCacheProviderEnabled = false; + boolean closeFile = false; + boolean isPending = false; + long lastAttemptTime = 0; + boolean initDone = false; + + PrintWriter logWriter = null; + AuditIndexRecord currentWriterIndexRecord = null; + AuditIndexRecord currentConsumerIndexRecord = null; + + BufferedReader logReader = null; + Thread destinationThread = null; + + boolean isWriting = true; + boolean isDrain = false; + boolean isDestDown = false; + boolean isSpoolingSuccessful = true; + + public AuditFileCacheProviderSpool(AuditHandler consumerProvider) { + this.consumerProvider = consumerProvider; + } + + public void init(Properties prop) { + init(prop, null); + } + + public boolean init(Properties props, String basePropertyName) { + logger.debug("==> AuditFileCacheProviderSpool.init()"); + + if (initDone) { + logger.error("init() called more than once. queueProvider=" + + "" + ", consumerProvider=" + + consumerProvider.getName()); + return true; + } + String propPrefix = "xasecure.audit.filespool"; + if (basePropertyName != null) { + propPrefix = basePropertyName; + } + + try { + // Initial folder and file properties + String logFolderProp = MiscUtil.getStringProperty(props, propPrefix + + "." + PROP_FILE_SPOOL_LOCAL_DIR); + logFileNameFormat = MiscUtil.getStringProperty(props, + basePropertyName + "." + PROP_FILE_SPOOL_LOCAL_FILE_NAME); + String archiveFolderProp = MiscUtil.getStringProperty(props, + propPrefix + "." + PROP_FILE_SPOOL_ARCHIVE_DIR); + fileNamePrefix = MiscUtil.getStringProperty(props, propPrefix + "." + + PROP_FILE_SPOOL_FILENAME_PREFIX); + indexFileName = MiscUtil.getStringProperty(props, propPrefix + "." + + PROP_FILE_SPOOL_INDEX_FILE); + retryDestinationMS = MiscUtil.getIntProperty(props, propPrefix + + "." + PROP_FILE_SPOOL_DEST_RETRY_MS, retryDestinationMS); + fileRolloverSec = MiscUtil.getIntProperty(props, propPrefix + "." + + PROP_FILE_SPOOL_FILE_ROLLOVER, fileRolloverSec); + maxArchiveFiles = MiscUtil.getIntProperty(props, propPrefix + "." + + PROP_FILE_SPOOL_ARCHIVE_MAX_FILES_COUNT, maxArchiveFiles); + isAuditFileCacheProviderEnabled = MiscUtil.getBooleanProperty(props, AUDIT_IS_FILE_CACHE_PROVIDER_ENABLE_PROP, false); + logger.info("retryDestinationMS=" + retryDestinationMS + + ", queueName=" + FILE_CACHE_PROVIDER_NAME); + logger.info("fileRolloverSec=" + fileRolloverSec + ", queueName=" + + FILE_CACHE_PROVIDER_NAME); + logger.info("maxArchiveFiles=" + maxArchiveFiles + ", queueName=" + + FILE_CACHE_PROVIDER_NAME); + + if (logFolderProp == null || logFolderProp.isEmpty()) { + logger.fatal("Audit spool folder is not configured. Please set " + + propPrefix + + "." + + PROP_FILE_SPOOL_LOCAL_DIR + + ". queueName=" + FILE_CACHE_PROVIDER_NAME); + return false; + } + logFolder = new File(logFolderProp); + if (!logFolder.isDirectory()) { + boolean result = logFolder.mkdirs(); + if (!logFolder.isDirectory() || !result) { + logger.fatal("File Spool folder not found and can't be created. folder=" + + logFolder.getAbsolutePath() + + ", queueName=" + + FILE_CACHE_PROVIDER_NAME); + return false; + } + } + logger.info("logFolder=" + logFolder + ", queueName=" + + FILE_CACHE_PROVIDER_NAME); + + if (logFileNameFormat == null || logFileNameFormat.isEmpty()) { + logFileNameFormat = "spool_" + "%app-type%" + "_" + + "%time:yyyyMMdd-HHmm.ss%.log"; + } + logger.info("logFileNameFormat=" + logFileNameFormat + + ", queueName=" + FILE_CACHE_PROVIDER_NAME); + + if (archiveFolderProp == null || archiveFolderProp.isEmpty()) { + archiveFolder = new File(logFolder, "archive"); + } else { + archiveFolder = new File(archiveFolderProp); + } + if (!archiveFolder.isDirectory()) { + boolean result = archiveFolder.mkdirs(); + if (!archiveFolder.isDirectory() || !result) { + logger.error("File Spool archive folder not found and can't be created. folder=" + + archiveFolder.getAbsolutePath() + + ", queueName=" + + FILE_CACHE_PROVIDER_NAME); + return false; + } + } + logger.info("archiveFolder=" + archiveFolder + ", queueName=" + + FILE_CACHE_PROVIDER_NAME); + + if (indexFileName == null || indexFileName.isEmpty()) { + if (fileNamePrefix == null || fileNamePrefix.isEmpty()) { + fileNamePrefix = FILE_CACHE_PROVIDER_NAME + "_" + + consumerProvider.getName(); + } + indexFileName = "index_" + fileNamePrefix + "_" + "%app-type%" + + ".json"; + indexFileName = MiscUtil.replaceTokens(indexFileName, + System.currentTimeMillis()); + } + + indexFile = new File(logFolder, indexFileName); + if (!indexFile.exists()) { + boolean ret = indexFile.createNewFile(); + if (!ret) { + logger.fatal("Error creating index file. fileName=" + + indexFile.getPath()); + return false; + } + } + logger.info("indexFile=" + indexFile + ", queueName=" + + FILE_CACHE_PROVIDER_NAME); + + int lastDot = indexFileName.lastIndexOf('.'); + if (lastDot < 0) { + lastDot = indexFileName.length() - 1; + } + indexDoneFileName = indexFileName.substring(0, lastDot) + + "_closed.json"; + indexDoneFile = new File(logFolder, indexDoneFileName); + if (!indexDoneFile.exists()) { + boolean ret = indexDoneFile.createNewFile(); + if (!ret) { + logger.fatal("Error creating index done file. fileName=" + + indexDoneFile.getPath()); + return false; + } + } + logger.info("indexDoneFile=" + indexDoneFile + ", queueName=" + + FILE_CACHE_PROVIDER_NAME); + + // Load index file + loadIndexFile(); + for (AuditIndexRecord auditIndexRecord : indexRecords) { + if (!auditIndexRecord.status.equals(SPOOL_FILE_STATUS.done)) { + isPending = true; + } + if (auditIndexRecord.status + .equals(SPOOL_FILE_STATUS.write_inprogress)) { + currentWriterIndexRecord = auditIndexRecord; + logger.info("currentWriterIndexRecord=" + + currentWriterIndexRecord.filePath + + ", queueName=" + FILE_CACHE_PROVIDER_NAME); + } + if (auditIndexRecord.status + .equals(SPOOL_FILE_STATUS.read_inprogress)) { + indexQueue.add(auditIndexRecord); + } + } + printIndex(); + for (int i = 0; i < indexRecords.size(); i++) { + AuditIndexRecord auditIndexRecord = indexRecords.get(i); + if (auditIndexRecord.status.equals(SPOOL_FILE_STATUS.pending)) { + File consumerFile = new File(auditIndexRecord.filePath); + if (!consumerFile.exists()) { + logger.error("INIT: Consumer file=" + + consumerFile.getPath() + " not found."); + } else { + indexQueue.add(auditIndexRecord); + } + } + } + + } catch (Throwable t) { + logger.fatal("Error initializing File Spooler. queue=" + + FILE_CACHE_PROVIDER_NAME, t); + return false; + } + + auditBatchSize = MiscUtil.getIntProperty(props, propPrefix + + "." + PROP_FILE_SPOOL_BATCH_SIZE, auditBatchSize); + + initDone = true; + + logger.debug("<== AuditFileCacheProviderSpool.init()"); + return true; + } + + /** + * Start looking for outstanding logs and update status according. + */ + public void start() { + if (!initDone) { + logger.error("Cannot start Audit File Spooler. Initilization not done yet. queueName=" + + FILE_CACHE_PROVIDER_NAME); + return; + } + + logger.info("Starting writerThread, queueName=" + + FILE_CACHE_PROVIDER_NAME + ", consumer=" + + consumerProvider.getName()); + + // Let's start the thread to read + destinationThread = new Thread(this, FILE_CACHE_PROVIDER_NAME + "_" + + consumerProvider.getName() + "_destWriter"); + destinationThread.setDaemon(true); + destinationThread.start(); + } + + public void stop() { + if (!initDone) { + logger.error("Cannot stop Audit File Spooler. Initilization not done. queueName=" + + FILE_CACHE_PROVIDER_NAME); + return; + } + logger.info("Stop called, queueName=" + FILE_CACHE_PROVIDER_NAME + + ", consumer=" + consumerProvider.getName()); + + isDrain = true; + flush(); + + PrintWriter out = getOpenLogFileStream(); + if (out != null) { + // If write is still going on, then let's give it enough time to + // complete + for (int i = 0; i < 3; i++) { + if (isWriting) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // ignore + } + continue; + } + try { + logger.info("Closing open file, queueName=" + + FILE_CACHE_PROVIDER_NAME + ", consumer=" + + consumerProvider.getName()); + + out.flush(); + out.close(); + break; + } catch (Throwable t) { + logger.debug("Error closing spool out file.", t); + } + } + } + try { + if (destinationThread != null) { + destinationThread.interrupt(); + } + destinationThread = null; + } catch (Throwable e) { + // ignore + } + } + + public void flush() { + if (!initDone) { + logger.error("Cannot flush Audit File Spooler. Initilization not done. queueName=" + + FILE_CACHE_PROVIDER_NAME); + return; + } + PrintWriter out = getOpenLogFileStream(); + if (out != null) { + out.flush(); + } + } + + /** + * If any files are still not processed. Also, if the destination is not + * reachable + * + * @return + */ + public boolean isPending() { + if (!initDone) { + logError("isPending(): File Spooler not initialized. queueName=" + + FILE_CACHE_PROVIDER_NAME); + return false; + } + + return isPending; + } + + /** + * Milliseconds from last attempt time + * + * @return + */ + public long getLastAttemptTimeDelta() { + if (lastAttemptTime == 0) { + return 0; + } + return System.currentTimeMillis() - lastAttemptTime; + } + + synchronized public void stashLogs(AuditEventBase event) { + + if (isDrain) { + // Stop has been called, so this method shouldn't be called + logger.error("stashLogs() is called after stop is called. event=" + + event); + return; + } + try { + isWriting = true; + PrintWriter logOut = getLogFileStream(); + // Convert event to json + String jsonStr = MiscUtil.stringify(event); + logOut.println(jsonStr); + logOut.flush(); + isPending = true; + isSpoolingSuccessful = true; + } catch (Throwable t) { + isSpoolingSuccessful = false; + logger.error("Error writing to file. event=" + event, t); + } finally { + isWriting = false; + } + + } + + synchronized public void stashLogs(Collection events) { + for (AuditEventBase event : events) { + stashLogs(event); + } + flush(); + } + + synchronized public void stashLogsString(String event) { + if (isDrain) { + // Stop has been called, so this method shouldn't be called + logger.error("stashLogs() is called after stop is called. event=" + + event); + return; + } + try { + isWriting = true; + PrintWriter logOut = getLogFileStream(); + logOut.println(event); + } catch (Exception ex) { + logger.error("Error writing to file. event=" + event, ex); + } finally { + isWriting = false; + } + + } + + synchronized public boolean isSpoolingSuccessful() { + return isSpoolingSuccessful; + } + + synchronized public void stashLogsString(Collection events) { + for (String event : events) { + stashLogsString(event); + } + flush(); + } + + /** + * This return the current file. If there are not current open output file, + * then it will return null + * + * @return + * @throws Exception + */ + synchronized private PrintWriter getOpenLogFileStream() { + return logWriter; + } + + /** + * @return + * @throws Exception + */ + synchronized private PrintWriter getLogFileStream() throws Exception { + closeFileIfNeeded(); + // Either there are no open log file or the previous one has been rolled + // over + if (currentWriterIndexRecord == null) { + Date currentTime = new Date(); + // Create a new file + String fileName = MiscUtil.replaceTokens(logFileNameFormat, + currentTime.getTime()); + String newFileName = fileName; + File outLogFile = null; + int i = 0; + while (true) { + outLogFile = new File(logFolder, newFileName); + File archiveLogFile = new File(archiveFolder, newFileName); + if (!outLogFile.exists() && !archiveLogFile.exists()) { + break; + } + i++; + int lastDot = fileName.lastIndexOf('.'); + String baseName = fileName.substring(0, lastDot); + String extension = fileName.substring(lastDot); + newFileName = baseName + "." + i + extension; + } + fileName = newFileName; + logger.info("Creating new file. queueName=" + + FILE_CACHE_PROVIDER_NAME + ", fileName=" + fileName); + // Open the file + logWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream( + outLogFile),"UTF-8"))); + + AuditIndexRecord tmpIndexRecord = new AuditIndexRecord(); + + tmpIndexRecord.id = MiscUtil.generateUniqueId(); + tmpIndexRecord.filePath = outLogFile.getPath(); + tmpIndexRecord.status = SPOOL_FILE_STATUS.write_inprogress; + tmpIndexRecord.fileCreateTime = currentTime; + tmpIndexRecord.lastAttempt = true; + currentWriterIndexRecord = tmpIndexRecord; + indexRecords.add(currentWriterIndexRecord); + saveIndexFile(); + + } else { + if (logWriter == null) { + // This means the process just started. We need to open the file + // in append mode. + logger.info("Opening existing file for append. queueName=" + + FILE_CACHE_PROVIDER_NAME + ", fileName=" + + currentWriterIndexRecord.filePath); + logWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream( + currentWriterIndexRecord.filePath, true),"UTF-8"))); + } + } + return logWriter; + } + + synchronized private void closeFileIfNeeded() throws FileNotFoundException, + IOException { + // Is there file open to write or there are no pending file, then close + // the active file + if (currentWriterIndexRecord != null) { + // Check whether the file needs to rolled + rollOverSpoolFileByTime(); + + if (closeFile) { + // Roll the file + if (logWriter != null) { + logWriter.flush(); + logWriter.close(); + logWriter = null; + closeFile = false; + } + currentWriterIndexRecord.status = SPOOL_FILE_STATUS.pending; + currentWriterIndexRecord.writeCompleteTime = new Date(); + saveIndexFile(); + logger.info("Adding file to queue. queueName=" + + FILE_CACHE_PROVIDER_NAME + ", fileName=" + + currentWriterIndexRecord.filePath); + indexQueue.add(currentWriterIndexRecord); + currentWriterIndexRecord = null; + } + } + } + + private void rollOverSpoolFileByTime() { + if (System.currentTimeMillis() + - currentWriterIndexRecord.fileCreateTime.getTime() > fileRolloverSec * 1000) { + closeFile = true; + logger.info("Closing file. Rolling over. queueName=" + + FILE_CACHE_PROVIDER_NAME + ", fileName=" + + currentWriterIndexRecord.filePath); + } + } + + /** + * Load the index file + * + * @throws IOException + */ + void loadIndexFile() throws IOException { + logger.info("Loading index file. fileName=" + indexFile.getPath()); + BufferedReader br = null; + try { + br = new BufferedReader(new InputStreamReader(new FileInputStream(indexFile), "UTF-8")); + indexRecords.clear(); + String line; + while ((line = br.readLine()) != null) { + if (!line.isEmpty() && !line.startsWith("#")) { + AuditIndexRecord record = AuthObjectUtil.fromJson(line, AuditIndexRecord.class); + indexRecords.add(record); + } + } + } finally { + if (br!= null) { + br.close(); + } + } + } + + synchronized void printIndex() { + logger.info("INDEX printIndex() ==== START"); + Iterator iter = indexRecords.iterator(); + while (iter.hasNext()) { + AuditIndexRecord record = iter.next(); + logger.info("INDEX=" + record + ", isFileExist=" + + (new File(record.filePath).exists())); + } + logger.info("INDEX printIndex() ==== END"); + } + + synchronized void removeIndexRecord(AuditIndexRecord indexRecord) + throws FileNotFoundException, IOException { + Iterator iter = indexRecords.iterator(); + while (iter.hasNext()) { + AuditIndexRecord record = iter.next(); + if (record.id.equals(indexRecord.id)) { + logger.info("Removing file from index. file=" + record.filePath + + ", queueName=" + FILE_CACHE_PROVIDER_NAME + + ", consumer=" + consumerProvider.getName()); + + iter.remove(); + appendToDoneFile(record); + } + } + saveIndexFile(); + // If there are no more files in the index, then let's assume the + // destination is now available + if (indexRecords.size() == 0) { + isPending = false; + } + } + + synchronized void saveIndexFile() throws FileNotFoundException, IOException { + PrintWriter out = new PrintWriter(indexFile,"UTF-8"); + for (AuditIndexRecord auditIndexRecord : indexRecords) { + out.println(AuthObjectUtil.toJson(auditIndexRecord)); + } + out.close(); + // printIndex(); + + } + + void appendToDoneFile(AuditIndexRecord indexRecord) + throws FileNotFoundException, IOException { + logger.info("Moving to done file. " + indexRecord.filePath + + ", queueName=" + FILE_CACHE_PROVIDER_NAME + ", consumer=" + + consumerProvider.getName()); + String line = AuthObjectUtil.toJson(indexRecord); + PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream( + indexDoneFile, true),"UTF-8"))); + out.println(line); + out.flush(); + out.close(); + + // After Each file is read and audit events are pushed into pipe, we flush to reach the destination immediate. + consumerProvider.flush(); + + // Move to archive folder + File logFile = null; + File archiveFile = null; + try { + logFile = new File(indexRecord.filePath); + String fileName = logFile.getName(); + archiveFile = new File(archiveFolder, fileName); + logger.info("Moving logFile " + logFile + " to " + archiveFile); + boolean result = logFile.renameTo(archiveFile); + if (!result) { + logger.error("Error moving log file to archive folder. Unable to rename" + + logFile + " to archiveFile=" + archiveFile); + } + } catch (Throwable t) { + logger.error("Error moving log file to archive folder. logFile=" + + logFile + ", archiveFile=" + archiveFile, t); + } + + // After archiving the file flush the pipe + consumerProvider.flush(); + + archiveFile = null; + try { + // Remove old files + File[] logFiles = archiveFolder.listFiles(new FileFilter() { + public boolean accept(File pathname) { + return pathname.getName().toLowerCase().endsWith(".log"); + } + }); + + if (logFiles != null && logFiles.length > maxArchiveFiles) { + int filesToDelete = logFiles.length - maxArchiveFiles; + BufferedReader br = new BufferedReader(new FileReader( + indexDoneFile)); + try { + int filesDeletedCount = 0; + while ((line = br.readLine()) != null) { + if (!line.isEmpty() && !line.startsWith("#")) { + AuditIndexRecord record = AuthObjectUtil.fromJson(line, AuditIndexRecord.class); + logFile = new File(record.filePath); + String fileName = logFile.getName(); + archiveFile = new File(archiveFolder, fileName); + if (archiveFile.exists()) { + logger.info("Deleting archive file " + + archiveFile); + boolean ret = archiveFile.delete(); + if (!ret) { + logger.error("Error deleting archive file. archiveFile=" + + archiveFile); + } + filesDeletedCount++; + if (filesDeletedCount >= filesToDelete) { + logger.info("Deleted " + filesDeletedCount + + " files"); + break; + } + } + } + } + } finally { + br.close(); + } + } + } catch (Throwable t) { + logger.error("Error deleting older archive file. archiveFile=" + + archiveFile, t); + } + + } + + void logError(String msg) { + long currTimeMS = System.currentTimeMillis(); + if (currTimeMS - lastErrorLogMS > errorLogIntervalMS) { + logger.error(msg); + lastErrorLogMS = currTimeMS; + } + } + + class AuditIndexRecord { + String id; + String filePath; + int linePosition = 0; + SPOOL_FILE_STATUS status = SPOOL_FILE_STATUS.write_inprogress; + Date fileCreateTime; + Date writeCompleteTime; + Date doneCompleteTime; + Date lastSuccessTime; + Date lastFailedTime; + int failedAttemptCount = 0; + boolean lastAttempt = false; + + @Override + public String toString() { + return "AuditIndexRecord [id=" + id + ", filePath=" + filePath + + ", linePosition=" + linePosition + ", status=" + status + + ", fileCreateTime=" + fileCreateTime + + ", writeCompleteTime=" + writeCompleteTime + + ", doneCompleteTime=" + doneCompleteTime + + ", lastSuccessTime=" + lastSuccessTime + + ", lastFailedTime=" + lastFailedTime + + ", failedAttemptCount=" + failedAttemptCount + + ", lastAttempt=" + lastAttempt + "]"; + } + + } + + /* + * (non-Javadoc) + * + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + try { + //This is done to clear the MDC context to avoid issue with Ranger Auditing for Knox + //MDC.clear(); + runLogAudit(); + } catch (Throwable t) { + logger.fatal("Exited thread without abnormaly. queue=" + + consumerProvider.getName(), t); + } + } + + public void runLogAudit() { + // boolean isResumed = false; + while (true) { + try { + if (isDestDown) { + logger.info("Destination is down. sleeping for " + + retryDestinationMS + + " milli seconds. indexQueue=" + indexQueue.size() + + ", queueName=" + FILE_CACHE_PROVIDER_NAME + + ", consumer=" + consumerProvider.getName()); + Thread.sleep(retryDestinationMS); + } + // Let's pause between each iteration + if (currentConsumerIndexRecord == null) { + currentConsumerIndexRecord = indexQueue.poll( + retryDestinationMS, TimeUnit.MILLISECONDS); + } else { + Thread.sleep(retryDestinationMS); + } + + if (isDrain) { + // Need to exit + break; + } + if (currentConsumerIndexRecord == null) { + closeFileIfNeeded(); + continue; + } + + boolean isRemoveIndex = false; + File consumerFile = new File( + currentConsumerIndexRecord.filePath); + if (!consumerFile.exists()) { + logger.error("Consumer file=" + consumerFile.getPath() + + " not found."); + printIndex(); + isRemoveIndex = true; + } else { + // Let's open the file to write + BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream( + currentConsumerIndexRecord.filePath),"UTF-8")); + try { + int startLine = currentConsumerIndexRecord.linePosition; + String line; + int currLine = 0; + List events = new ArrayList<>(); + while ((line = br.readLine()) != null) { + currLine++; + if (currLine < startLine) { + continue; + } + AuditEventBase event = MiscUtil.fromJson(line, AuthzAuditEvent.class); + events.add(event); + + if (events.size() == auditBatchSize) { + boolean ret = sendEvent(events, + currentConsumerIndexRecord, currLine); + if (!ret) { + throw new Exception("Destination down"); + } + events.clear(); + } + } + if (events.size() > 0) { + boolean ret = sendEvent(events, + currentConsumerIndexRecord, currLine); + if (!ret) { + throw new Exception("Destination down"); + } + events.clear(); + } + logger.info("Done reading file. file=" + + currentConsumerIndexRecord.filePath + + ", queueName=" + FILE_CACHE_PROVIDER_NAME + + ", consumer=" + consumerProvider.getName()); + // The entire file is read + currentConsumerIndexRecord.status = SPOOL_FILE_STATUS.done; + currentConsumerIndexRecord.doneCompleteTime = new Date(); + currentConsumerIndexRecord.lastAttempt = true; + + isRemoveIndex = true; + } catch (Exception ex) { + isDestDown = true; + logError("Destination down. queueName=" + + FILE_CACHE_PROVIDER_NAME + ", consumer=" + + consumerProvider.getName()); + lastAttemptTime = System.currentTimeMillis(); + // Update the index file + currentConsumerIndexRecord.lastFailedTime = new Date(); + currentConsumerIndexRecord.failedAttemptCount++; + currentConsumerIndexRecord.lastAttempt = false; + saveIndexFile(); + } finally { + br.close(); + } + } + if (isRemoveIndex) { + // Remove this entry from index + removeIndexRecord(currentConsumerIndexRecord); + currentConsumerIndexRecord = null; + closeFileIfNeeded(); + } + } catch (InterruptedException e) { + logger.info("Caught exception in consumer thread. Shutdown might be in progress"); + } catch (Throwable t) { + logger.error("Exception in destination writing thread.", t); + } + } + logger.info("Exiting file spooler. provider=" + FILE_CACHE_PROVIDER_NAME + + ", consumer=" + consumerProvider.getName()); + } + + private boolean sendEvent(List events, AuditIndexRecord indexRecord, + int currLine) { + boolean ret = true; + try { + ret = consumerProvider.log(events); + if (!ret) { + // Need to log error after fixed interval + logError("Error sending logs to consumer. provider=" + + FILE_CACHE_PROVIDER_NAME + ", consumer=" + + consumerProvider.getName()); + } else { + // Update index and save + indexRecord.linePosition = currLine; + indexRecord.status = SPOOL_FILE_STATUS.read_inprogress; + indexRecord.lastSuccessTime = new Date(); + indexRecord.lastAttempt = true; + saveIndexFile(); + + if (isDestDown) { + isDestDown = false; + logger.info("Destination up now. " + indexRecord.filePath + + ", queueName=" + FILE_CACHE_PROVIDER_NAME + + ", consumer=" + consumerProvider.getName()); + } + } + } catch (Throwable t) { + logger.error("Error while sending logs to consumer. provider=" + + FILE_CACHE_PROVIDER_NAME + ", consumer=" + + consumerProvider.getName() + ", log=" + events, t); + } + + return ret; + } + +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditFileQueue.java b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditFileQueue.java new file mode 100644 index 00000000000..281f9df7bd1 --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditFileQueue.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.queue; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.audit.model.AuditEventBase; +import org.apache.atlas.audit.provider.AuditHandler; +import org.apache.atlas.audit.provider.BaseAuditHandler; + +import java.util.Collection; +import java.util.Properties; + +/* + AuditFileQueue class does the work of stashing the audit logs into Local Filesystem before sending it to the AuditBatchQueue Consumer +*/ + +public class AuditFileQueue extends BaseAuditHandler { + private static final Log logger = LogFactory.getLog(AuditFileQueue.class); + + AuditFileQueueSpool fileSpooler = null; + AuditHandler consumer = null; + + static final String DEFAULT_NAME = "batch"; + + public AuditFileQueue(AuditHandler consumer) { + this.consumer = consumer; + } + + public void init(Properties prop, String basePropertyName) { + String propPrefix = "xasecure.audit.batch"; + if (basePropertyName != null) { + propPrefix = basePropertyName; + } + super.init(prop, propPrefix); + + //init AuditFileQueueSpooler thread to send Local logs to destination + fileSpooler = new AuditFileQueueSpool(consumer); + fileSpooler.init(prop,propPrefix); + } + + @Override + public boolean log(AuditEventBase event) { + boolean ret = false; + if ( event != null) { + fileSpooler.stashLogs(event); + if (fileSpooler.isSpoolingSuccessful()) { + ret = true; + } + } + return ret; + } + + @Override + public boolean log(Collection events) { + boolean ret = true; + if ( events != null) { + for (AuditEventBase event : events) { + ret = log(event); + } + } + return ret; + } + + + @Override + public void start() { + // Start the consumer thread + if (consumer != null) { + consumer.start(); + } + if (fileSpooler != null) { + // start AuditFileSpool thread + fileSpooler.start(); + } + } + + @Override + public void stop() { + logger.info("Stop called. name=" + getName()); + if (consumer != null) { + consumer.stop(); + } + } + + @Override + public void waitToComplete() { + logger.info("waitToComplete called. name=" + getName()); + if ( consumer != null) { + consumer.waitToComplete(); + } + } + + @Override + public void waitToComplete(long timeout) { + logger.info("waitToComplete called. name=" + getName()); + if ( consumer != null) { + consumer.waitToComplete(timeout); + } + } + + @Override + public void flush() { + logger.info("waitToComplete. name=" + getName()); + if ( consumer != null) { + consumer.flush(); + } + } + +} \ No newline at end of file diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditFileQueueSpool.java b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditFileQueueSpool.java new file mode 100644 index 00000000000..89b93e4eb6d --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditFileQueueSpool.java @@ -0,0 +1,1010 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you 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 org.apache.atlas.audit.queue; + +import org.apache.atlas.audit.model.AuditEventBase; +import org.apache.atlas.audit.model.AuthzAuditEvent; +import org.apache.atlas.audit.provider.AuditHandler; +import org.apache.atlas.audit.provider.MiscUtil; +import org.apache.atlas.audit.utils.AuthObjectUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +/** + * This class temporarily stores logs in Local file system before it despatches each logs in file to the AuditBatchQueue Consumer. + * This gets instantiated only when AuditFileCacheProvider is enabled (xasecure.audit.provider.filecache.is.enabled). + * When AuditFileCacheProvider is enabled all the logs are stored in local file system before sent to destination. + */ + +public class AuditFileQueueSpool implements Runnable { + private static final Logger logger = LoggerFactory.getLogger(AuditFileQueueSpool.class); + + public enum SPOOL_FILE_STATUS { + pending, write_inprogress, read_inprogress, done + } + + public static final String PROP_FILE_SPOOL_LOCAL_DIR = "filespool.dir"; + public static final String PROP_FILE_SPOOL_LOCAL_FILE_NAME = "filespool.filename.format"; + public static final String PROP_FILE_SPOOL_ARCHIVE_DIR = "filespool.archive.dir"; + public static final String PROP_FILE_SPOOL_ARCHIVE_MAX_FILES_COUNT = "filespool.archive.max.files"; + public static final String PROP_FILE_SPOOL_FILENAME_PREFIX = "filespool.file.prefix"; + public static final String PROP_FILE_SPOOL_FILE_ROLLOVER = "filespool.file.rollover.sec"; + public static final String PROP_FILE_SPOOL_INDEX_FILE = "filespool.index.filename"; + public static final String PROP_FILE_SPOOL_DEST_RETRY_MS = "filespool.destination.retry.ms"; + public static final String PROP_FILE_SPOOL_BATCH_SIZE = "filespool.buffer.size"; + public static final String FILE_QUEUE_PROVIDER_NAME = "AuditFileQueueSpool"; + public static final String DEFAULT_AUDIT_FILE_TYPE = "json"; + + AuditHandler consumerProvider = null; + BlockingQueue indexQueue = new LinkedBlockingQueue(); + List indexRecords = new ArrayList(); + + // Folder and File attributes + File logFolder = null; + String logFileNameFormat = null; + File archiveFolder = null; + String fileNamePrefix = null; + String indexFileName = null; + File indexFile = null; + String indexDoneFileName = null; + String auditFileType = null; + File indexDoneFile = null; + int retryDestinationMS = 30 * 1000; // Default 30 seconds + int fileRolloverSec = 24 * 60 * 60; // In seconds + int maxArchiveFiles = 100; + int errorLogIntervalMS = 30 * 1000; // Every 30 seconds + long lastErrorLogMS = 0; + boolean isAuditFileCacheProviderEnabled = false; + boolean closeFile = false; + boolean isPending = false; + long lastAttemptTime = 0; + long bufferSize = 1000; + boolean initDone = false; + + PrintWriter logWriter = null; + AuditIndexRecord currentWriterIndexRecord = null; + AuditIndexRecord currentConsumerIndexRecord = null; + + BufferedReader logReader = null; + Thread destinationThread = null; + + boolean isWriting = true; + boolean isDrain = false; + boolean isDestDown = false; + boolean isSpoolingSuccessful = true; + + public AuditFileQueueSpool(AuditHandler consumerProvider) { + this.consumerProvider = consumerProvider; + } + + public void init(Properties prop) { + init(prop, null); + } + + public boolean init(Properties props, String basePropertyName) { + logger.debug("==> AuditFileQueueSpool.init()"); + + if (initDone) { + logger.error("init() called more than once. queueProvider=" + + "" + ", consumerProvider=" + + consumerProvider.getName()); + return true; + } + String propPrefix = "xasecure.audit.filespool"; + if (basePropertyName != null) { + propPrefix = basePropertyName; + } + + try { + // Initial folder and file properties + String logFolderProp = MiscUtil.getStringProperty(props, propPrefix + + "." + PROP_FILE_SPOOL_LOCAL_DIR); + logFileNameFormat = MiscUtil.getStringProperty(props, + basePropertyName + "." + PROP_FILE_SPOOL_LOCAL_FILE_NAME); + String archiveFolderProp = MiscUtil.getStringProperty(props, + propPrefix + "." + PROP_FILE_SPOOL_ARCHIVE_DIR); + fileNamePrefix = MiscUtil.getStringProperty(props, propPrefix + "." + + PROP_FILE_SPOOL_FILENAME_PREFIX); + indexFileName = MiscUtil.getStringProperty(props, propPrefix + "." + + PROP_FILE_SPOOL_INDEX_FILE); + retryDestinationMS = MiscUtil.getIntProperty(props, propPrefix + + "." + PROP_FILE_SPOOL_DEST_RETRY_MS, retryDestinationMS); + fileRolloverSec = MiscUtil.getIntProperty(props, propPrefix + "." + + PROP_FILE_SPOOL_FILE_ROLLOVER, fileRolloverSec); + maxArchiveFiles = MiscUtil.getIntProperty(props, propPrefix + "." + + PROP_FILE_SPOOL_ARCHIVE_MAX_FILES_COUNT, maxArchiveFiles); + logger.info("retryDestinationMS=" + retryDestinationMS + + ", queueName=" + FILE_QUEUE_PROVIDER_NAME); + logger.info("fileRolloverSec=" + fileRolloverSec + ", queueName=" + + FILE_QUEUE_PROVIDER_NAME); + logger.info("maxArchiveFiles=" + maxArchiveFiles + ", queueName=" + + FILE_QUEUE_PROVIDER_NAME); + + if (logFolderProp == null || logFolderProp.isEmpty()) { + logger.error("Audit spool folder is not configured. Please set " + + propPrefix + + "." + + PROP_FILE_SPOOL_LOCAL_DIR + + ". queueName=" + FILE_QUEUE_PROVIDER_NAME); + return false; + } + logFolder = new File(logFolderProp); + if (!logFolder.isDirectory()) { + boolean result = logFolder.mkdirs(); + if (!logFolder.isDirectory() || !result) { + logger.error("File Spool folder not found and can't be created. folder=" + + logFolder.getAbsolutePath() + + ", queueName=" + + FILE_QUEUE_PROVIDER_NAME); + return false; + } + } + logger.info("logFolder=" + logFolder + ", queueName=" + + FILE_QUEUE_PROVIDER_NAME); + + if (logFileNameFormat == null || logFileNameFormat.isEmpty()) { + logFileNameFormat = "spool_" + "%app-type%" + "_" + + "%time:yyyyMMdd-HHmm.ss%.log"; + } + logger.info("logFileNameFormat=" + logFileNameFormat + + ", queueName=" + FILE_QUEUE_PROVIDER_NAME); + + if (archiveFolderProp == null || archiveFolderProp.isEmpty()) { + archiveFolder = new File(logFolder, "archive"); + } else { + archiveFolder = new File(archiveFolderProp); + } + if (!archiveFolder.isDirectory()) { + boolean result = archiveFolder.mkdirs(); + if (!archiveFolder.isDirectory() || !result) { + logger.error("File Spool archive folder not found and can't be created. folder=" + + archiveFolder.getAbsolutePath() + + ", queueName=" + + FILE_QUEUE_PROVIDER_NAME); + return false; + } + } + logger.info("archiveFolder=" + archiveFolder + ", queueName=" + + FILE_QUEUE_PROVIDER_NAME); + + if (indexFileName == null || indexFileName.isEmpty()) { + if (fileNamePrefix == null || fileNamePrefix.isEmpty()) { + fileNamePrefix = FILE_QUEUE_PROVIDER_NAME + "_" + + consumerProvider.getName(); + } + indexFileName = "index_" + fileNamePrefix + "_" + "%app-type%" + + ".json"; + indexFileName = MiscUtil.replaceTokens(indexFileName, + System.currentTimeMillis()); + } + + indexFile = new File(logFolder, indexFileName); + if (!indexFile.exists()) { + boolean ret = indexFile.createNewFile(); + if (!ret) { + logger.error("Error creating index file. fileName=" + + indexFile.getPath()); + return false; + } + } + logger.info("indexFile=" + indexFile + ", queueName=" + + FILE_QUEUE_PROVIDER_NAME); + + int lastDot = indexFileName.lastIndexOf('.'); + if (lastDot < 0) { + lastDot = indexFileName.length() - 1; + } + indexDoneFileName = indexFileName.substring(0, lastDot) + + "_closed.json"; + indexDoneFile = new File(logFolder, indexDoneFileName); + if (!indexDoneFile.exists()) { + boolean ret = indexDoneFile.createNewFile(); + if (!ret) { + logger.error("Error creating index done file. fileName=" + + indexDoneFile.getPath()); + return false; + } + } + logger.info("indexDoneFile=" + indexDoneFile + ", queueName=" + + FILE_QUEUE_PROVIDER_NAME); + + // Load index file + loadIndexFile(); + for (AuditIndexRecord auditIndexRecord : indexRecords) { + if (!auditIndexRecord.status.equals(SPOOL_FILE_STATUS.done)) { + isPending = true; + } + if (auditIndexRecord.status + .equals(SPOOL_FILE_STATUS.write_inprogress)) { + currentWriterIndexRecord = auditIndexRecord; + logger.info("currentWriterIndexRecord=" + + currentWriterIndexRecord.filePath + + ", queueName=" + FILE_QUEUE_PROVIDER_NAME); + } + if (auditIndexRecord.status + .equals(SPOOL_FILE_STATUS.read_inprogress)) { + indexQueue.add(auditIndexRecord); + } + } + printIndex(); + for (int i = 0; i < indexRecords.size(); i++) { + AuditIndexRecord auditIndexRecord = indexRecords.get(i); + if (auditIndexRecord.status.equals(SPOOL_FILE_STATUS.pending)) { + File consumerFile = new File(auditIndexRecord.filePath); + if (!consumerFile.exists()) { + logger.error("INIT: Consumer file=" + + consumerFile.getPath() + " not found."); + } else { + indexQueue.add(auditIndexRecord); + } + } + } + + auditFileType = MiscUtil.getStringProperty(props, propPrefix + ".filetype", DEFAULT_AUDIT_FILE_TYPE); + if (auditFileType == null) { + auditFileType = DEFAULT_AUDIT_FILE_TYPE; + } + + } catch (Throwable t) { + logger.error("Error initializing File Spooler. queue=" + + FILE_QUEUE_PROVIDER_NAME, t); + return false; + } + + bufferSize = MiscUtil.getLongProperty(props, propPrefix + + "." + PROP_FILE_SPOOL_BATCH_SIZE, bufferSize); + + initDone = true; + + logger.debug("<== AuditFileQueueSpool.init()"); + return true; + } + + /** + * Start looking for outstanding logs and update status according. + */ + public void start() { + if (!initDone) { + logger.error("Cannot start Audit File Spooler. Initilization not done yet. queueName=" + + FILE_QUEUE_PROVIDER_NAME); + return; + } + + logger.info("Starting writerThread, queueName=" + + FILE_QUEUE_PROVIDER_NAME + ", consumer=" + + consumerProvider.getName()); + + // Let's start the thread to read + destinationThread = new Thread(this, FILE_QUEUE_PROVIDER_NAME + "_" + + consumerProvider.getName() + "_destWriter"); + destinationThread.setDaemon(true); + destinationThread.start(); + } + + public void stop() { + if (!initDone) { + logger.error("Cannot stop Audit File Spooler. Initilization not done. queueName=" + + FILE_QUEUE_PROVIDER_NAME); + return; + } + logger.info("Stop called, queueName=" + FILE_QUEUE_PROVIDER_NAME + + ", consumer=" + consumerProvider.getName()); + + isDrain = true; + flush(); + + PrintWriter out = getOpenLogFileStream(); + if (out != null) { + // If write is still going on, then let's give it enough time to + // complete + for (int i = 0; i < 3; i++) { + if (isWriting) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // ignore + } + continue; + } + try { + logger.info("Closing open file, queueName=" + + FILE_QUEUE_PROVIDER_NAME + ", consumer=" + + consumerProvider.getName()); + + out.flush(); + out.close(); + break; + } catch (Throwable t) { + logger.debug("Error closing spool out file.", t); + } + } + } + try { + if (destinationThread != null) { + destinationThread.interrupt(); + } + destinationThread = null; + } catch (Throwable e) { + // ignore + } + } + + public void flush() { + if (!initDone) { + logger.error("Cannot flush Audit File Spooler. Initilization not done. queueName=" + + FILE_QUEUE_PROVIDER_NAME); + return; + } + PrintWriter out = getOpenLogFileStream(); + if (out != null) { + out.flush(); + } + } + + /** + * If any files are still not processed. Also, if the destination is not + * reachable + * + * @return + */ + public boolean isPending() { + if (!initDone) { + logError("isPending(): File Spooler not initialized. queueName=" + + FILE_QUEUE_PROVIDER_NAME); + return false; + } + + return isPending; + } + + /** + * Milliseconds from last attempt time + * + * @return + */ + public long getLastAttemptTimeDelta() { + if (lastAttemptTime == 0) { + return 0; + } + return System.currentTimeMillis() - lastAttemptTime; + } + + synchronized public void stashLogs(AuditEventBase event) { + + if (isDrain) { + // Stop has been called, so this method shouldn't be called + logger.error("stashLogs() is called after stop is called. event=" + + event); + return; + } + try { + isWriting = true; + PrintWriter logOut = getLogFileStream(); + // Convert event to json + String jsonStr = MiscUtil.stringify(event); + logOut.println(jsonStr); + logOut.flush(); + isPending = true; + isSpoolingSuccessful = true; + } catch (Throwable t) { + isSpoolingSuccessful = false; + logger.error("Error writing to file. event=" + event, t); + } finally { + isWriting = false; + } + + } + + synchronized public void stashLogs(Collection events) { + for (AuditEventBase event : events) { + stashLogs(event); + } + flush(); + } + + synchronized public void stashLogsString(String event) { + if (isDrain) { + // Stop has been called, so this method shouldn't be called + logger.error("stashLogs() is called after stop is called. event=" + + event); + return; + } + try { + isWriting = true; + PrintWriter logOut = getLogFileStream(); + logOut.println(event); + } catch (Exception ex) { + logger.error("Error writing to file. event=" + event, ex); + } finally { + isWriting = false; + } + + } + + synchronized public boolean isSpoolingSuccessful() { + return isSpoolingSuccessful; + } + + synchronized public void stashLogsString(Collection events) { + for (String event : events) { + stashLogsString(event); + } + flush(); + } + + /** + * This return the current file. If there are not current open output file, + * then it will return null + * + * @return + * @throws Exception + */ + synchronized private PrintWriter getOpenLogFileStream() { + return logWriter; + } + + /** + * @return + * @throws Exception + */ + synchronized private PrintWriter getLogFileStream() throws Exception { + closeFileIfNeeded(); + // Either there are no open log file or the previous one has been rolled + // over + if (currentWriterIndexRecord == null) { + Date currentTime = new Date(); + // Create a new file + String fileName = MiscUtil.replaceTokens(logFileNameFormat, + currentTime.getTime()); + String newFileName = fileName; + File outLogFile = null; + int i = 0; + while (true) { + outLogFile = new File(logFolder, newFileName); + File archiveLogFile = new File(archiveFolder, newFileName); + if (!outLogFile.exists() && !archiveLogFile.exists()) { + break; + } + i++; + int lastDot = fileName.lastIndexOf('.'); + String baseName = fileName.substring(0, lastDot); + String extension = fileName.substring(lastDot); + newFileName = baseName + "." + i + extension; + } + fileName = newFileName; + logger.info("Creating new file. queueName=" + + FILE_QUEUE_PROVIDER_NAME + ", fileName=" + fileName); + // Open the file + logWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream( + outLogFile),"UTF-8"))); + + AuditIndexRecord tmpIndexRecord = new AuditIndexRecord(); + + tmpIndexRecord.id = MiscUtil.generateUniqueId(); + tmpIndexRecord.filePath = outLogFile.getPath(); + tmpIndexRecord.status = SPOOL_FILE_STATUS.write_inprogress; + tmpIndexRecord.fileCreateTime = currentTime; + tmpIndexRecord.lastAttempt = true; + currentWriterIndexRecord = tmpIndexRecord; + indexRecords.add(currentWriterIndexRecord); + saveIndexFile(); + + } else { + if (logWriter == null) { + // This means the process just started. We need to open the file + // in append mode. + logger.info("Opening existing file for append. queueName=" + + FILE_QUEUE_PROVIDER_NAME + ", fileName=" + + currentWriterIndexRecord.filePath); + logWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream( + currentWriterIndexRecord.filePath, true),"UTF-8"))); + } + } + return logWriter; + } + + synchronized private void closeFileIfNeeded() throws FileNotFoundException, + IOException { + // Is there file open to write or there are no pending file, then close + // the active file + if (currentWriterIndexRecord != null) { + // Check whether the file needs to rolled + rollOverSpoolFileByTime(); + + if (closeFile) { + // Roll the file + if (logWriter != null) { + logWriter.flush(); + logWriter.close(); + logWriter = null; + closeFile = false; + } + currentWriterIndexRecord.status = SPOOL_FILE_STATUS.pending; + currentWriterIndexRecord.writeCompleteTime = new Date(); + saveIndexFile(); + logger.info("Adding file to queue. queueName=" + + FILE_QUEUE_PROVIDER_NAME + ", fileName=" + + currentWriterIndexRecord.filePath); + indexQueue.add(currentWriterIndexRecord); + currentWriterIndexRecord = null; + } + } + } + + private void rollOverSpoolFileByTime() { + if (System.currentTimeMillis() + - currentWriterIndexRecord.fileCreateTime.getTime() > fileRolloverSec * 1000) { + closeFile = true; + logger.info("Closing file. Rolling over. queueName=" + + FILE_QUEUE_PROVIDER_NAME + ", fileName=" + + currentWriterIndexRecord.filePath); + } + } + + /** + * Load the index file + * + * @throws IOException + */ + void loadIndexFile() throws IOException { + logger.info("Loading index file. fileName=" + indexFile.getPath()); + BufferedReader br = null; + try { + br = new BufferedReader(new InputStreamReader(new FileInputStream(indexFile), "UTF-8")); + indexRecords.clear(); + String line; + while ((line = br.readLine()) != null) { + if (!line.isEmpty() && !line.startsWith("#")) { + AuditIndexRecord record = AuthObjectUtil.fromJson(line, + AuditIndexRecord.class); + indexRecords.add(record); + } + } + } finally { + if (br!= null) { + br.close(); + } + } + } + + synchronized void printIndex() { + logger.info("INDEX printIndex() ==== START"); + Iterator iter = indexRecords.iterator(); + while (iter.hasNext()) { + AuditIndexRecord record = iter.next(); + logger.info("INDEX=" + record + ", isFileExist=" + + (new File(record.filePath).exists())); + } + logger.info("INDEX printIndex() ==== END"); + } + + synchronized void removeIndexRecord(AuditIndexRecord indexRecord) + throws FileNotFoundException, IOException { + Iterator iter = indexRecords.iterator(); + while (iter.hasNext()) { + AuditIndexRecord record = iter.next(); + if (record.id.equals(indexRecord.id)) { + logger.info("Removing file from index. file=" + record.filePath + + ", queueName=" + FILE_QUEUE_PROVIDER_NAME + + ", consumer=" + consumerProvider.getName()); + + iter.remove(); + appendToDoneFile(record); + } + } + saveIndexFile(); + // If there are no more files in the index, then let's assume the + // destination is now available + if (indexRecords.size() == 0) { + isPending = false; + } + } + + synchronized void saveIndexFile() throws FileNotFoundException, IOException { + PrintWriter out = new PrintWriter(indexFile,"UTF-8"); + for (AuditIndexRecord auditIndexRecord : indexRecords) { + out.println(AuthObjectUtil.toJson(auditIndexRecord)); + } + out.close(); + // printIndex(); + + } + + void appendToDoneFile(AuditIndexRecord indexRecord) + throws FileNotFoundException, IOException { + logger.info("Moving to done file. " + indexRecord.filePath + + ", queueName=" + FILE_QUEUE_PROVIDER_NAME + ", consumer=" + + consumerProvider.getName()); + String line = AuthObjectUtil.toJson(indexRecord); + PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream( + indexDoneFile, true),"UTF-8"))); + out.println(line); + out.flush(); + out.close(); + + // After Each file is read and audit events are pushed into pipe, we flush to reach the destination immediate. + consumerProvider.flush(); + + // Move to archive folder + File logFile = null; + File archiveFile = null; + try { + logFile = new File(indexRecord.filePath); + String fileName = logFile.getName(); + archiveFile = new File(archiveFolder, fileName); + logger.info("Moving logFile " + logFile + " to " + archiveFile); + boolean result = logFile.renameTo(archiveFile); + if (!result) { + logger.error("Error moving log file to archive folder. Unable to rename" + + logFile + " to archiveFile=" + archiveFile); + } + } catch (Throwable t) { + logger.error("Error moving log file to archive folder. logFile=" + + logFile + ", archiveFile=" + archiveFile, t); + } + + // After archiving the file flush the pipe + consumerProvider.flush(); + + archiveFile = null; + try { + // Remove old files + File[] logFiles = archiveFolder.listFiles(new FileFilter() { + public boolean accept(File pathname) { + return pathname.getName().toLowerCase().endsWith(".log"); + } + }); + + if (logFiles != null && logFiles.length > maxArchiveFiles) { + int filesToDelete = logFiles.length - maxArchiveFiles; + BufferedReader br = new BufferedReader(new FileReader( + indexDoneFile)); + try { + int filesDeletedCount = 0; + while ((line = br.readLine()) != null) { + if (!line.isEmpty() && !line.startsWith("#")) { + AuditIndexRecord record = AuthObjectUtil.fromJson(line, AuditIndexRecord.class); + logFile = new File(record.filePath); + String fileName = logFile.getName(); + archiveFile = new File(archiveFolder, fileName); + if (archiveFile.exists()) { + logger.info("Deleting archive file " + + archiveFile); + boolean ret = archiveFile.delete(); + if (!ret) { + logger.error("Error deleting archive file. archiveFile=" + + archiveFile); + } + filesDeletedCount++; + if (filesDeletedCount >= filesToDelete) { + logger.info("Deleted " + filesDeletedCount + + " files"); + break; + } + } + } + } + } finally { + br.close(); + } + } + } catch (Throwable t) { + logger.error("Error deleting older archive file. archiveFile=" + + archiveFile, t); + } + + } + + void logError(String msg) { + long currTimeMS = System.currentTimeMillis(); + if (currTimeMS - lastErrorLogMS > errorLogIntervalMS) { + logger.error(msg); + lastErrorLogMS = currTimeMS; + } + } + + class AuditIndexRecord { + String id; + String filePath; + int linePosition = 0; + SPOOL_FILE_STATUS status = SPOOL_FILE_STATUS.write_inprogress; + Date fileCreateTime; + Date writeCompleteTime; + Date doneCompleteTime; + Date lastSuccessTime; + Date lastFailedTime; + int failedAttemptCount = 0; + boolean lastAttempt = false; + + @Override + public String toString() { + return "AuditIndexRecord [id=" + id + ", filePath=" + filePath + + ", linePosition=" + linePosition + ", status=" + status + + ", fileCreateTime=" + fileCreateTime + + ", writeCompleteTime=" + writeCompleteTime + + ", doneCompleteTime=" + doneCompleteTime + + ", lastSuccessTime=" + lastSuccessTime + + ", lastFailedTime=" + lastFailedTime + + ", failedAttemptCount=" + failedAttemptCount + + ", lastAttempt=" + lastAttempt + "]"; + } + + } + + /* + * (non-Javadoc) + * + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + try { + //This is done to clear the MDC context to avoid issue with Ranger Auditing for Knox + //MDC.clear(); + runLogAudit(); + } catch (Throwable t) { + logger.error("Exited thread without abnormaly. queue=" + + consumerProvider.getName(), t); + } + } + + public void runLogAudit() { + // boolean isResumed = false; + while (true) { + try { + if (isDestDown) { + logger.info("Destination is down. sleeping for " + + retryDestinationMS + + " milli seconds. indexQueue=" + indexQueue.size() + + ", queueName=" + FILE_QUEUE_PROVIDER_NAME + + ", consumer=" + consumerProvider.getName()); + Thread.sleep(retryDestinationMS); + } + // Let's pause between each iteration + if (currentConsumerIndexRecord == null) { + currentConsumerIndexRecord = indexQueue.poll( + retryDestinationMS, TimeUnit.MILLISECONDS); + } else { + Thread.sleep(retryDestinationMS); + } + + if (isDrain) { + // Need to exit + break; + } + if (currentConsumerIndexRecord == null) { + closeFileIfNeeded(); + continue; + } + + boolean isRemoveIndex = false; + File consumerFile = new File( + currentConsumerIndexRecord.filePath); + if (!consumerFile.exists()) { + logger.error("Consumer file=" + consumerFile.getPath() + + " not found."); + printIndex(); + isRemoveIndex = true; + } else { + // Let's open the file to write + BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream( + currentConsumerIndexRecord.filePath),"UTF-8")); + try { + if (auditFileType.equalsIgnoreCase(DEFAULT_AUDIT_FILE_TYPE)) { + // if Audit File format is JSON each audit file in the Local Spool Location will be copied + // to HDFS location as JSON + File srcFile = new File(currentConsumerIndexRecord.filePath); + logFile(srcFile); + } else { + // If Audit File format is ORC, each records in audit files in the Local Spool Location will be + // read and converted into ORC format and pushed into an ORC file. + logEvent(br); + } + logger.info("Done reading file. file=" + + currentConsumerIndexRecord.filePath + + ", queueName=" + FILE_QUEUE_PROVIDER_NAME + + ", consumer=" + consumerProvider.getName()); + // The entire file is read + currentConsumerIndexRecord.status = SPOOL_FILE_STATUS.done; + currentConsumerIndexRecord.doneCompleteTime = new Date(); + currentConsumerIndexRecord.lastAttempt = true; + + isRemoveIndex = true; + } catch (Exception ex) { + isDestDown = true; + logError("Destination down. queueName=" + + FILE_QUEUE_PROVIDER_NAME + ", consumer=" + + consumerProvider.getName()); + lastAttemptTime = System.currentTimeMillis(); + // Update the index file + currentConsumerIndexRecord.lastFailedTime = new Date(); + currentConsumerIndexRecord.failedAttemptCount++; + currentConsumerIndexRecord.lastAttempt = false; + saveIndexFile(); + } finally { + br.close(); + } + } + if (isRemoveIndex) { + // Remove this entry from index + removeIndexRecord(currentConsumerIndexRecord); + currentConsumerIndexRecord = null; + closeFileIfNeeded(); + } + } catch (InterruptedException e) { + logger.info("Caught exception in consumer thread. Shutdown might be in progress"); + } catch (Throwable t) { + logger.error("Exception in destination writing thread.", t); + } + } + logger.info("Exiting file spooler. provider=" + FILE_QUEUE_PROVIDER_NAME + + ", consumer=" + consumerProvider.getName()); + } + + private void logEvent(BufferedReader br) throws Exception { + String line; + int currLine = 0; + int startLine = currentConsumerIndexRecord.linePosition; + List events = new ArrayList<>(); + while ((line = br.readLine()) != null) { + currLine++; + if (currLine < startLine) { + continue; + } + AuditEventBase event = MiscUtil.fromJson(line, AuthzAuditEvent.class); + events.add(event); + + if (events.size() == bufferSize) { + boolean ret = sendEvent(events, + currentConsumerIndexRecord, currLine); + if (!ret) { + throw new Exception("Destination down"); + } + events.clear(); + } + } + if (events.size() > 0) { + boolean ret = sendEvent(events, + currentConsumerIndexRecord, currLine); + if (!ret) { + throw new Exception("Destination down"); + } + events.clear(); + } + } + + private boolean sendEvent(List events, AuditIndexRecord indexRecord, + int currLine) { + boolean ret = true; + try { + ret = consumerProvider.log(events); + if (!ret) { + // Need to log error after fixed interval + logError("Error sending logs to consumer. provider=" + + FILE_QUEUE_PROVIDER_NAME + ", consumer=" + + consumerProvider.getName()); + } else { + // Update index and save + indexRecord.linePosition = currLine; + indexRecord.status = SPOOL_FILE_STATUS.read_inprogress; + indexRecord.lastSuccessTime = new Date(); + indexRecord.lastAttempt = true; + saveIndexFile(); + + if (isDestDown) { + isDestDown = false; + logger.info("Destination up now. " + indexRecord.filePath + + ", queueName=" + FILE_QUEUE_PROVIDER_NAME + + ", consumer=" + consumerProvider.getName()); + } + } + } catch (Throwable t) { + logger.error("Error while sending logs to consumer. provider=" + + FILE_QUEUE_PROVIDER_NAME + ", consumer=" + + consumerProvider.getName() + ", log=" + events, t); + } + + return ret; + } + + private void logFile(File file) throws Exception { + if (logger.isDebugEnabled()) { + logger.debug("==> AuditFileQueueSpool.logFile()"); + } + int currLine = 0; + int startLine = currentConsumerIndexRecord.linePosition; + + if (currLine < startLine) { + currLine++; + } + + boolean ret = sendFile(file,currentConsumerIndexRecord, currLine); + if (!ret) { + throw new Exception("Destination down"); + } + + if (logger.isDebugEnabled()) { + logger.debug("<== AuditFileQueueSpool.logFile()"); + } + } + + private boolean sendFile(File file, AuditIndexRecord indexRecord, + int currLine) { + boolean ret = true; + if (logger.isDebugEnabled()) { + logger.debug("==> AuditFileQueueSpool.sendFile()"); + } + + try { + ret = consumerProvider.logFile(file); + if (!ret) { + // Need to log error after fixed interval + logError("Error sending log file to consumer. provider=" + + FILE_QUEUE_PROVIDER_NAME + ", consumer=" + + consumerProvider.getName()+ ", logFile=" + file.getName()); + } else { + // Update index and save + indexRecord.linePosition = currLine; + indexRecord.status = SPOOL_FILE_STATUS.read_inprogress; + indexRecord.lastSuccessTime = new Date(); + indexRecord.lastAttempt = true; + saveIndexFile(); + + if (isDestDown) { + isDestDown = false; + logger.info("Destination up now. " + indexRecord.filePath + + ", queueName=" + FILE_QUEUE_PROVIDER_NAME + + ", consumer=" + consumerProvider.getName()); + } + } + } catch (Throwable t) { + logger.error("Error sending log file to consumer. provider=" + + FILE_QUEUE_PROVIDER_NAME + ", consumer=" + + consumerProvider.getName() + ", logFile=" + file.getName(), t); + } + + if (logger.isDebugEnabled()) { + logger.debug("<== AuditFileQueueSpool.sendFile() " + ret ); + } + return ret; + } +} \ No newline at end of file diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditFileSpool.java b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditFileSpool.java new file mode 100644 index 00000000000..b358744111a --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditFileSpool.java @@ -0,0 +1,901 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.queue; + +import org.apache.atlas.audit.utils.AuthObjectUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +//import org.apache.log4j.MDC; +import org.apache.atlas.audit.model.AuditEventBase; +import org.apache.atlas.audit.provider.AuditHandler; +import org.apache.atlas.audit.provider.MiscUtil; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileFilter; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +/** + * This class temporarily stores logs in file system if the destination is + * overloaded or down + */ +public class AuditFileSpool implements Runnable { + private static final Log logger = LogFactory.getLog(AuditFileSpool.class); + + public enum SPOOL_FILE_STATUS { + pending, write_inprogress, read_inprogress, done + } + + public static final String PROP_FILE_SPOOL_LOCAL_DIR = "filespool.dir"; + public static final String PROP_FILE_SPOOL_LOCAL_FILE_NAME = "filespool.filename.format"; + public static final String PROP_FILE_SPOOL_ARCHIVE_DIR = "filespool.archive.dir"; + public static final String PROP_FILE_SPOOL_ARCHIVE_MAX_FILES_COUNT = "filespool.archive.max.files"; + public static final String PROP_FILE_SPOOL_FILENAME_PREFIX = "filespool.file.prefix"; + public static final String PROP_FILE_SPOOL_FILE_ROLLOVER = "filespool.file.rollover.sec"; + public static final String PROP_FILE_SPOOL_INDEX_FILE = "filespool.index.filename"; + // public static final String PROP_FILE_SPOOL_INDEX_DONE_FILE = + // "filespool.index.done_filename"; + public static final String PROP_FILE_SPOOL_DEST_RETRY_MS = "filespool.destination.retry.ms"; + + AuditQueue queueProvider = null; + AuditHandler consumerProvider = null; + + BlockingQueue indexQueue = new LinkedBlockingQueue(); + + // Folder and File attributes + File logFolder = null; + String logFileNameFormat = null; + File archiveFolder = null; + String fileNamePrefix = null; + String indexFileName = null; + File indexFile = null; + String indexDoneFileName = null; + File indexDoneFile = null; + int retryDestinationMS = 30 * 1000; // Default 30 seconds + int fileRolloverSec = 24 * 60 * 60; // In seconds + int maxArchiveFiles = 100; + + int errorLogIntervalMS = 30 * 1000; // Every 30 seconds + long lastErrorLogMS = 0; + + List indexRecords = new ArrayList(); + + boolean isPending = false; + long lastAttemptTime = 0; + boolean initDone = false; + + PrintWriter logWriter = null; + AuditIndexRecord currentWriterIndexRecord = null; + AuditIndexRecord currentConsumerIndexRecord = null; + + BufferedReader logReader = null; + + Thread destinationThread = null; + + boolean isWriting = true; + boolean isDrain = false; + boolean isDestDown = false; + + public AuditFileSpool(AuditQueue queueProvider, + AuditHandler consumerProvider) { + this.queueProvider = queueProvider; + this.consumerProvider = consumerProvider; + } + + public void init(Properties prop) { + init(prop, null); + } + + public boolean init(Properties props, String basePropertyName) { + if (initDone) { + logger.error("init() called more than once. queueProvider=" + + queueProvider.getName() + ", consumerProvider=" + + consumerProvider.getName()); + return true; + } + String propPrefix = "xasecure.audit.filespool"; + if (basePropertyName != null) { + propPrefix = basePropertyName; + } + + try { + // Initial folder and file properties + String logFolderProp = MiscUtil.getStringProperty(props, propPrefix + + "." + PROP_FILE_SPOOL_LOCAL_DIR); + logFileNameFormat = MiscUtil.getStringProperty(props, + basePropertyName + "." + PROP_FILE_SPOOL_LOCAL_FILE_NAME); + String archiveFolderProp = MiscUtil.getStringProperty(props, + propPrefix + "." + PROP_FILE_SPOOL_ARCHIVE_DIR); + fileNamePrefix = MiscUtil.getStringProperty(props, propPrefix + "." + + PROP_FILE_SPOOL_FILENAME_PREFIX); + indexFileName = MiscUtil.getStringProperty(props, propPrefix + "." + + PROP_FILE_SPOOL_INDEX_FILE); + retryDestinationMS = MiscUtil.getIntProperty(props, propPrefix + + "." + PROP_FILE_SPOOL_DEST_RETRY_MS, retryDestinationMS); + fileRolloverSec = MiscUtil.getIntProperty(props, propPrefix + "." + + PROP_FILE_SPOOL_FILE_ROLLOVER, fileRolloverSec); + maxArchiveFiles = MiscUtil.getIntProperty(props, propPrefix + "." + + PROP_FILE_SPOOL_ARCHIVE_MAX_FILES_COUNT, maxArchiveFiles); + + logger.info("retryDestinationMS=" + retryDestinationMS + + ", queueName=" + queueProvider.getName()); + logger.info("fileRolloverSec=" + fileRolloverSec + ", queueName=" + + queueProvider.getName()); + logger.info("maxArchiveFiles=" + maxArchiveFiles + ", queueName=" + + queueProvider.getName()); + + if (logFolderProp == null || logFolderProp.isEmpty()) { + logger.fatal("Audit spool folder is not configured. Please set " + + propPrefix + + "." + + PROP_FILE_SPOOL_LOCAL_DIR + + ". queueName=" + queueProvider.getName()); + return false; + } + logFolder = new File(logFolderProp); + if (!logFolder.isDirectory()) { + logFolder.mkdirs(); + if (!logFolder.isDirectory()) { + logger.fatal("File Spool folder not found and can't be created. folder=" + + logFolder.getAbsolutePath() + + ", queueName=" + + queueProvider.getName()); + return false; + } + } + logger.info("logFolder=" + logFolder + ", queueName=" + + queueProvider.getName()); + + if (logFileNameFormat == null || logFileNameFormat.isEmpty()) { + logFileNameFormat = "spool_" + "%app-type%" + "_" + + "%time:yyyyMMdd-HHmm.ss%.log"; + } + logger.info("logFileNameFormat=" + logFileNameFormat + + ", queueName=" + queueProvider.getName()); + + if (archiveFolderProp == null || archiveFolderProp.isEmpty()) { + archiveFolder = new File(logFolder, "archive"); + } else { + archiveFolder = new File(archiveFolderProp); + } + if (!archiveFolder.isDirectory()) { + archiveFolder.mkdirs(); + if (!archiveFolder.isDirectory()) { + logger.error("File Spool archive folder not found and can't be created. folder=" + + archiveFolder.getAbsolutePath() + + ", queueName=" + + queueProvider.getName()); + return false; + } + } + logger.info("archiveFolder=" + archiveFolder + ", queueName=" + + queueProvider.getName()); + + if (indexFileName == null || indexFileName.isEmpty()) { + if (fileNamePrefix == null || fileNamePrefix.isEmpty()) { + fileNamePrefix = queueProvider.getName() + "_" + + consumerProvider.getName(); + } + indexFileName = "index_" + fileNamePrefix + "_" + "%app-type%" + + ".json"; + indexFileName = MiscUtil.replaceTokens(indexFileName, + System.currentTimeMillis()); + } + + indexFile = new File(logFolder, indexFileName); + if (!indexFile.exists()) { + boolean ret = indexFile.createNewFile(); + if (!ret) { + logger.fatal("Error creating index file. fileName=" + + indexDoneFile.getPath()); + return false; + } + } + logger.info("indexFile=" + indexFile + ", queueName=" + + queueProvider.getName()); + + int lastDot = indexFileName.lastIndexOf('.'); + if (lastDot < 0) { + lastDot = indexFileName.length() - 1; + } + indexDoneFileName = indexFileName.substring(0, lastDot) + + "_closed.json"; + indexDoneFile = new File(logFolder, indexDoneFileName); + if (!indexDoneFile.exists()) { + boolean ret = indexDoneFile.createNewFile(); + if (!ret) { + logger.fatal("Error creating index done file. fileName=" + + indexDoneFile.getPath()); + return false; + } + } + logger.info("indexDoneFile=" + indexDoneFile + ", queueName=" + + queueProvider.getName()); + + // Load index file + loadIndexFile(); + for (AuditIndexRecord auditIndexRecord : indexRecords) { + if (!auditIndexRecord.status.equals(SPOOL_FILE_STATUS.done)) { + isPending = true; + } + if (auditIndexRecord.status + .equals(SPOOL_FILE_STATUS.write_inprogress)) { + currentWriterIndexRecord = auditIndexRecord; + logger.info("currentWriterIndexRecord=" + + currentWriterIndexRecord.filePath + + ", queueName=" + queueProvider.getName()); + } + if (auditIndexRecord.status + .equals(SPOOL_FILE_STATUS.read_inprogress)) { + indexQueue.add(auditIndexRecord); + } + } + printIndex(); + for (AuditIndexRecord auditIndexRecord : indexRecords) { + if (auditIndexRecord.status.equals(SPOOL_FILE_STATUS.pending)) { + File consumerFile = new File(auditIndexRecord.filePath); + if (!consumerFile.exists()) { + logger.error("INIT: Consumer file=" + + consumerFile.getPath() + " not found."); + } else { + indexQueue.add(auditIndexRecord); + } + } + } + + } catch (Throwable t) { + logger.fatal("Error initializing File Spooler. queue=" + + queueProvider.getName(), t); + return false; + } + initDone = true; + return true; + } + + /** + * Start looking for outstanding logs and update status according. + */ + public void start() { + if (!initDone) { + logger.error("Cannot start Audit File Spooler. Initilization not done yet. queueName=" + + queueProvider.getName()); + return; + } + + logger.info("Starting writerThread, queueName=" + + queueProvider.getName() + ", consumer=" + + consumerProvider.getName()); + + // Let's start the thread to read + destinationThread = new Thread(this, queueProvider.getName() + "_" + + consumerProvider.getName() + "_destWriter"); + destinationThread.setDaemon(true); + destinationThread.start(); + } + + public void stop() { + if (!initDone) { + logger.error("Cannot stop Audit File Spooler. Initilization not done. queueName=" + + queueProvider.getName()); + return; + } + logger.info("Stop called, queueName=" + queueProvider.getName() + + ", consumer=" + consumerProvider.getName()); + + isDrain = true; + flush(); + + PrintWriter out = getOpenLogFileStream(); + if (out != null) { + // If write is still going on, then let's give it enough time to + // complete + for (int i = 0; i < 3; i++) { + if (isWriting) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // ignore + } + continue; + } + try { + logger.info("Closing open file, queueName=" + + queueProvider.getName() + ", consumer=" + + consumerProvider.getName()); + + out.flush(); + out.close(); + break; + } catch (Throwable t) { + logger.debug("Error closing spool out file.", t); + } + } + } + try { + if (destinationThread != null) { + destinationThread.interrupt(); + } + destinationThread = null; + } catch (Throwable e) { + // ignore + } + } + + public void flush() { + if (!initDone) { + logger.error("Cannot flush Audit File Spooler. Initilization not done. queueName=" + + queueProvider.getName()); + return; + } + PrintWriter out = getOpenLogFileStream(); + if (out != null) { + out.flush(); + } + } + + /** + * If any files are still not processed. Also, if the destination is not + * reachable + * + * @return + */ + public boolean isPending() { + if (!initDone) { + logError("isPending(): File Spooler not initialized. queueName=" + + queueProvider.getName()); + return false; + } + + return isPending; + } + + /** + * Milliseconds from last attempt time + * + * @return + */ + public long getLastAttemptTimeDelta() { + if (lastAttemptTime == 0) { + return 0; + } + return System.currentTimeMillis() - lastAttemptTime; + } + + synchronized public void stashLogs(AuditEventBase event) { + if (isDrain) { + // Stop has been called, so this method shouldn't be called + logger.error("stashLogs() is called after stop is called. event=" + + event); + return; + } + try { + isWriting = true; + PrintWriter logOut = getLogFileStream(); + // Convert event to json + String jsonStr = MiscUtil.stringify(event); + logOut.println(jsonStr); + isPending = true; + } catch (Exception ex) { + logger.error("Error writing to file. event=" + event, ex); + } finally { + isWriting = false; + } + + } + + synchronized public void stashLogs(Collection events) { + for (AuditEventBase event : events) { + stashLogs(event); + } + flush(); + } + + synchronized public void stashLogsString(String event) { + if (isDrain) { + // Stop has been called, so this method shouldn't be called + logger.error("stashLogs() is called after stop is called. event=" + + event); + return; + } + try { + isWriting = true; + PrintWriter logOut = getLogFileStream(); + logOut.println(event); + } catch (Exception ex) { + logger.error("Error writing to file. event=" + event, ex); + } finally { + isWriting = false; + } + + } + + synchronized public void stashLogsString(Collection events) { + for (String event : events) { + stashLogsString(event); + } + flush(); + } + + /** + * This return the current file. If there are not current open output file, + * then it will return null + * + * @return + * @throws Exception + */ + synchronized private PrintWriter getOpenLogFileStream() { + return logWriter; + } + + /** + * @return + * @throws Exception + */ + synchronized private PrintWriter getLogFileStream() throws Exception { + closeFileIfNeeded(); + + // Either there are no open log file or the previous one has been rolled + // over + if (currentWriterIndexRecord == null) { + Date currentTime = new Date(); + // Create a new file + String fileName = MiscUtil.replaceTokens(logFileNameFormat, + currentTime.getTime()); + String newFileName = fileName; + File outLogFile = null; + int i = 0; + while (true) { + outLogFile = new File(logFolder, newFileName); + File archiveLogFile = new File(archiveFolder, newFileName); + if (!outLogFile.exists() && !archiveLogFile.exists()) { + break; + } + i++; + int lastDot = fileName.lastIndexOf('.'); + String baseName = fileName.substring(0, lastDot); + String extension = fileName.substring(lastDot); + newFileName = baseName + "." + i + extension; + } + fileName = newFileName; + logger.info("Creating new file. queueName=" + + queueProvider.getName() + ", fileName=" + fileName); + // Open the file + logWriter = new PrintWriter(new BufferedWriter(new FileWriter( + outLogFile))); + + AuditIndexRecord tmpIndexRecord = new AuditIndexRecord(); + + tmpIndexRecord.id = MiscUtil.generateUniqueId(); + tmpIndexRecord.filePath = outLogFile.getPath(); + tmpIndexRecord.status = SPOOL_FILE_STATUS.write_inprogress; + tmpIndexRecord.fileCreateTime = currentTime; + tmpIndexRecord.lastAttempt = true; + currentWriterIndexRecord = tmpIndexRecord; + indexRecords.add(currentWriterIndexRecord); + saveIndexFile(); + + } else { + if (logWriter == null) { + // This means the process just started. We need to open the file + // in append mode. + logger.info("Opening existing file for append. queueName=" + + queueProvider.getName() + ", fileName=" + + currentWriterIndexRecord.filePath); + logWriter = new PrintWriter(new BufferedWriter(new FileWriter( + currentWriterIndexRecord.filePath, true))); + } + } + return logWriter; + } + + synchronized private void closeFileIfNeeded() throws FileNotFoundException, + IOException { + // Is there file open to write or there are no pending file, then close + // the active file + if (currentWriterIndexRecord != null) { + // Check whether the file needs to rolled + boolean closeFile = false; + if (indexRecords.size() == 1) { + closeFile = true; + logger.info("Closing file. Only one open file. queueName=" + + queueProvider.getName() + ", fileName=" + + currentWriterIndexRecord.filePath); + } else if (System.currentTimeMillis() + - currentWriterIndexRecord.fileCreateTime.getTime() > fileRolloverSec * 1000) { + closeFile = true; + logger.info("Closing file. Rolling over. queueName=" + + queueProvider.getName() + ", fileName=" + + currentWriterIndexRecord.filePath); + } + if (closeFile) { + // Roll the file + if (logWriter != null) { + logWriter.flush(); + logWriter.close(); + logWriter = null; + } + currentWriterIndexRecord.status = SPOOL_FILE_STATUS.pending; + currentWriterIndexRecord.writeCompleteTime = new Date(); + saveIndexFile(); + logger.info("Adding file to queue. queueName=" + + queueProvider.getName() + ", fileName=" + + currentWriterIndexRecord.filePath); + indexQueue.add(currentWriterIndexRecord); + currentWriterIndexRecord = null; + } + } + } + + /** + * Load the index file + * + * @throws IOException + */ + void loadIndexFile() throws IOException { + logger.info("Loading index file. fileName=" + indexFile.getPath()); + BufferedReader br = new BufferedReader(new FileReader(indexFile)); + indexRecords.clear(); + String line; + while ((line = br.readLine()) != null) { + if (!line.isEmpty() && !line.startsWith("#")) { + AuditIndexRecord record = AuthObjectUtil.fromJson(line, AuditIndexRecord.class); + indexRecords.add(record); + } + } + br.close(); + } + + synchronized void printIndex() { + logger.info("INDEX printIndex() ==== START"); + Iterator iter = indexRecords.iterator(); + while (iter.hasNext()) { + AuditIndexRecord record = iter.next(); + logger.info("INDEX=" + record + ", isFileExist=" + + (new File(record.filePath).exists())); + } + logger.info("INDEX printIndex() ==== END"); + } + + synchronized void removeIndexRecord(AuditIndexRecord indexRecord) + throws FileNotFoundException, IOException { + Iterator iter = indexRecords.iterator(); + while (iter.hasNext()) { + AuditIndexRecord record = iter.next(); + if (record.id.equals(indexRecord.id)) { + logger.info("Removing file from index. file=" + record.filePath + + ", queueName=" + queueProvider.getName() + + ", consumer=" + consumerProvider.getName()); + + iter.remove(); + appendToDoneFile(record); + } + } + saveIndexFile(); + // If there are no more files in the index, then let's assume the + // destination is now available + if (indexRecords.size() == 0) { + isPending = false; + } + } + + synchronized void saveIndexFile() throws FileNotFoundException, IOException { + PrintWriter out = new PrintWriter(indexFile); + for (AuditIndexRecord auditIndexRecord : indexRecords) { + out.println(AuthObjectUtil.toJson(auditIndexRecord)); + } + out.close(); + // printIndex(); + + } + + void appendToDoneFile(AuditIndexRecord indexRecord) + throws FileNotFoundException, IOException { + logger.info("Moving to done file. " + indexRecord.filePath + + ", queueName=" + queueProvider.getName() + ", consumer=" + + consumerProvider.getName()); + String line = AuthObjectUtil.toJson(indexRecord); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter( + indexDoneFile, true))); + out.println(line); + out.flush(); + out.close(); + + // Move to archive folder + File logFile = null; + File archiveFile = null; + try { + logFile = new File(indexRecord.filePath); + String fileName = logFile.getName(); + archiveFile = new File(archiveFolder, fileName); + logger.info("Moving logFile " + logFile + " to " + archiveFile); + logFile.renameTo(archiveFile); + } catch (Throwable t) { + logger.error("Error moving log file to archive folder. logFile=" + + logFile + ", archiveFile=" + archiveFile, t); + } + + archiveFile = null; + try { + // Remove old files + File[] logFiles = archiveFolder.listFiles(new FileFilter() { + public boolean accept(File pathname) { + return pathname.getName().toLowerCase().endsWith(".log"); + } + }); + + if (logFiles != null && logFiles.length > maxArchiveFiles) { + int filesToDelete = logFiles.length - maxArchiveFiles; + BufferedReader br = new BufferedReader(new FileReader( + indexDoneFile)); + try { + int filesDeletedCount = 0; + while ((line = br.readLine()) != null) { + if (!line.isEmpty() && !line.startsWith("#")) { + AuditIndexRecord record = AuthObjectUtil.fromJson(line, AuditIndexRecord.class); + logFile = new File(record.filePath); + String fileName = logFile.getName(); + archiveFile = new File(archiveFolder, fileName); + if (archiveFile.exists()) { + logger.info("Deleting archive file " + + archiveFile); + boolean ret = archiveFile.delete(); + if (!ret) { + logger.error("Error deleting archive file. archiveFile=" + + archiveFile); + } + filesDeletedCount++; + if (filesDeletedCount >= filesToDelete) { + logger.info("Deleted " + filesDeletedCount + + " files"); + break; + } + } + } + } + } finally { + br.close(); + } + } + } catch (Throwable t) { + logger.error("Error deleting older archive file. archiveFile=" + + archiveFile, t); + } + + } + + void logError(String msg) { + long currTimeMS = System.currentTimeMillis(); + if (currTimeMS - lastErrorLogMS > errorLogIntervalMS) { + logger.error(msg); + lastErrorLogMS = currTimeMS; + } + } + + class AuditIndexRecord { + String id; + String filePath; + int linePosition = 0; + SPOOL_FILE_STATUS status = SPOOL_FILE_STATUS.write_inprogress; + Date fileCreateTime; + Date writeCompleteTime; + Date doneCompleteTime; + Date lastSuccessTime; + Date lastFailedTime; + int failedAttemptCount = 0; + boolean lastAttempt = false; + + @Override + public String toString() { + return "AuditIndexRecord [id=" + id + ", filePath=" + filePath + + ", linePosition=" + linePosition + ", status=" + status + + ", fileCreateTime=" + fileCreateTime + + ", writeCompleteTime=" + writeCompleteTime + + ", doneCompleteTime=" + doneCompleteTime + + ", lastSuccessTime=" + lastSuccessTime + + ", lastFailedTime=" + lastFailedTime + + ", failedAttemptCount=" + failedAttemptCount + + ", lastAttempt=" + lastAttempt + "]"; + } + + } + + class AuditFileSpoolAttempt { + Date attemptTime; + String status; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + try { + //This is done to clear the MDC context to avoid issue with Ranger Auditing for Knox + //MDC.clear(); + runLogAudit(); + } catch (Throwable t) { + logger.fatal("Exited thread without abnormaly. queue=" + + consumerProvider.getName(), t); + } + } + + public void runLogAudit() { + // boolean isResumed = false; + while (true) { + try { + if (isDestDown) { + logger.info("Destination is down. sleeping for " + + retryDestinationMS + + " milli seconds. indexQueue=" + indexQueue.size() + + ", queueName=" + queueProvider.getName() + + ", consumer=" + consumerProvider.getName()); + Thread.sleep(retryDestinationMS); + } + + // Let's pause between each iteration + if (currentConsumerIndexRecord == null) { + currentConsumerIndexRecord = indexQueue.poll( + retryDestinationMS, TimeUnit.MILLISECONDS); + } else { + Thread.sleep(retryDestinationMS); + } + + if (isDrain) { + // Need to exit + break; + } + if (currentConsumerIndexRecord == null) { + closeFileIfNeeded(); + continue; + } + + boolean isRemoveIndex = false; + File consumerFile = new File( + currentConsumerIndexRecord.filePath); + if (!consumerFile.exists()) { + logger.error("Consumer file=" + consumerFile.getPath() + + " not found."); + printIndex(); + isRemoveIndex = true; + } else { + // Let's open the file to write + BufferedReader br = new BufferedReader(new FileReader( + currentConsumerIndexRecord.filePath)); + try { + int startLine = currentConsumerIndexRecord.linePosition; + String line; + int currLine = 0; + List lines = new ArrayList(); + while ((line = br.readLine()) != null) { + currLine++; + if (currLine < startLine) { + continue; + } + lines.add(line); + if (lines.size() == queueProvider.getMaxBatchSize()) { + boolean ret = sendEvent(lines, + currentConsumerIndexRecord, currLine); + if (!ret) { + throw new Exception("Destination down"); + } + lines.clear(); + } + } + if (lines.size() > 0) { + boolean ret = sendEvent(lines, + currentConsumerIndexRecord, currLine); + if (!ret) { + throw new Exception("Destination down"); + } + lines.clear(); + } + logger.info("Done reading file. file=" + + currentConsumerIndexRecord.filePath + + ", queueName=" + queueProvider.getName() + + ", consumer=" + consumerProvider.getName()); + // The entire file is read + currentConsumerIndexRecord.status = SPOOL_FILE_STATUS.done; + currentConsumerIndexRecord.doneCompleteTime = new Date(); + currentConsumerIndexRecord.lastAttempt = true; + + isRemoveIndex = true; + } catch (Exception ex) { + isDestDown = true; + logError("Destination down. queueName=" + + queueProvider.getName() + ", consumer=" + + consumerProvider.getName()); + lastAttemptTime = System.currentTimeMillis(); + // Update the index file + currentConsumerIndexRecord.lastFailedTime = new Date(); + currentConsumerIndexRecord.failedAttemptCount++; + currentConsumerIndexRecord.lastAttempt = false; + saveIndexFile(); + } finally { + br.close(); + } + } + if (isRemoveIndex) { + // Remove this entry from index + removeIndexRecord(currentConsumerIndexRecord); + currentConsumerIndexRecord = null; + closeFileIfNeeded(); + } + } catch (InterruptedException e) { + logger.info("Caught exception in consumer thread. Shutdown might be in progress"); + break; + } catch (Throwable t) { + logger.error("Exception in destination writing thread.", t); + } + } + logger.info("Exiting file spooler. provider=" + queueProvider.getName() + + ", consumer=" + consumerProvider.getName()); + } + + private boolean sendEvent(List lines, AuditIndexRecord indexRecord, + int currLine) { + boolean ret = true; + try { + ret = consumerProvider.logJSON(lines); + if (!ret) { + // Need to log error after fixed interval + logError("Error sending logs to consumer. provider=" + + queueProvider.getName() + ", consumer=" + + consumerProvider.getName()); + } else { + // Update index and save + indexRecord.linePosition = currLine; + indexRecord.status = SPOOL_FILE_STATUS.read_inprogress; + indexRecord.lastSuccessTime = new Date(); + indexRecord.lastAttempt = true; + saveIndexFile(); + + if (isDestDown) { + isDestDown = false; + logger.info("Destination up now. " + indexRecord.filePath + + ", queueName=" + queueProvider.getName() + + ", consumer=" + consumerProvider.getName()); + } + } + } catch (Throwable t) { + logger.error("Error while sending logs to consumer. provider=" + + queueProvider.getName() + ", consumer=" + + consumerProvider.getName() + ", log=" + lines, t); + } + + return ret; + } + +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditQueue.java b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditQueue.java new file mode 100644 index 00000000000..d27ab300358 --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditQueue.java @@ -0,0 +1,230 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.queue; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.audit.destination.AuditDestination; +import org.apache.atlas.audit.provider.AuditHandler; +import org.apache.atlas.audit.provider.BaseAuditHandler; +import org.apache.atlas.audit.provider.MiscUtil; + +import java.util.Properties; + +public abstract class AuditQueue extends BaseAuditHandler { + private static final Log LOG = LogFactory.getLog(AuditQueue.class); + + public static final int AUDIT_MAX_QUEUE_SIZE_DEFAULT = 1024 * 1024; + public static final int AUDIT_BATCH_INTERVAL_DEFAULT_MS = 3000; + public static final int AUDIT_BATCH_SIZE_DEFAULT = 1000; + + // This is the max time the consumer thread will wait before exiting the + // loop + public static final int AUDIT_CONSUMER_THREAD_WAIT_MS = 5000; + + private int maxQueueSize = AUDIT_MAX_QUEUE_SIZE_DEFAULT; + private int maxBatchInterval = AUDIT_BATCH_INTERVAL_DEFAULT_MS; + private int maxBatchSize = AUDIT_BATCH_SIZE_DEFAULT; + + public static final String PROP_QUEUE = "queue"; + + public static final String PROP_BATCH_SIZE = "batch.size"; + public static final String PROP_QUEUE_SIZE = "queue.size"; + public static final String PROP_BATCH_INTERVAL = "batch.interval.ms"; + + public static final String PROP_FILE_SPOOL_ENABLE = "filespool.enable"; + public static final String PROP_FILE_SPOOL_WAIT_FOR_FULL_DRAIN = "filespool.drain.full.wait.ms"; + public static final String PROP_FILE_SPOOL_QUEUE_THRESHOLD = "filespool.drain.threshold.percent"; + + final protected AuditHandler consumer; + protected AuditFileSpool fileSpooler = null; + + private boolean isDrain = false; + + protected boolean fileSpoolerEnabled = false; + protected int fileSpoolMaxWaitTime = 5 * 60 * 1000; // Default 5 minutes + protected int fileSpoolDrainThresholdPercent = 80; + + boolean isConsumerDestination = false; + // This is set when the first time stop is called. + protected long stopTime = 0; + + /** + * @param consumer + */ + public AuditQueue(AuditHandler consumer) { + this.consumer = consumer; + if (consumer instanceof BaseAuditHandler) { + BaseAuditHandler baseAuditHander = (BaseAuditHandler) consumer; + baseAuditHander.setParentPath(getName()); + } + + if (consumer != null && consumer instanceof AuditDestination) { + // If consumer is destination, then the thread should run as server + // user + isConsumerDestination = true; + } + } + + @Override + public void init(Properties props, String basePropertyName) { + LOG.info("BaseAuditProvider.init()"); + super.init(props, basePropertyName); + + setMaxBatchSize(MiscUtil.getIntProperty(props, propPrefix + "." + + PROP_BATCH_SIZE, getMaxBatchSize())); + setMaxQueueSize(MiscUtil.getIntProperty(props, propPrefix + "." + + PROP_QUEUE_SIZE, getMaxQueueSize())); + setMaxBatchInterval(MiscUtil.getIntProperty(props, propPrefix + "." + + PROP_BATCH_INTERVAL, getMaxBatchInterval())); + + fileSpoolerEnabled = MiscUtil.getBooleanProperty(props, propPrefix + + "." + PROP_FILE_SPOOL_ENABLE, false); + String logFolderProp = MiscUtil.getStringProperty(props, propPrefix + + "." + AuditFileSpool.PROP_FILE_SPOOL_LOCAL_DIR); + if (fileSpoolerEnabled || logFolderProp != null) { + LOG.info("File spool is enabled for " + getName() + + ", logFolderProp=" + logFolderProp + ", " + propPrefix + + "." + AuditFileSpool.PROP_FILE_SPOOL_LOCAL_DIR + "=" + + fileSpoolerEnabled); + fileSpoolerEnabled = true; + fileSpoolMaxWaitTime = MiscUtil.getIntProperty(props, propPrefix + + "." + PROP_FILE_SPOOL_WAIT_FOR_FULL_DRAIN, + fileSpoolMaxWaitTime); + fileSpoolDrainThresholdPercent = MiscUtil.getIntProperty(props, + propPrefix + "." + PROP_FILE_SPOOL_QUEUE_THRESHOLD, + fileSpoolDrainThresholdPercent); + fileSpooler = new AuditFileSpool(this, consumer); + if (!fileSpooler.init(props, basePropertyName)) { + fileSpoolerEnabled = false; + LOG.fatal("Couldn't initialize file spooler. Disabling it. queue=" + + getName() + ", consumer=" + consumer.getName()); + } + } else { + LOG.info("File spool is disabled for " + getName()); + } + + } + + @Override + public void setParentPath(String parentPath) { + super.setParentPath(parentPath); + if (consumer != null && consumer instanceof BaseAuditHandler) { + BaseAuditHandler base = (BaseAuditHandler) consumer; + base.setParentPath(getName()); + } + } + + @Override + public String getFinalPath() { + if (consumer != null) { + if (consumer instanceof BaseAuditHandler) { + return ((BaseAuditHandler) consumer).getFinalPath(); + } else { + return consumer.getName(); + } + } + return getName(); + } + + @Override + public void setName(String name) { + super.setName(name); + if (consumer != null && consumer instanceof BaseAuditHandler) { + BaseAuditHandler base = (BaseAuditHandler) consumer; + base.setParentPath(getName()); + } + } + + public AuditHandler getConsumer() { + return consumer; + } + + public boolean isDrainMaxTimeElapsed() { + return (stopTime - System.currentTimeMillis()) > AUDIT_CONSUMER_THREAD_WAIT_MS; + } + + public boolean isDrain() { + return isDrain; + } + + public void setDrain(boolean isDrain) { + if (isDrain && stopTime != 0) { + stopTime = System.currentTimeMillis(); + } + this.isDrain = isDrain; + } + + public int getMaxQueueSize() { + return maxQueueSize; + } + + public void setMaxQueueSize(int maxQueueSize) { + this.maxQueueSize = maxQueueSize; + } + + public int getMaxBatchInterval() { + return maxBatchInterval; + } + + public void setMaxBatchInterval(int maxBatchInterval) { + this.maxBatchInterval = maxBatchInterval; + } + + public int getMaxBatchSize() { + return maxBatchSize; + } + + public void setMaxBatchSize(int maxBatchSize) { + this.maxBatchSize = maxBatchSize; + } + + /* + * (non-Javadoc) + * + * @see org.apache.ranger.audit.provider.AuditProvider#waitToComplete() + */ + @Override + public void waitToComplete() { + if (consumer != null) { + consumer.waitToComplete(-1); + } + } + + @Override + public void waitToComplete(long timeout) { + if (consumer != null) { + consumer.waitToComplete(timeout); + } + } + + /* + * (non-Javadoc) + * + * @see org.apache.ranger.audit.provider.AuditProvider#flush() + */ + @Override + public void flush() { + if (consumer != null) { + consumer.flush(); + } + } + +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditSummaryQueue.java b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditSummaryQueue.java new file mode 100644 index 00000000000..54911829ded --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/queue/AuditSummaryQueue.java @@ -0,0 +1,265 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.queue; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +//import org.apache.log4j.MDC; +import org.apache.atlas.audit.model.AuditEventBase; +import org.apache.atlas.audit.provider.AuditHandler; +import org.apache.atlas.audit.provider.MiscUtil; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +/** + * This is a non-blocking queue with no limit on capacity. + */ +public class AuditSummaryQueue extends AuditQueue implements Runnable { + private static final Log logger = LogFactory + .getLog(AuditSummaryQueue.class); + + public static final String PROP_SUMMARY_INTERVAL = "summary.interval.ms"; + + LinkedBlockingQueue queue = new LinkedBlockingQueue(); + Thread consumerThread = null; + + static int threadCount = 0; + static final String DEFAULT_NAME = "summary"; + + private static final int MAX_DRAIN = 100000; + + private int maxSummaryIntervalMs = 5000; + + HashMap summaryMap = new HashMap(); + + public AuditSummaryQueue(AuditHandler consumer) { + super(consumer); + setName(DEFAULT_NAME); + } + + @Override + public void init(Properties props, String propPrefix) { + super.init(props, propPrefix); + maxSummaryIntervalMs = MiscUtil.getIntProperty(props, propPrefix + "." + + PROP_SUMMARY_INTERVAL, maxSummaryIntervalMs); + logger.info("maxSummaryInterval=" + maxSummaryIntervalMs + ", name=" + + getName()); + } + + /* + * (non-Javadoc) + * + * @see + * org.apache.ranger.audit.provider.AuditProvider#log(org.apache.ranger. + * audit.model.AuditEventBase) + */ + @Override + public boolean log(AuditEventBase event) { + // Add to the queue and return ASAP + if (queue.size() >= getMaxQueueSize()) { + return false; + } + queue.add(event); + return true; + } + + @Override + public boolean log(Collection events) { + boolean ret = true; + for (AuditEventBase event : events) { + ret = log(event); + if (!ret) { + break; + } + } + return ret; + } + + /* + * (non-Javadoc) + * + * @see org.apache.ranger.audit.provider.AuditProvider#start() + */ + @Override + public void start() { + if (consumer != null) { + consumer.start(); + } + + consumerThread = new Thread(this, this.getClass().getName() + + (threadCount++)); + consumerThread.setDaemon(true); + consumerThread.start(); + } + + /* + * (non-Javadoc) + * + * @see org.apache.ranger.audit.provider.AuditProvider#stop() + */ + @Override + public void stop() { + logger.info("Stop called. name=" + getName()); + setDrain(true); + try { + if (consumerThread != null) { + logger.info("Interrupting consumerThread. name=" + getName() + + ", consumer=" + + (consumer == null ? null : consumer.getName())); + + consumerThread.interrupt(); + } + } catch (Throwable t) { + // ignore any exception + } + consumerThread = null; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Runnable#run() + */ + @Override + public void run() { + try { + //This is done to clear the MDC context to avoid issue with Ranger Auditing for Knox + //MDC.clear(); + runLogAudit(); + } catch (Throwable t) { + logger.fatal("Exited thread without abnormaly. queue=" + getName(), + t); + } + } + + public void runLogAudit() { + + long lastDispatchTime = System.currentTimeMillis(); + + while (true) { + // Time to next dispatch + long nextDispatchDuration = lastDispatchTime + - System.currentTimeMillis() + maxSummaryIntervalMs; + + Collection eventList = new ArrayList(); + + try { + AuditEventBase event = null; + if (!isDrain() && nextDispatchDuration > 0) { + event = queue.poll(nextDispatchDuration, + TimeUnit.MILLISECONDS); + } else { + // For poll() is non blocking + event = queue.poll(); + } + + if (event != null) { + eventList.add(event); + queue.drainTo(eventList, MAX_DRAIN - 1); + } else { + // poll returned due to timeout, so reseting clock + nextDispatchDuration = lastDispatchTime + - System.currentTimeMillis() + maxSummaryIntervalMs; + lastDispatchTime = System.currentTimeMillis(); + } + } catch (InterruptedException e) { + logger.info("Caught exception in consumer thread. Shutdown might be in progress"); + } catch (Throwable t) { + logger.error("Caught error during processing request.", t); + } + + for (AuditEventBase event : eventList) { + // Add to hash map + String key = event.getEventKey(); + AuditSummary auditSummary = summaryMap.get(key); + if (auditSummary == null) { + auditSummary = new AuditSummary(); + auditSummary.event = event; + auditSummary.startTime = event.getEventTime(); + auditSummary.endTime = event.getEventTime(); + auditSummary.count = 1; + summaryMap.put(key, auditSummary); + } else { + auditSummary.endTime = event.getEventTime(); + auditSummary.count++; + } + } + + if (isDrain() || nextDispatchDuration <= 0) { + // Reset time just before sending the logs + lastDispatchTime = System.currentTimeMillis(); + + for (Map.Entry entry : summaryMap + .entrySet()) { + AuditSummary auditSummary = entry.getValue(); + auditSummary.event.setEventCount(auditSummary.count); + long timeDiff = auditSummary.endTime.getTime() + - auditSummary.startTime.getTime(); + timeDiff = timeDiff > 0 ? timeDiff : 1; + auditSummary.event.setEventDurationMS(timeDiff); + boolean ret = consumer.log(auditSummary.event); + if (!ret) { + // We need to drop this event + logFailedEvent(auditSummary.event); + } + } + summaryMap.clear(); + } + + if (isDrain()) { + if (summaryMap.isEmpty() && queue.isEmpty()) { + break; + } + if (isDrainMaxTimeElapsed()) { + logger.warn("Exiting polling loop because max time allowed reached. name=" + + getName() + + ", waited for " + + (stopTime - System.currentTimeMillis()) + " ms"); + } + } + + } + + logger.info("Exiting polling loop. name=" + getName()); + try { + // Call stop on the consumer + logger.info("Calling to stop consumer. name=" + getName() + + ", consumer.name=" + consumer.getName()); + consumer.stop(); + } catch (Throwable t) { + logger.error("Error while calling stop on consumer.", t); + } + logger.info("Exiting consumerThread.run() method. name=" + getName()); + } + + class AuditSummary { + Date startTime = null; + Date endTime = null; + int count = 0; + AuditEventBase event; + } +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/utils/AuthObjectUtil.java b/auth-audits/src/main/java/org/apache/atlas/audit/utils/AuthObjectUtil.java new file mode 100644 index 00000000000..3a612641630 --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/utils/AuthObjectUtil.java @@ -0,0 +1,47 @@ +package org.apache.atlas.audit.utils; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.text.SimpleDateFormat; + +public class AuthObjectUtil { + private static final Logger LOG = LoggerFactory.getLogger(AuthObjectUtil.class); + + private static ObjectMapper MAPPER = new ObjectMapper().setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")); + + public static String toJson(Object obj) { + String ret; + try { + if (obj instanceof JsonNode && ((JsonNode) obj).isTextual()) { + ret = ((JsonNode) obj).textValue(); + } else { + ret = MAPPER.writeValueAsString(obj); + } + }catch (IOException e){ + LOG.error("AuthObjectUtil.toJson()", e); + + ret = null; + } + return ret; + } + + public static T fromJson(String jsonStr, Class type) { + T ret = null; + + if (jsonStr != null) { + try { + ret = MAPPER.readValue(jsonStr, type); + } catch (IOException e) { + LOG.error("AuthObjectUtil.fromJson()", e); + + ret = null; + } + } + + return ret; + } +} diff --git a/auth-audits/src/main/java/org/apache/atlas/audit/utils/CredentialsProviderUtil.java b/auth-audits/src/main/java/org/apache/atlas/audit/utils/CredentialsProviderUtil.java new file mode 100644 index 00000000000..4fbac81606a --- /dev/null +++ b/auth-audits/src/main/java/org/apache/atlas/audit/utils/CredentialsProviderUtil.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.audit.utils; + +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CredentialsProviderUtil { + private static final Logger logger = LoggerFactory.getLogger(CredentialsProviderUtil.class); + + public static CredentialsProvider getBasicCredentials(String user, String password) { + CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(AuthScope.ANY, + new UsernamePasswordCredentials(user, password)); + return credentialsProvider; + } + +} diff --git a/auth-common/pom.xml b/auth-common/pom.xml new file mode 100644 index 00000000000..0e8a3fc28d2 --- /dev/null +++ b/auth-common/pom.xml @@ -0,0 +1,42 @@ + + + + apache-atlas + org.apache.atlas + 3.0.0-SNAPSHOT + + 4.0.0 + + auth-common + + + + commons-collections + commons-collections + + + commons-lang + commons-lang + + + com.fasterxml.jackson.core + jackson-annotations + 2.15.2 + compile + + + javax.xml.bind + jaxb-api + ${jaxb.api.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.databind.version} + compile + + + + \ No newline at end of file diff --git a/auth-common/src/main/java/org/apache/atlas/constants/RangerAtlasConstants.java b/auth-common/src/main/java/org/apache/atlas/constants/RangerAtlasConstants.java new file mode 100644 index 00000000000..768cf980ddf --- /dev/null +++ b/auth-common/src/main/java/org/apache/atlas/constants/RangerAtlasConstants.java @@ -0,0 +1,28 @@ +package org.apache.atlas.constants; + +public class RangerAtlasConstants { + + public static final String RESOURCE_SERVICE = "atlas-service"; + public static final String RESOURCE_TYPE_CATEGORY = "type-category"; + public static final String RESOURCE_TYPE_NAME = "type"; + public static final String RESOURCE_ENTITY_TYPE = "entity-type"; + public static final String RESOURCE_ENTITY_CLASSIFICATION = "entity-classification"; + public static final String RESOURCE_CLASSIFICATION = "classification"; + public static final String RESOURCE_ENTITY_ID = "entity"; + public static final String RESOURCE_ENTITY_LABEL = "entity-label"; + public static final String RESOURCE_ENTITY_BUSINESS_METADATA = "entity-business-metadata"; + public static final String RESOURCE_ENTITY_OWNER = "owner"; + public static final String RESOURCE_RELATIONSHIP_TYPE = "relationship-type"; + public static final String RESOURCE_END_ONE_ENTITY_TYPE = "end-one-entity-type"; + public static final String RESOURCE_END_ONE_ENTITY_CLASSIFICATION = "end-one-entity-classification"; + public static final String RESOURCE_END_ONE_ENTITY_ID = "end-one-entity"; + public static final String RESOURCE_END_TWO_ENTITY_TYPE = "end-two-entity-type"; + public static final String RESOURCE_END_TWO_ENTITY_CLASSIFICATION = "end-two-entity-classification"; + public static final String RESOURCE_END_TWO_ENTITY_ID = "end-two-entity"; + + public static final String ACCESS_TYPE_TYPE_READ = "type-read"; + + public static final String ENTITY_NOT_CLASSIFIED = "_NOT_CLASSIFIED"; + + public static final String COMPONENT_ACCESSTYPE_SEPARATOR = ":"; +} \ No newline at end of file diff --git a/auth-common/src/main/java/org/apache/atlas/plugin/model/GroupInfo.java b/auth-common/src/main/java/org/apache/atlas/plugin/model/GroupInfo.java new file mode 100644 index 00000000000..8ab39fe7b27 --- /dev/null +++ b/auth-common/src/main/java/org/apache/atlas/plugin/model/GroupInfo.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.apache.atlas.plugin.util.RangerUserStoreUtil; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.HashMap; +import java.util.Map; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class GroupInfo extends RangerBaseModelObject implements java.io.Serializable { + + private static final long serialVersionUID = 1L; + private String name; + private String description; + private Map otherAttributes; + + public GroupInfo() { + this(null, null, null); + } + + public GroupInfo(String name, String description, Map otherAttributes) { + setName(name); + setDescription(description); + setOtherAttributes(otherAttributes); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Map getOtherAttributes() { + return otherAttributes; + } + + public void setOtherAttributes(Map otherAttributes) { + this.otherAttributes = otherAttributes == null ? new HashMap<>() : otherAttributes; + } + + @Override + public String toString() { + return "{name=" + name + + ", description=" + description + + ", otherAttributes=" + RangerUserStoreUtil.getPrintableOptions(otherAttributes) + + "}"; + } + +} \ No newline at end of file diff --git a/auth-common/src/main/java/org/apache/atlas/plugin/model/NewAccessResourceImpl.java b/auth-common/src/main/java/org/apache/atlas/plugin/model/NewAccessResourceImpl.java new file mode 100644 index 00000000000..08410603870 --- /dev/null +++ b/auth-common/src/main/java/org/apache/atlas/plugin/model/NewAccessResourceImpl.java @@ -0,0 +1,253 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import org.apache.atlas.plugin.model.RangerServiceDef.RangerResourceDef; +import org.apache.commons.lang.ObjectUtils; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class NewAccessResourceImpl { + + private String RESOURCE_SEP = "/"; + private String RESOURCE_NAME_VAL_SEP = "="; + + private String ownerUser; + private Map elements; + private String stringifiedValue; + private String stringifiedCacheKeyValue; + private String leafName; + private RangerServiceDef serviceDef; + + public NewAccessResourceImpl() { + this(null, null); + } + + public NewAccessResourceImpl(Map elements) { + this(elements, null); + } + + public NewAccessResourceImpl(Map elements, String ownerUser) { + this.elements = elements; + this.ownerUser = ownerUser; + } + + public String getOwnerUser() { + return ownerUser; + } + + public boolean exists(String name) { + return elements != null && elements.containsKey(name); + } + + public Object getValue(String name) { + Object ret = null; + + if(elements != null && elements.containsKey(name)) { + ret = elements.get(name); + } + + return ret; + } + + public Set getKeys() { + Set ret = null; + + if(elements != null) { + ret = elements.keySet(); + } + + return ret; + } + + public void setOwnerUser(String ownerUser) { + this.ownerUser = ownerUser; + } + + public void setValue(String name, Object value) { + if(value == null) { + if(elements != null) { + elements.remove(name); + + if(elements.isEmpty()) { + elements = null; + } + } + } else { + if(elements == null) { + elements = new HashMap<>(); + } + elements.put(name, value); + } + + // reset, so that these will be computed again with updated elements + stringifiedValue = stringifiedCacheKeyValue = leafName = null; + } + + public void setServiceDef(final RangerServiceDef serviceDef) { + this.serviceDef = serviceDef; + this.stringifiedValue = this.stringifiedCacheKeyValue = this.leafName = null; + } + + public RangerServiceDef getServiceDef() { + return this.serviceDef; + } + + public String getLeafName() { + String ret = leafName; + + if(ret == null) { + if(serviceDef != null && serviceDef.getResources() != null) { + List resourceDefs = serviceDef.getResources(); + + for(int idx = resourceDefs.size() - 1; idx >= 0; idx--) { + RangerResourceDef resourceDef = resourceDefs.get(idx); + + if(resourceDef != null && exists(resourceDef.getName())) { + ret = leafName = resourceDef.getName(); + break; + } + } + } + } + + return ret; + } + + public String getAsString() { + String ret = stringifiedValue; + + if(ret == null) { + if(serviceDef != null && serviceDef.getResources() != null) { + StringBuilder sb = new StringBuilder(); + + for(RangerResourceDef resourceDef : serviceDef.getResources()) { + if(resourceDef == null || !exists(resourceDef.getName())) { + continue; + } + + if(sb.length() > 0) { + sb.append(RESOURCE_SEP); + } + + sb.append(getValue(resourceDef.getName())); + } + + if(sb.length() > 0) { + ret = stringifiedValue = sb.toString(); + } + } + } + + return ret; + } + + public String getCacheKey() { + String ret = stringifiedCacheKeyValue; + + if(ret == null) { + if(serviceDef != null && serviceDef.getResources() != null) { + StringBuilder sb = new StringBuilder(); + + for(RangerResourceDef resourceDef : serviceDef.getResources()) { + if(resourceDef == null || !exists(resourceDef.getName())) { + continue; + } + + if(sb.length() > 0) { + sb.append(RESOURCE_SEP); + } + + sb.append(resourceDef.getName()).append(RESOURCE_NAME_VAL_SEP).append(getValue(resourceDef.getName())); + } + + if(sb.length() > 0) { + ret = stringifiedCacheKeyValue = sb.toString(); + } + } + } + + return ret; + } + + public Map getAsMap() { + return elements == null ? Collections.EMPTY_MAP : Collections.unmodifiableMap(elements); + } + + public boolean equals(Object obj) { + if(obj == null || !(obj instanceof NewAccessResourceImpl)) { + return false; + } + + if(this == obj) { + return true; + } + + NewAccessResourceImpl other = (NewAccessResourceImpl) obj; + + return ObjectUtils.equals(ownerUser, other.ownerUser) && + ObjectUtils.equals(elements, other.elements); + } + + @Override + public int hashCode() { + int ret = 7; + + ret = 31 * ret + ObjectUtils.hashCode(ownerUser); + ret = 31 * ret + ObjectUtils.hashCode(elements); + + return ret; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerResourceImpl={"); + + sb.append("ownerUser={").append(ownerUser).append("} "); + + sb.append("elements={"); + if(elements != null) { + for(Map.Entry e : elements.entrySet()) { + sb.append(e.getKey()).append("=").append(e.getValue()).append("; "); + } + } + sb.append("} "); + + sb.append("}"); + + return sb; + } + + protected String getStringifiedValue() { return stringifiedValue; } + + protected void setStringifiedValue(String val) { this.stringifiedValue = val; } +} diff --git a/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerBaseModelObject.java b/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerBaseModelObject.java new file mode 100644 index 00000000000..704f545c0c2 --- /dev/null +++ b/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerBaseModelObject.java @@ -0,0 +1,170 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Date; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerBaseModelObject implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private Long id; + private String guid; + private Boolean isEnabled; + private String createdBy; + private String updatedBy; + private Date createTime; + private Date updateTime; + private Long version; + + public RangerBaseModelObject() { + setIsEnabled(null); + } + + public void updateFrom(RangerBaseModelObject other) { + setIsEnabled(other.getIsEnabled()); + } + + /** + * @return the id + */ + public Long getId() { + return id; + } + /** + * @param id the id to set + */ + public void setId(Long id) { + this.id = id; + } + /** + * @return the guid + */ + public String getGuid() { + return guid; + } + /** + * @param guid the guid to set + */ + public void setGuid(String guid) { + this.guid = guid; + } + /** + * @return the isEnabled + */ + public Boolean getIsEnabled() { + return isEnabled; + } + /** + * @param isEnabled the isEnabled to set + */ + public void setIsEnabled(Boolean isEnabled) { + this.isEnabled = isEnabled == null ? Boolean.TRUE : isEnabled; + } + /** + * @return the createdBy + */ + public String getCreatedBy() { + return createdBy; + } + /** + * @param createdBy the createdBy to set + */ + public void setCreatedBy(String createdBy) { + this.createdBy = createdBy; + } + /** + * @return the updatedBy + */ + public String getUpdatedBy() { + return updatedBy; + } + /** + * @param updatedBy the updatedBy to set + */ + public void setUpdatedBy(String updatedBy) { + this.updatedBy = updatedBy; + } + /** + * @return the createTime + */ + public Date getCreateTime() { + return createTime; + } + /** + * @param createTime the createTime to set + */ + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + /** + * @return the updateTime + */ + public Date getUpdateTime() { + return updateTime; + } + /** + * @param updateTime the updateTime to set + */ + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + /** + * @return the version + */ + public Long getVersion() { + return version; + } + /** + * @param version the version to set + */ + public void setVersion(Long version) { + this.version = version; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("id={").append(id).append("} "); + sb.append("guid={").append(guid).append("} "); + sb.append("isEnabled={").append(isEnabled).append("} "); + sb.append("createdBy={").append(createdBy).append("} "); + sb.append("updatedBy={").append(updatedBy).append("} "); + sb.append("createTime={").append(createTime).append("} "); + sb.append("updateTime={").append(updateTime).append("} "); + sb.append("version={").append(version).append("} "); + + return sb; + } +} diff --git a/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerPolicy.java b/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerPolicy.java new file mode 100644 index 00000000000..e4fcbdff9f4 --- /dev/null +++ b/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerPolicy.java @@ -0,0 +1,1776 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import org.apache.commons.collections.CollectionUtils; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; + +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/* +RangerPolicy and other model and util in this package are extracted out from auth-agents-common module +to avoid the circular dependency when ABAC authorizer was implemented. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerPolicy extends RangerBaseModelObject implements java.io.Serializable { + private static final ObjectMapper mapper = new ObjectMapper(); + + public static final String POLICY_TYPE_ACCESS = "ACCESS"; + public static final String POLICY_TYPE_DATAMASK = "DATA_MASK"; + public static final String POLICY_TYPE_ROWFILTER = "ROW_FILTER"; + public static final String POLICY_TYPE_AUDIT = "AUDIT"; + + public static final String[] POLICY_TYPES = new String[] { + POLICY_TYPE_ACCESS, + POLICY_TYPE_DATAMASK, + POLICY_TYPE_ROWFILTER + }; + + public static final String MASK_TYPE_NULL = "MASK_NULL"; + public static final String MASK_TYPE_NONE = "MASK_NONE"; + public static final String MASK_TYPE_CUSTOM = "CUSTOM"; + + public static final int POLICY_PRIORITY_NORMAL = 0; + public static final int POLICY_PRIORITY_OVERRIDE = 1; + + public static final String POLICY_PRIORITY_NAME_NORMAL = "NORMAL"; + public static final String POLICY_PRIORITY_NAME_OVERRIDE = "OVERRIDE"; + + public static final Comparator POLICY_ID_COMPARATOR = new PolicyIdComparator(); + private static final Logger LOG = LoggerFactory.getLogger(RangerPolicy.class); + + // For future use + private static final long serialVersionUID = 1L; + + private String service; + private String name; + private String policyType; + private Integer policyPriority; + private String description; + private String resourceSignature; + private Boolean isAuditEnabled; + private Map resources; + private List conditions; + private List policyItems; + private List denyPolicyItems; + private List allowExceptions; + private List denyExceptions; + private List dataMaskPolicyItems; + private List rowFilterPolicyItems; + private String serviceType; + private Map options; + private List validitySchedules; + private List policyLabels; + private String zoneName; + private Boolean isDenyAllElse; + private Map attributes; + private String policyFilterCriteria; + private String policyResourceCategory; + + @JsonIgnore + private JsonNode filterCriteriaNode; + + public RangerPolicy() { + this(null, null, null, null, null, null, null, null, null, null, null); + } + + public RangerPolicy(String service, String name, String policyType, Integer policyPriority, String description, Map resources, List policyItems, String resourceSignature, Map options, List validitySchedules, List policyLables) { + this(service, name, policyType, policyPriority, description, resources, policyItems, resourceSignature, options, validitySchedules, policyLables, null); + } + + public RangerPolicy(String service, String name, String policyType, Integer policyPriority, String description, Map resources, List policyItems, String resourceSignature, Map options, List validitySchedules, List policyLables, String zoneName) { + this(service, name, policyType, policyPriority, description, resources, policyItems, resourceSignature, options, validitySchedules, policyLables, zoneName, null); + } + + public RangerPolicy(String service, String name, String policyType, Integer policyPriority, String description, Map resources, List policyItems, String resourceSignature, Map options, List validitySchedules, List policyLables, String zoneName, List conditions) { + this(service, name, policyType, policyPriority, description, resources, policyItems, resourceSignature, options, validitySchedules, policyLables, zoneName, conditions, null); + } + + public RangerPolicy(String service, String name, String policyType, Integer policyPriority, String description, Map resources, List policyItems, String resourceSignature, Map options, List validitySchedules, List policyLables, String zoneName, List conditions, Boolean isDenyAllElse) { + this(service, name, policyType, policyPriority, description, resources, policyItems, resourceSignature, options, validitySchedules, policyLables, zoneName, conditions, null, null, null); + } + + /** + * @param service + * @param name + * @param policyType + * @param description + * @param resources + * @param policyItems + * @param resourceSignature TODO + */ + public RangerPolicy(String service, String name, String policyType, Integer policyPriority, String description, Map resources, List policyItems, String resourceSignature, Map options, List validitySchedules, List policyLables, String zoneName, List conditions, Boolean isDenyAllElse, String policyFilterCriteria, String policyResourceCategory) { + super(); + + setService(service); + setName(name); + setPolicyType(policyType); + setPolicyPriority(policyPriority); + setDescription(description); + setResourceSignature(resourceSignature); + setIsAuditEnabled(null); + setResources(resources); + setPolicyItems(policyItems); + setDenyPolicyItems(null); + setAllowExceptions(null); + setDenyExceptions(null); + setDataMaskPolicyItems(null); + setRowFilterPolicyItems(null); + setOptions(options); + setValiditySchedules(validitySchedules); + setPolicyLabels(policyLables); + setZoneName(zoneName); + setConditions(conditions); + setIsDenyAllElse(isDenyAllElse); + setPolicyFilterCriteria(null); + setPolicyResourceCategory(null); + + } + + /** + * @param other + */ + public void updateFrom(RangerPolicy other) { + super.updateFrom(other); + + setService(other.getService()); + setName(other.getName()); + setPolicyType(other.getPolicyType()); + setPolicyPriority(other.getPolicyPriority()); + setDescription(other.getDescription()); + setResourceSignature(other.getResourceSignature()); + setIsAuditEnabled(other.getIsAuditEnabled()); + setResources(other.getResources()); + setConditions(other.getConditions()); + setPolicyItems(other.getPolicyItems()); + setDenyPolicyItems(other.getDenyPolicyItems()); + setAllowExceptions(other.getAllowExceptions()); + setDenyExceptions(other.getDenyExceptions()); + setDataMaskPolicyItems(other.getDataMaskPolicyItems()); + setRowFilterPolicyItems(other.getRowFilterPolicyItems()); + setServiceType(other.getServiceType()); + setOptions(other.getOptions()); + setValiditySchedules(other.getValiditySchedules()); + setPolicyLabels(other.getPolicyLabels()); + setZoneName(other.getZoneName()); + setIsDenyAllElse(other.getIsDenyAllElse()); + setPolicyFilterCriteria(other.getPolicyFilterCriteria()); + setPolicyResourceCategory(other.getPolicyResourceCategory()); + } + + public Map getAttributes() { + return attributes; + } + + public void setAttributes(Map attributes) { + this.attributes = attributes; + } + + /** + * @return the type + */ + public String getService() { + return service; + } + + /** + * @param service the type to set + */ + public void setService(String service) { + this.service = service; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the policyType + */ + public String getPolicyType() { + return policyType; + } + + /** + * @param policyType the policyType to set + */ + public void setPolicyType(String policyType) { + this.policyType = policyType; + } + + /** + * @return the policyPriority + */ + public Integer getPolicyPriority() { + return policyPriority; + } + + /** + * @param policyPriority the policyPriority to set + */ + public void setPolicyPriority(Integer policyPriority) { + this.policyPriority = policyPriority == null ? RangerPolicy.POLICY_PRIORITY_NORMAL : policyPriority; + } + + /** + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * @param description the description to set + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * @return the resourceSignature + */ + public String getResourceSignature() { + return resourceSignature; + } + + /** + * @param resourceSignature the resourceSignature to set + */ + public void setResourceSignature(String resourceSignature) { + this.resourceSignature = resourceSignature; + } + + /** + * @return the isAuditEnabled + */ + public Boolean getIsAuditEnabled() { + return isAuditEnabled; + } + + /** + * @param isAuditEnabled the isEnabled to set + */ + public void setIsAuditEnabled(Boolean isAuditEnabled) { + this.isAuditEnabled = isAuditEnabled == null ? Boolean.TRUE : isAuditEnabled; + } + + public String getServiceType() { + return serviceType; + } + + public void setServiceType(String serviceType) { + this.serviceType = serviceType; + } + + public List getPolicyLabels() { + return policyLabels; + } + + public void setPolicyLabels(List policyLabels) { + if (this.policyLabels == null) { + this.policyLabels = new ArrayList<>(); + } + + if (this.policyLabels == policyLabels) { + return; + } + + this.policyLabels.clear(); + + if (policyLabels != null) { + this.policyLabels.addAll(policyLabels); + } + } + + /** + * @return the resources + */ + public Map getResources() { + return resources; + } + + /** + * @param resources the resources to set + */ + public void setResources(Map resources) { + if(this.resources == null) { + this.resources = new HashMap<>(); + } + + if(this.resources == resources) { + return; + } + + this.resources.clear(); + + if(resources != null) { + for(Map.Entry e : resources.entrySet()) { + this.resources.put(e.getKey(), e.getValue()); + } + } + } + + /** + * @return the policyItems + */ + public List getPolicyItems() { + return policyItems; + } + + /** + * @param policyItems the policyItems to set + */ + public void setPolicyItems(List policyItems) { + if(this.policyItems == null) { + this.policyItems = new ArrayList<>(); + } + + if(this.policyItems == policyItems) { + return; + } + + this.policyItems.clear(); + + if(policyItems != null) { + this.policyItems.addAll(policyItems); + } + } + + /** + * @return the denyPolicyItems + */ + public List getDenyPolicyItems() { + return denyPolicyItems; + } + + /** + * @param denyPolicyItems the denyPolicyItems to set + */ + public void setDenyPolicyItems(List denyPolicyItems) { + if(this.denyPolicyItems == null) { + this.denyPolicyItems = new ArrayList<>(); + } + + if(this.denyPolicyItems == denyPolicyItems) { + return; + } + + this.denyPolicyItems.clear(); + + if(denyPolicyItems != null) { + this.denyPolicyItems.addAll(denyPolicyItems); + } + } + + /** + * @return the allowExceptions + */ + public List getAllowExceptions() { + return allowExceptions; + } + + /** + * @param allowExceptions the allowExceptions to set + */ + public void setAllowExceptions(List allowExceptions) { + if(this.allowExceptions == null) { + this.allowExceptions = new ArrayList<>(); + } + + if(this.allowExceptions == allowExceptions) { + return; + } + + this.allowExceptions.clear(); + + if(allowExceptions != null) { + this.allowExceptions.addAll(allowExceptions); + } + } + + /** + * @return the denyExceptions + */ + public List getDenyExceptions() { + return denyExceptions; + } + + /** + * @param denyExceptions the denyExceptions to set + */ + public void setDenyExceptions(List denyExceptions) { + if(this.denyExceptions == null) { + this.denyExceptions = new ArrayList<>(); + } + + if(this.denyExceptions == denyExceptions) { + return; + } + + this.denyExceptions.clear(); + + if(denyExceptions != null) { + this.denyExceptions.addAll(denyExceptions); + } + } + + public List getDataMaskPolicyItems() { + return dataMaskPolicyItems; + } + + public void setDataMaskPolicyItems(List dataMaskPolicyItems) { + if(this.dataMaskPolicyItems == null) { + this.dataMaskPolicyItems = new ArrayList<>(); + } + + if(this.dataMaskPolicyItems == dataMaskPolicyItems) { + return; + } + + this.dataMaskPolicyItems.clear(); + + if(dataMaskPolicyItems != null) { + this.dataMaskPolicyItems.addAll(dataMaskPolicyItems); + } + } + + public List getRowFilterPolicyItems() { + return rowFilterPolicyItems; + } + + public void setRowFilterPolicyItems(List rowFilterPolicyItems) { + if(this.rowFilterPolicyItems == null) { + this.rowFilterPolicyItems = new ArrayList<>(); + } + + if(this.rowFilterPolicyItems == rowFilterPolicyItems) { + return; + } + + this.rowFilterPolicyItems.clear(); + + if(rowFilterPolicyItems != null) { + this.rowFilterPolicyItems.addAll(rowFilterPolicyItems); + } + } + + public Map getOptions() { return options; } + + public void setOptions(Map options) { + if (this.options == null) { + this.options = new HashMap<>(); + } + if (this.options == options) { + return; + } + this.options.clear(); + + if(options != null) { + for(Map.Entry e : options.entrySet()) { + this.options.put(e.getKey(), e.getValue()); + } + } + } + + public List getValiditySchedules() { return validitySchedules; } + + public void setValiditySchedules(List validitySchedules) { + if (this.validitySchedules == null) { + this.validitySchedules = new ArrayList<>(); + } + if (this.validitySchedules == validitySchedules) { + return; + } + this.validitySchedules.clear(); + + if(validitySchedules != null) { + this.validitySchedules.addAll(validitySchedules); + } + } + public String getZoneName() { return zoneName; } + + public void setZoneName(String zoneName) { + this.zoneName = zoneName; + } + + /** + * @return the conditions + */ + public List getConditions() { return conditions; } + /** + * @param conditions the conditions to set + */ + public void setConditions(List conditions) { + this.conditions = conditions; + } + + public Boolean getIsDenyAllElse() { + return isDenyAllElse; + } + + public void setIsDenyAllElse(Boolean isDenyAllElse) { + this.isDenyAllElse = isDenyAllElse == null ? Boolean.FALSE : isDenyAllElse; + } + + @JsonIgnore + public String getAtlasGuid() { + return getGuid().length() > 36 ? getGuid().substring(0, 36) : getGuid(); + } + + public String getPolicyFilterCriteria() { + return policyFilterCriteria; + } + + public void setPolicyFilterCriteria(String policyFilterCriteria) { + this.policyFilterCriteria = policyFilterCriteria; + } + + public String getPolicyResourceCategory() { + return policyResourceCategory; + } + + public void setPolicyResourceCategory(String policyResourceCategory) { + this.policyResourceCategory = policyResourceCategory; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public JsonNode getPolicyParsedFilterCriteria(String rootKey) { + // only parse json once + if (this.filterCriteriaNode == null) { + if (StringUtils.isEmpty(this.policyFilterCriteria)) { + return null; + } + try { + this.filterCriteriaNode = mapper.readTree(this.policyFilterCriteria); + } catch (JsonProcessingException e) { + LOG.error("ABAC_AUTH: parsing filterCriteria failed for policy={}, filterCriteria={}", this.getGuid(), this.policyFilterCriteria); + } + } + + if (filterCriteriaNode != null && filterCriteriaNode.get(rootKey) != null) { + return filterCriteriaNode.get(rootKey); + } + return null; + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerPolicy={"); + + super.toString(sb); + + sb.append("service={").append(service).append("} "); + sb.append("name={").append(name).append("} "); + sb.append("policyType={").append(policyType).append("} "); + sb.append("policyPriority={").append(policyPriority).append("} "); + sb.append("description={").append(description).append("} "); + sb.append("resourceSignature={").append(resourceSignature).append("} "); + sb.append("isAuditEnabled={").append(isAuditEnabled).append("} "); + sb.append("serviceType={").append(serviceType).append("} "); + + sb.append("resources={"); + if(resources != null) { + for(Map.Entry e : resources.entrySet()) { + sb.append(e.getKey()).append("={"); + e.getValue().toString(sb); + sb.append("} "); + } + } + sb.append("} "); + sb.append("policyLabels={"); + if(policyLabels != null) { + for(String policyLabel : policyLabels) { + if(policyLabel != null) { + sb.append(policyLabel).append(" "); + } + } + } + sb.append("} "); + + sb.append("policyConditions={"); + if(conditions != null) { + for(RangerPolicyItemCondition condition : conditions) { + if(condition != null) { + condition.toString(sb); + } + } + } + sb.append("} "); + + sb.append("policyItems={"); + if(policyItems != null) { + for(RangerPolicyItem policyItem : policyItems) { + if(policyItem != null) { + policyItem.toString(sb); + } + } + } + sb.append("} "); + + sb.append("denyPolicyItems={"); + if(denyPolicyItems != null) { + for(RangerPolicyItem policyItem : denyPolicyItems) { + if(policyItem != null) { + policyItem.toString(sb); + } + } + } + sb.append("} "); + + sb.append("allowExceptions={"); + if(allowExceptions != null) { + for(RangerPolicyItem policyItem : allowExceptions) { + if(policyItem != null) { + policyItem.toString(sb); + } + } + } + sb.append("} "); + + sb.append("denyExceptions={"); + if(denyExceptions != null) { + for(RangerPolicyItem policyItem : denyExceptions) { + if(policyItem != null) { + policyItem.toString(sb); + } + } + } + sb.append("} "); + + sb.append("dataMaskPolicyItems={"); + if(dataMaskPolicyItems != null) { + for(RangerDataMaskPolicyItem dataMaskPolicyItem : dataMaskPolicyItems) { + if(dataMaskPolicyItem != null) { + dataMaskPolicyItem.toString(sb); + } + } + } + sb.append("} "); + + sb.append("rowFilterPolicyItems={"); + if(rowFilterPolicyItems != null) { + for(RangerRowFilterPolicyItem rowFilterPolicyItem : rowFilterPolicyItems) { + if(rowFilterPolicyItem != null) { + rowFilterPolicyItem.toString(sb); + } + } + } + sb.append("} "); + + sb.append("options={"); + if(options != null) { + for(Map.Entry e : options.entrySet()) { + sb.append(e.getKey()).append("={"); + sb.append(e.getValue().toString()); + sb.append("} "); + } + } + sb.append("} "); + + //sb.append("validitySchedules={").append(validitySchedules).append("} "); + sb.append("validitySchedules={"); + if (CollectionUtils.isNotEmpty(validitySchedules)) { + for (RangerValiditySchedule schedule : validitySchedules) { + if (schedule != null) { + sb.append("schedule={").append(schedule).append("}"); + } + } + } + sb.append(", zoneName=").append(zoneName); + + sb.append(", policyFilterCriteria=").append(policyFilterCriteria); + + sb.append(", policyResourceCategory=").append(policyResourceCategory); + + sb.append(", isDenyAllElse={").append(isDenyAllElse).append("} "); + + sb.append("}"); + + sb.append("}"); + + return sb; + } + + static class PolicyIdComparator implements Comparator, java.io.Serializable { + @Override + public int compare(RangerPolicy me, RangerPolicy other) { + return Long.compare(me.getId(), other.getId()); + } + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerPolicyResource implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private List values; + private Boolean isExcludes; + private Boolean isRecursive; + + public RangerPolicyResource() { + this((List)null, null, null); + } + + public RangerPolicyResource(String value) { + setValue(value); + setIsExcludes(null); + setIsRecursive(null); + } + + public RangerPolicyResource(String value, Boolean isExcludes, Boolean isRecursive) { + setValue(value); + setIsExcludes(isExcludes); + setIsRecursive(isRecursive); + } + + public RangerPolicyResource(List values, Boolean isExcludes, Boolean isRecursive) { + setValues(values); + setIsExcludes(isExcludes); + setIsRecursive(isRecursive); + } + + /** + * @return the values + */ + public List getValues() { + return values; + } + + /** + * @param values the values to set + */ + public void setValues(List values) { + if(this.values == null) { + this.values = new ArrayList<>(); + } + + if(this.values == values) { + return; + } + + this.values.clear(); + + if(values != null) { + this.values.addAll(values); + } + } + + /** + * @param value the value to set + */ + public void setValue(String value) { + if(this.values == null) { + this.values = new ArrayList<>(); + } + + this.values.clear(); + + this.values.add(value); + } + + /** + * @return the isExcludes + */ + public Boolean getIsExcludes() { + return isExcludes; + } + + /** + * @param isExcludes the isExcludes to set + */ + public void setIsExcludes(Boolean isExcludes) { + this.isExcludes = isExcludes == null ? Boolean.FALSE : isExcludes; + } + + /** + * @return the isRecursive + */ + public Boolean getIsRecursive() { + return isRecursive; + } + + /** + * @param isRecursive the isRecursive to set + */ + public void setIsRecursive(Boolean isRecursive) { + this.isRecursive = isRecursive == null ? Boolean.FALSE : isRecursive; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerPolicyResource={"); + sb.append("values={"); + if(values != null) { + for(String value : values) { + sb.append(value).append(" "); + } + } + sb.append("} "); + sb.append("isExcludes={").append(isExcludes).append("} "); + sb.append("isRecursive={").append(isRecursive).append("} "); + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((isExcludes == null) ? 0 : isExcludes.hashCode()); + result = prime * result + + ((isRecursive == null) ? 0 : isRecursive.hashCode()); + result = prime * result + + ((values == null) ? 0 : values.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerPolicyResource other = (RangerPolicyResource) obj; + if (isExcludes == null) { + if (other.isExcludes != null) + return false; + } else if (!isExcludes.equals(other.isExcludes)) + return false; + if (isRecursive == null) { + if (other.isRecursive != null) + return false; + } else if (!isRecursive.equals(other.isRecursive)) + return false; + if (values == null) { + if (other.values != null) + return false; + } else if (!values.equals(other.values)) + return false; + return true; + } + + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerPolicyItem implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private List accesses; + private List users; + private List groups; + private List roles; + private List conditions; + private Boolean delegateAdmin; + + public RangerPolicyItem() { + this(null, null, null, null, null, null); + } + + public RangerPolicyItem(List accessTypes, List users, List groups, List roles, List conditions, Boolean delegateAdmin) { + setAccesses(accessTypes); + setUsers(users); + setGroups(groups); + setRoles(roles); + setConditions(conditions); + setDelegateAdmin(delegateAdmin); + } + + /** + * @return the accesses + */ + public List getAccesses() { + return accesses; + } + /** + * @param accesses the accesses to set + */ + public void setAccesses(List accesses) { + if(this.accesses == null) { + this.accesses = new ArrayList<>(); + } + + if(this.accesses == accesses) { + return; + } + + this.accesses.clear(); + + if(accesses != null) { + this.accesses.addAll(accesses); + } + } + /** + * @return the users + */ + public List getUsers() { + return users; + } + /** + * @param users the users to set + */ + public void setUsers(List users) { + if(this.users == null) { + this.users = new ArrayList<>(); + } + + if(this.users == users) { + return; + } + + this.users.clear(); + + if(users != null) { + this.users.addAll(users); + } + } + /** + * @return the groups + */ + public List getGroups() { + return groups; + } + /** + * @param groups the groups to set + */ + public void setGroups(List groups) { + if(this.groups == null) { + this.groups = new ArrayList<>(); + } + + if(this.groups == groups) { + return; + } + + this.groups.clear(); + + if(groups != null) { + this.groups.addAll(groups); + } + } + /** + * @return the roles + */ + public List getRoles() { + return roles; + } + /** + * @param roles the roles to set + */ + public void setRoles(List roles) { + if(this.roles == null) { + this.roles = new ArrayList<>(); + } + + if(this.roles == roles) { + return; + } + + this.roles.clear(); + + if(roles != null) { + this.roles.addAll(roles); + } + } + /** + * @return the conditions + */ + public List getConditions() { + return conditions; + } + /** + * @param conditions the conditions to set + */ + public void setConditions(List conditions) { + if(this.conditions == null) { + this.conditions = new ArrayList<>(); + } + + if(this.conditions == conditions) { + return; + } + + this.conditions.clear(); + + if(conditions != null) { + this.conditions.addAll(conditions); + } + } + + /** + * @return the delegateAdmin + */ + public Boolean getDelegateAdmin() { + return delegateAdmin; + } + + /** + * @param delegateAdmin the delegateAdmin to set + */ + public void setDelegateAdmin(Boolean delegateAdmin) { + this.delegateAdmin = delegateAdmin == null ? Boolean.FALSE : delegateAdmin; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerPolicyItem={"); + + sb.append("accessTypes={"); + if(accesses != null) { + for(RangerPolicyItemAccess access : accesses) { + if(access != null) { + access.toString(sb); + } + } + } + sb.append("} "); + + sb.append("users={"); + if(users != null) { + for(String user : users) { + if(user != null) { + sb.append(user).append(" "); + } + } + } + sb.append("} "); + + sb.append("groups={"); + if(groups != null) { + for(String group : groups) { + if(group != null) { + sb.append(group).append(" "); + } + } + } + sb.append("} "); + + sb.append("roles={"); + if(roles != null) { + for(String role : roles) { + if(role != null) { + sb.append(role).append(" "); + } + } + } + sb.append("} "); + + sb.append("conditions={"); + if(conditions != null) { + for(RangerPolicyItemCondition condition : conditions) { + if(condition != null) { + condition.toString(sb); + } + } + } + sb.append("} "); + + sb.append("delegateAdmin={").append(delegateAdmin).append("} "); + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((accesses == null) ? 0 : accesses.hashCode()); + result = prime * result + + ((conditions == null) ? 0 : conditions.hashCode()); + result = prime * result + + ((delegateAdmin == null) ? 0 : delegateAdmin.hashCode()); + result = prime * result + + ((roles == null) ? 0 : roles.hashCode()); + result = prime * result + + ((groups == null) ? 0 : groups.hashCode()); + result = prime * result + ((users == null) ? 0 : users.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerPolicyItem other = (RangerPolicyItem) obj; + if (accesses == null) { + if (other.accesses != null) + return false; + } else if (!accesses.equals(other.accesses)) + return false; + if (conditions == null) { + if (other.conditions != null) + return false; + } else if (!conditions.equals(other.conditions)) + return false; + if (delegateAdmin == null) { + if (other.delegateAdmin != null) + return false; + } else if (!delegateAdmin.equals(other.delegateAdmin)) + return false; + if (roles == null) { + if (other.roles != null) + return false; + } else if (!roles.equals(other.roles)) + return false; + if (groups == null) { + if (other.groups != null) + return false; + } else if (!groups.equals(other.groups)) + return false; + if (users == null) { + if (other.users != null) + return false; + } else if (!users.equals(other.users)) + return false; + return true; + + } + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerDataMaskPolicyItem extends RangerPolicyItem implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private RangerPolicyItemDataMaskInfo dataMaskInfo; + + public RangerDataMaskPolicyItem() { + this(null, null, null, null, null, null, null); + } + + public RangerDataMaskPolicyItem(List accesses, RangerPolicyItemDataMaskInfo dataMaskDetail, List users, List groups, List roles, List conditions, Boolean delegateAdmin) { + super(accesses, users, groups, roles, conditions, delegateAdmin); + + setDataMaskInfo(dataMaskDetail); + } + + /** + * @return the dataMaskInfo + */ + public RangerPolicyItemDataMaskInfo getDataMaskInfo() { + return dataMaskInfo; + } + + /** + * @param dataMaskInfo the dataMaskInfo to set + */ + public void setDataMaskInfo(RangerPolicyItemDataMaskInfo dataMaskInfo) { + this.dataMaskInfo = dataMaskInfo == null ? new RangerPolicyItemDataMaskInfo() : dataMaskInfo; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((dataMaskInfo == null) ? 0 : dataMaskInfo.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if(! super.equals(obj)) + return false; + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerDataMaskPolicyItem other = (RangerDataMaskPolicyItem) obj; + if (dataMaskInfo == null) { + if (other.dataMaskInfo != null) + return false; + } else if (!dataMaskInfo.equals(other.dataMaskInfo)) + return false; + return true; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerDataMaskPolicyItem={"); + + super.toString(sb); + + sb.append("dataMaskInfo={"); + if(dataMaskInfo != null) { + dataMaskInfo.toString(sb); + } + sb.append("} "); + + sb.append("}"); + + return sb; + } + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerRowFilterPolicyItem extends RangerPolicyItem implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private RangerPolicyItemRowFilterInfo rowFilterInfo; + + public RangerRowFilterPolicyItem() { + this(null, null, null, null, null, null, null); + } + + public RangerRowFilterPolicyItem(RangerPolicyItemRowFilterInfo rowFilterInfo, List accesses, List users, List groups, List roles, List conditions, Boolean delegateAdmin) { + super(accesses, users, groups, roles, conditions, delegateAdmin); + + setRowFilterInfo(rowFilterInfo); + } + + /** + * @return the rowFilterInfo + */ + public RangerPolicyItemRowFilterInfo getRowFilterInfo() { + return rowFilterInfo; + } + + /** + * @param rowFilterInfo the rowFilterInfo to set + */ + public void setRowFilterInfo(RangerPolicyItemRowFilterInfo rowFilterInfo) { + this.rowFilterInfo = rowFilterInfo == null ? new RangerPolicyItemRowFilterInfo() : rowFilterInfo; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((rowFilterInfo == null) ? 0 : rowFilterInfo.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if(! super.equals(obj)) + return false; + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerRowFilterPolicyItem other = (RangerRowFilterPolicyItem) obj; + if (rowFilterInfo == null) { + if (other.rowFilterInfo != null) + return false; + } else if (!rowFilterInfo.equals(other.rowFilterInfo)) + return false; + return true; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerRowFilterPolicyItem={"); + + super.toString(sb); + + sb.append("rowFilterInfo={"); + if(rowFilterInfo != null) { + rowFilterInfo.toString(sb); + } + sb.append("} "); + + sb.append("}"); + + return sb; + } + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerPolicyItemAccess implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String type; + private Boolean isAllowed; + + public RangerPolicyItemAccess() { + this(null, null); + } + + public RangerPolicyItemAccess(String type) { + this(type, null); + } + + public RangerPolicyItemAccess(String type, Boolean isAllowed) { + setType(type); + setIsAllowed(isAllowed); + } + + /** + * @return the type + */ + public String getType() { + return type; + } + + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + + /** + * @return the isAllowed + */ + public Boolean getIsAllowed() { + return isAllowed; + } + + /** + * @param isAllowed the isAllowed to set + */ + public void setIsAllowed(Boolean isAllowed) { + this.isAllowed = isAllowed == null ? Boolean.TRUE : isAllowed; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerPolicyItemAccess={"); + sb.append("type={").append(type).append("} "); + sb.append("isAllowed={").append(isAllowed).append("} "); + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((isAllowed == null) ? 0 : isAllowed.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerPolicyItemAccess other = (RangerPolicyItemAccess) obj; + if (isAllowed == null) { + if (other.isAllowed != null) + return false; + } else if (!isAllowed.equals(other.isAllowed)) + return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + return true; + } + + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerPolicyItemCondition implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String type; + private List values; + + public RangerPolicyItemCondition() { + this(null, null); + } + + public RangerPolicyItemCondition(String type, List values) { + setType(type); + setValues(values); + } + + /** + * @return the type + */ + public String getType() { + return type; + } + + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + + /** + * @return the value + */ + public List getValues() { + return values; + } + + /** + * @param values the value to set + */ + public void setValues(List values) { + if (this.values == null) { + this.values = new ArrayList<>(); + } + + if(this.values == values) { + return; + } + + this.values.clear(); + + if(values != null) { + this.values.addAll(values); + } + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerPolicyCondition={"); + sb.append("type={").append(type).append("} "); + sb.append("values={"); + if(values != null) { + for(String value : values) { + sb.append(value).append(" "); + } + } + sb.append("} "); + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + + ((values == null) ? 0 : values.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerPolicyItemCondition other = (RangerPolicyItemCondition) obj; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + if (values == null) { + if (other.values != null) + return false; + } else if (!values.equals(other.values)) + return false; + return true; + } + + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerPolicyItemDataMaskInfo implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String dataMaskType; + private String conditionExpr; + private String valueExpr; + + public RangerPolicyItemDataMaskInfo() { } + + public RangerPolicyItemDataMaskInfo(String dataMaskType, String conditionExpr, String valueExpr) { + setDataMaskType(dataMaskType); + setConditionExpr(conditionExpr); + setValueExpr(valueExpr); + } + + public RangerPolicyItemDataMaskInfo(RangerPolicyItemDataMaskInfo that) { + this.dataMaskType = that.dataMaskType; + this.conditionExpr = that.conditionExpr; + this.valueExpr = that.valueExpr; + } + + public String getDataMaskType() { + return dataMaskType; + } + + public void setDataMaskType(String dataMaskType) { + this.dataMaskType = dataMaskType; + } + + public String getConditionExpr() { + return conditionExpr; + } + + public void setConditionExpr(String conditionExpr) { + this.conditionExpr = conditionExpr; + } + + public String getValueExpr() { + return valueExpr; + } + + public void setValueExpr(String valueExpr) { + this.valueExpr = valueExpr; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((dataMaskType == null) ? 0 : dataMaskType.hashCode()); + result = prime * result + ((conditionExpr == null) ? 0 : conditionExpr.hashCode()); + result = prime * result + ((valueExpr == null) ? 0 : valueExpr.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerPolicyItemDataMaskInfo other = (RangerPolicyItemDataMaskInfo) obj; + if (dataMaskType == null) { + if (other.dataMaskType != null) + return false; + } else if (!dataMaskType.equals(other.dataMaskType)) + return false; + if (conditionExpr == null) { + if (other.conditionExpr != null) + return false; + } else if (!conditionExpr.equals(other.conditionExpr)) + return false; + if (valueExpr == null) { + if (other.valueExpr != null) + return false; + } else if (!valueExpr.equals(other.valueExpr)) + return false; + return true; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerPolicyItemDataMaskInfo={"); + + sb.append("dataMaskType={").append(dataMaskType).append("} "); + sb.append("conditionExpr={").append(conditionExpr).append("} "); + sb.append("valueExpr={").append(valueExpr).append("} "); + + sb.append("}"); + + return sb; + } + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerPolicyItemRowFilterInfo implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String filterExpr; + + public RangerPolicyItemRowFilterInfo() { } + + public RangerPolicyItemRowFilterInfo(String filterExpr) { + setFilterExpr(filterExpr); + } + + public RangerPolicyItemRowFilterInfo(RangerPolicyItemRowFilterInfo that) { + this.filterExpr = that.filterExpr; + } + + public String getFilterExpr() { + return filterExpr; + } + + public void setFilterExpr(String filterExpr) { + this.filterExpr = filterExpr; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((filterExpr == null) ? 0 : filterExpr.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerPolicyItemRowFilterInfo other = (RangerPolicyItemRowFilterInfo) obj; + if (filterExpr == null) { + if (other.filterExpr != null) + return false; + } else if (!filterExpr.equals(other.filterExpr)) + return false; + return true; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerPolicyItemRowFilterInfo={"); + + sb.append("filterExpr={").append(filterExpr).append("} "); + + sb.append("}"); + + return sb; + } + } +} diff --git a/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerRole.java b/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerRole.java new file mode 100644 index 00000000000..8e47316240f --- /dev/null +++ b/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerRole.java @@ -0,0 +1,192 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import org.apache.commons.collections.MapUtils; +import com.fasterxml.jackson.annotation.JsonInclude; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerRole extends RangerBaseModelObject implements java.io.Serializable { + public static final String KEY_USER = "user"; + public static final String KEY_GROUP = "group"; + + private static final long serialVersionUID = 1L; + private String name; + private String description; + private Map options; + private List users; + private List groups; + private List roles; + private String createdByUser; + + public RangerRole() { + this(null, null, null, null, null, null); + } + + public RangerRole(String name, String description, Map options, List users, List groups) { + this(name, description, options, users, groups, null); + } + + public RangerRole(String name, String description, Map options, List users, List groups, List roles) { + setName(name); + setDescription(description); + setOptions(options); + setUsers(users); + setGroups(groups); + setRoles(roles); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Map getOptions() { + return options; + } + + public void setOptions(Map options) { + this.options = options == null ? new HashMap<>() : options; + } + + public List getUsers() { + return users; + } + + public void setUsers(List users) { + this.users = users == null ? new ArrayList<>() : users; + } + + public List getGroups() { + return groups; + } + + public void setGroups(List groups) { + this.groups = groups == null ? new ArrayList<>() : groups; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles == null ? new ArrayList<>() : roles; + } + + public String getCreatedByUser() { + return createdByUser; + } + + public void setCreatedByUser(String createdByUser) { + this.createdByUser = createdByUser; + } + + @Override + public String toString() { + return "{name=" + name + + ", description=" + description + + ", options=" + getPrintableOptions(options) + + ", users=" + users + + ", groups=" + groups + + ", roles=" + roles + + ", createdByUser=" + createdByUser + + "}"; + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RoleMember implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private String name; + private boolean isAdmin; + + public RoleMember() { + this(null, false); + } + public RoleMember(String name, boolean isAdmin) { + setName(name); + setIsAdmin(isAdmin); + } + public void setName(String name) { + this.name = name; + } + public void setIsAdmin(boolean isAdmin) { + this.isAdmin = isAdmin; + } + public String getName() { return name; } + public boolean getIsAdmin() { return isAdmin; } + + @Override + public String toString() { + return "{" + name + ", " + isAdmin + "}"; + } + @Override + public int hashCode() { + return Objects.hash(name, isAdmin); + } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RoleMember other = (RoleMember) obj; + return Objects.equals(name, other.name) && isAdmin == other.isAdmin; + } + } + + private String getPrintableOptions(Map options) { + if (MapUtils.isEmpty(options)) return "{}"; + StringBuilder ret = new StringBuilder(); + ret.append("{"); + for (Map.Entry entry : options.entrySet()) { + ret.append(entry.getKey()).append(", ").append("[").append(entry.getValue()).append("]").append(","); + } + ret.append("}"); + return ret.toString(); + } + +} \ No newline at end of file diff --git a/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerServiceDef.java b/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerServiceDef.java new file mode 100644 index 00000000000..43b4546f7b8 --- /dev/null +++ b/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerServiceDef.java @@ -0,0 +1,3065 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + + +@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerServiceDef extends RangerBaseModelObject implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + public static final String OPTION_ENABLE_DENY_AND_EXCEPTIONS_IN_POLICIES = "enableDenyAndExceptionsInPolicies"; + + private String name; + private String displayName; + private String implClass; + private String label; + private String description; + private String rbKeyLabel; + private String rbKeyDescription; + private Map options; + private List configs; + private List resources; + private List accessTypes; + private List policyConditions; + private List contextEnrichers; + private List enums; + private RangerDataMaskDef dataMaskDef; + private RangerRowFilterDef rowFilterDef; + + public RangerServiceDef() { + this(null, null, null, null, null, null, null, null, null, null, null, null, null); + } + + public RangerServiceDef(String name, String implClass, String label, String description, Map options, List configs, List resources, List accessTypes, List policyConditions, List contextEnrichers, List enums) { + this(name, implClass, label, description, options, configs, resources, accessTypes, policyConditions, contextEnrichers, enums, null, null); + } + + /** + * @param name + * @param implClass + * @param label + * @param description + * @param options + * @param configs + * @param resources + * @param accessTypes + * @param policyConditions + * @param contextEnrichers + * @param dataMaskDef + * @param enums + */ + public RangerServiceDef(String name, String implClass, String label, String description, Map options, List configs, List resources, List accessTypes, List policyConditions, List contextEnrichers, List enums, RangerDataMaskDef dataMaskDef, RangerRowFilterDef rowFilterDef) { + super(); + + setName(name); + setImplClass(implClass); + setLabel(label); + setDescription(description); + setConfigs(configs); + setOptions(options); + setResources(resources); + setAccessTypes(accessTypes); + setPolicyConditions(policyConditions); + setContextEnrichers(contextEnrichers); + setEnums(enums); + setDataMaskDef(dataMaskDef); + setRowFilterDef(rowFilterDef); + } + + public RangerServiceDef(String name, String displayName, String implClass, String label, String description, + Map options, List configs, + List modifiedResourceDefs, List accessTypes, + List policyConditions, List contextEnrichers, + List enums) { + this(name, implClass, label, description, options, configs, modifiedResourceDefs, accessTypes, policyConditions, contextEnrichers, enums); + this.setDisplayName(displayName); + } + + /** + * @param other + */ + public void updateFrom(RangerServiceDef other) { + super.updateFrom(other); + + setName(other.getName()); + setDisplayName(other.getDisplayName()); + setImplClass(other.getImplClass()); + setLabel(other.getLabel()); + setDescription(other.getDescription()); + setRbKeyLabel(other.getRbKeyLabel()); + setRbKeyDescription(other.getRbKeyDescription()); + setOptions(other.getOptions()); + setConfigs(other.getConfigs()); + setResources(other.getResources()); + setAccessTypes(other.getAccessTypes()); + setPolicyConditions(other.getPolicyConditions()); + setContextEnrichers(other.getContextEnrichers()); + setEnums(other.getEnums()); + setDataMaskDef(other.getDataMaskDef()); + setRowFilterDef(other.getRowFilterDef()); + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the implClass + */ + public String getImplClass() { + return implClass; + } + + /** + * @param implClass the implClass to set + */ + public void setImplClass(String implClass) { + this.implClass = implClass; + } + + /** + * @return the label + */ + public String getLabel() { + return label; + } + + /** + * @param label the label to set + */ + public void setLabel(String label) { + this.label = label; + } + + /** + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * @param description the description to set + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * @return the rbKeyLabel + */ + public String getRbKeyLabel() { + return rbKeyLabel; + } + + /** + * @param rbKeyLabel the rbKeyLabel to set + */ + public void setRbKeyLabel(String rbKeyLabel) { + this.rbKeyLabel = rbKeyLabel; + } + + /** + * @return the rbKeyDescription + */ + public String getRbKeyDescription() { + return rbKeyDescription; + } + + /** + * @param rbKeyDescription the rbKeyDescription to set + */ + public void setRbKeyDescription(String rbKeyDescription) { + this.rbKeyDescription = rbKeyDescription; + } + + /** + * @return the configs + */ + public List getConfigs() { + return configs; + } + + /** + * @param configs the configs to set + */ + public void setConfigs(List configs) { + if(this.configs == null) { + this.configs = new ArrayList<>(); + } else + + if(this.configs == configs) { + return; + } + + this.configs.clear(); + + if(configs != null) { + this.configs.addAll(configs); + } + } + + /** + * @return the options + */ + public Map getOptions() { + return options; + } + + /** + * @param options the options to set + */ + public void setOptions(Map options) { + if(this.options == null) { + this.options = new HashMap<>(); + } else if(this.options == options) { + return; + } + + this.options.clear(); + + if(options != null) { + for(Map.Entry entry : options.entrySet()) { + this.options.put(entry.getKey(), entry.getValue()); + } + } + } + + /** + * @return the resources + */ + public List getResources() { + return resources; + } + + /** + * @param resources the resources to set + */ + public void setResources(List resources) { + if(this.resources == null) { + this.resources = new ArrayList<>(); + } + + if(this.resources == resources) { + return; + } + + this.resources.clear(); + + if(resources != null) { + this.resources.addAll(resources); + } + } + + /** + * @return the accessTypes + */ + public List getAccessTypes() { + return accessTypes; + } + + /** + * @param accessTypes the accessTypes to set + */ + public void setAccessTypes(List accessTypes) { + if(this.accessTypes == null) { + this.accessTypes = new ArrayList<>(); + } + + if(this.accessTypes == accessTypes) { + return; + } + + this.accessTypes.clear(); + + if(accessTypes != null) { + this.accessTypes.addAll(accessTypes); + } + } + + /** + * @return the policyConditions + */ + public List getPolicyConditions() { + return policyConditions; + } + + /** + * @param policyConditions the policyConditions to set + */ + public void setPolicyConditions(List policyConditions) { + if(this.policyConditions == null) { + this.policyConditions = new ArrayList<>(); + } + + if(this.policyConditions == policyConditions) { + return; + } + + this.policyConditions.clear(); + + if(policyConditions != null) { + this.policyConditions.addAll(policyConditions); + } + } + + /** + * @return the contextEnrichers + */ + public List getContextEnrichers() { + return contextEnrichers; + } + + /** + * @param contextEnrichers the contextEnrichers to set + */ + public void setContextEnrichers(List contextEnrichers) { + if(this.contextEnrichers == null) { + this.contextEnrichers = new ArrayList<>(); + } + + if(this.contextEnrichers == contextEnrichers) { + return; + } + + this.contextEnrichers.clear(); + + if(contextEnrichers != null) { + this.contextEnrichers.addAll(contextEnrichers); + } + } + + /** + * @return the enums + */ + public List getEnums() { + return enums; + } + + /** + * @param enums the enums to set + */ + public void setEnums(List enums) { + if(this.enums == null) { + this.enums = new ArrayList<>(); + } + + if(this.enums == enums) { + return; + } + + this.enums.clear(); + + if(enums != null) { + this.enums.addAll(enums); + } + } + + public RangerDataMaskDef getDataMaskDef() { + return dataMaskDef; + } + + public void setDataMaskDef(RangerDataMaskDef dataMaskDef) { + this.dataMaskDef = dataMaskDef == null ? new RangerDataMaskDef() : dataMaskDef; + } + + public RangerRowFilterDef getRowFilterDef() { + return rowFilterDef; + } + + public void setRowFilterDef(RangerRowFilterDef rowFilterDef) { + this.rowFilterDef = rowFilterDef == null ? new RangerRowFilterDef() : rowFilterDef; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerServiceDef={"); + + super.toString(sb); + + sb.append("name={").append(name).append("} "); + sb.append("displayName={").append(displayName).append("} "); + sb.append("implClass={").append(implClass).append("} "); + sb.append("label={").append(label).append("} "); + sb.append("description={").append(description).append("} "); + sb.append("rbKeyLabel={").append(rbKeyLabel).append("} "); + sb.append("rbKeyDescription={").append(rbKeyDescription).append("} "); + + sb.append("options={"); + if(options != null) { + for(Map.Entry entry : options.entrySet()) { + sb.append(entry.getKey()).append("=").append(entry.getValue()).append(" "); + } + } + sb.append("} "); + + sb.append("configs={"); + if(configs != null) { + for(RangerServiceConfigDef config : configs) { + if(config != null) { + config.toString(sb); + } + } + } + sb.append("} "); + + sb.append("resources={"); + if(resources != null) { + for(RangerResourceDef resource : resources) { + if(resource != null) { + resource.toString(sb); + } + } + } + sb.append("} "); + + sb.append("accessTypes={"); + if(accessTypes != null) { + for(RangerAccessTypeDef accessType : accessTypes) { + if(accessType != null) { + accessType.toString(sb); + } + } + } + sb.append("} "); + + sb.append("policyConditions={"); + if(policyConditions != null) { + for(RangerPolicyConditionDef policyCondition : policyConditions) { + if(policyCondition != null) { + policyCondition.toString(sb); + } + } + } + sb.append("} "); + + sb.append("contextEnrichers={"); + if(contextEnrichers != null) { + for(RangerContextEnricherDef contextEnricher : contextEnrichers) { + if(contextEnricher != null) { + contextEnricher.toString(sb); + } + } + } + sb.append("} "); + + sb.append("enums={"); + if(enums != null) { + for(RangerEnumDef e : enums) { + if(e != null) { + e.toString(sb); + } + } + } + sb.append("} "); + + sb.append("dataMaskDef={"); + if(dataMaskDef != null) { + dataMaskDef.toString(sb); + } + sb.append("} "); + + sb.append("rowFilterDef={"); + if(rowFilterDef != null) { + rowFilterDef.toString(sb); + } + sb.append("} "); + + sb.append("}"); + + return sb; + } + + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerEnumDef implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private Long itemId; + private String name; + private List elements; + private Integer defaultIndex; + + public RangerEnumDef() { + this(null, null, null, null); + } + + public RangerEnumDef(Long itemId, String name, List elements, Integer defaultIndex) { + setItemId(itemId); + setName(name); + setElements(elements); + setDefaultIndex(defaultIndex); + } + + /** + * @return the itemId + */ + public Long getItemId() { + return itemId; + } + + /** + * @param itemId the itemId to set + */ + public void setItemId(Long itemId) { + this.itemId = itemId; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the elements + */ + public List getElements() { + return elements; + } + + /** + * @param elements the elements to set + */ + public void setElements(List elements) { + if(this.elements == null) { + this.elements = new ArrayList<>(); + } + + if(this.elements == elements) { + return; + } + + this.elements.clear(); + + if(elements != null) { + this.elements.addAll(elements); + } + } + + /** + * @return the defaultIndex + */ + public Integer getDefaultIndex() { + return defaultIndex; + } + + /** + * @param defaultIndex the defaultIndex to set + */ + public void setDefaultIndex(Integer defaultIndex) { + this.defaultIndex = (defaultIndex != null && this.elements.size() > defaultIndex) ? defaultIndex : 0; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerEnumDef={"); + sb.append("itemId={").append(itemId).append("} "); + sb.append("name={").append(name).append("} "); + sb.append("elements={"); + if(elements != null) { + for(RangerEnumElementDef element : elements) { + if(element != null) { + element.toString(sb); + } + } + } + sb.append("} "); + sb.append("defaultIndex={").append(defaultIndex).append("} "); + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((itemId == null) ? 0 : itemId.hashCode()); + result = prime * result + + ((defaultIndex == null) ? 0 : defaultIndex.hashCode()); + result = prime * result + + ((elements == null) ? 0 : elements.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerEnumDef other = (RangerEnumDef) obj; + if (itemId == null) { + if (other.itemId != null) + return false; + } else if (other.itemId == null || !itemId.equals(other.itemId)) + return false; + + if (defaultIndex == null) { + if (other.defaultIndex != null) + return false; + } else if (!defaultIndex.equals(other.defaultIndex)) + return false; + if (elements == null) { + if (other.elements != null) + return false; + } else if (!elements.equals(other.elements)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + } + + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerEnumElementDef implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private Long itemId; + private String name; + private String label; + private String rbKeyLabel; + + public RangerEnumElementDef() { + this(null, null, null, null); + } + + public RangerEnumElementDef(Long itemId, String name, String label, String rbKeyLabel) { + setItemId(itemId); + setName(name); + setLabel(label); + setRbKeyLabel(rbKeyLabel); + } + + /** + * @return the itemId + */ + public Long getItemId() { + return itemId; + } + + /** + * @param itemId the itemId to set + */ + public void setItemId(Long itemId) { + this.itemId = itemId; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the label + */ + public String getLabel() { + return label; + } + + /** + * @param label the label to set + */ + public void setLabel(String label) { + this.label = label; + } + + /** + * @return the rbKeyLabel + */ + public String getRbKeyLabel() { + return rbKeyLabel; + } + + /** + * @param rbKeyLabel the rbKeyLabel to set + */ + public void setRbKeyLabel(String rbKeyLabel) { + this.rbKeyLabel = rbKeyLabel; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerEnumElementDef={"); + sb.append("itemId={").append(itemId).append("} "); + sb.append("name={").append(name).append("} "); + sb.append("label={").append(label).append("} "); + sb.append("rbKeyLabel={").append(rbKeyLabel).append("} "); + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((itemId == null) ? 0 : itemId.hashCode()); + result = prime * result + ((label == null) ? 0 : label.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + + ((rbKeyLabel == null) ? 0 : rbKeyLabel.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerEnumElementDef other = (RangerEnumElementDef) obj; + if (itemId == null) { + if (other.itemId != null) { + return false; + } + } else if (other.itemId == null || !itemId.equals(other.itemId)) { + return false; + } + + if (label == null) { + if (other.label != null) + return false; + } else if (!label.equals(other.label)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (rbKeyLabel == null) { + if (other.rbKeyLabel != null) + return false; + } else if (!rbKeyLabel.equals(other.rbKeyLabel)) + return false; + return true; + } + } + + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerServiceConfigDef implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private Long itemId; + private String name; + private String type; + private String subType; + private Boolean mandatory; + private String defaultValue; + private String validationRegEx; + private String validationMessage; + private String uiHint; + private String label; + private String description; + private String rbKeyLabel; + private String rbKeyDescription; + private String rbKeyValidationMessage; + + public RangerServiceConfigDef() { + this(null, null, null, null, null, null, null, null, null, null, null, null, null, null); + } + + public RangerServiceConfigDef(Long itemId, String name, String type, String subType, Boolean mandatory, String defaultValue, String validationRegEx, String validationMessage, String uiHint, String label, String description, String rbKeyLabel, String rbKeyDescription, String rbKeyValidationMessage) { + setItemId(itemId); + setName(name); + setType(type); + setSubType(subType); + setMandatory(mandatory); + setDefaultValue(defaultValue); + setValidationRegEx(validationRegEx); + setValidationMessage(validationMessage); + setUiHint(uiHint); + setLabel(label); + setDescription(description); + setRbKeyLabel(rbKeyLabel); + setRbKeyDescription(rbKeyDescription); + setRbKeyValidationMessage(rbKeyValidationMessage); + } + + /** + * @return the itemId + */ + public Long getItemId() { + return itemId; + } + + /** + * @param itemId the itemId to set + */ + public void setItemId(Long itemId) { + this.itemId = itemId; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the type + */ + public String getType() { + return type; + } + + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + + /** + * @return the subType + */ + public String getSubType() { + return subType; + } + + /** + * @param subType the subType to set + */ + public void setSubType(String subType) { + this.subType = subType; + } + + /** + * @return the mandatory + */ + public Boolean getMandatory() { + return mandatory; + } + + /** + * @param mandatory the mandatory to set + */ + public void setMandatory(Boolean mandatory) { + this.mandatory = mandatory == null ? Boolean.FALSE : mandatory; + } + + /** + * @return the defaultValue + */ + public String getDefaultValue() { + return defaultValue; + } + + /** + * @param defaultValue the defaultValue to set + */ + public void setDefaultValue(String defaultValue) { + this.defaultValue = defaultValue; + } + + /** + * @return the validationRegEx + */ + public String getValidationRegEx() { + return validationRegEx; + } + + /** + * @param validationRegEx the validationRegEx to set + */ + public void setValidationRegEx(String validationRegEx) { + this.validationRegEx = validationRegEx; + } + + /** + * @return the validationMessage + */ + public String getValidationMessage() { + return validationMessage; + } + + /** + * @param validationMessage the validationMessage to set + */ + public void setValidationMessage(String validationMessage) { + this.validationMessage = validationMessage; + } + + /** + * @return the uiHint + */ + public String getUiHint() { + return uiHint; + } + + /** + * @param uiHint the uiHint to set + */ + public void setUiHint(String uiHint) { + this.uiHint = uiHint; + } + + /** + * @return the label + */ + public String getLabel() { + return label; + } + + /** + * @param label the label to set + */ + public void setLabel(String label) { + this.label = label; + } + + /** + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * @param description the description to set + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * @return the rbKeyLabel + */ + public String getRbKeyLabel() { + return rbKeyLabel; + } + + /** + * @param rbKeyLabel the rbKeyLabel to set + */ + public void setRbKeyLabel(String rbKeyLabel) { + this.rbKeyLabel = rbKeyLabel; + } + + /** + * @return the rbKeyDescription + */ + public String getRbKeyDescription() { + return rbKeyDescription; + } + + /** + * @param rbKeyDescription the rbKeyDescription to set + */ + public void setRbKeyDescription(String rbKeyDescription) { + this.rbKeyDescription = rbKeyDescription; + } + + /** + * @return the rbKeyValidationMessage + */ + public String getRbKeyValidationMessage() { + return rbKeyValidationMessage; + } + + /** + * @param rbKeyValidationMessage the rbKeyValidationMessage to set + */ + public void setRbKeyValidationMessage(String rbKeyValidationMessage) { + this.rbKeyValidationMessage = rbKeyValidationMessage; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerServiceConfigDef={"); + sb.append("itemId={").append(name).append("} "); + sb.append("name={").append(name).append("} "); + sb.append("type={").append(type).append("} "); + sb.append("subType={").append(subType).append("} "); + sb.append("mandatory={").append(mandatory).append("} "); + sb.append("defaultValue={").append(defaultValue).append("} "); + sb.append("validationRegEx={").append(validationRegEx).append("} "); + sb.append("validationMessage={").append(validationMessage).append("} "); + sb.append("uiHint={").append(uiHint).append("} "); + sb.append("label={").append(label).append("} "); + sb.append("description={").append(description).append("} "); + sb.append("rbKeyLabel={").append(rbKeyLabel).append("} "); + sb.append("rbKeyDescription={").append(rbKeyDescription).append("} "); + sb.append("rbKeyValidationMessage={").append(rbKeyValidationMessage).append("} "); + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((defaultValue == null) ? 0 : defaultValue.hashCode()); + result = prime * result + + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((label == null) ? 0 : label.hashCode()); + result = prime * result + + ((mandatory == null) ? 0 : mandatory.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime + * result + + ((rbKeyDescription == null) ? 0 : rbKeyDescription + .hashCode()); + result = prime * result + + ((rbKeyLabel == null) ? 0 : rbKeyLabel.hashCode()); + result = prime + * result + + ((rbKeyValidationMessage == null) ? 0 + : rbKeyValidationMessage.hashCode()); + result = prime * result + + ((subType == null) ? 0 : subType.hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + + ((uiHint == null) ? 0 : uiHint.hashCode()); + result = prime + * result + + ((validationMessage == null) ? 0 : validationMessage + .hashCode()); + result = prime + * result + + ((validationRegEx == null) ? 0 : validationRegEx + .hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerServiceConfigDef other = (RangerServiceConfigDef) obj; + if (defaultValue == null) { + if (other.defaultValue != null) + return false; + } else if (!defaultValue.equals(other.defaultValue)) + return false; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (label == null) { + if (other.label != null) + return false; + } else if (!label.equals(other.label)) + return false; + if (mandatory == null) { + if (other.mandatory != null) + return false; + } else if (!mandatory.equals(other.mandatory)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (rbKeyDescription == null) { + if (other.rbKeyDescription != null) + return false; + } else if (!rbKeyDescription.equals(other.rbKeyDescription)) + return false; + if (rbKeyLabel == null) { + if (other.rbKeyLabel != null) + return false; + } else if (!rbKeyLabel.equals(other.rbKeyLabel)) + return false; + if (rbKeyValidationMessage == null) { + if (other.rbKeyValidationMessage != null) + return false; + } else if (!rbKeyValidationMessage + .equals(other.rbKeyValidationMessage)) + return false; + if (subType == null) { + if (other.subType != null) + return false; + } else if (!subType.equals(other.subType)) + return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + if (uiHint == null) { + if (other.uiHint != null) + return false; + } else if (!uiHint.equals(other.uiHint)) + return false; + if (validationMessage == null) { + if (other.validationMessage != null) + return false; + } else if (!validationMessage.equals(other.validationMessage)) + return false; + if (validationRegEx == null) { + if (other.validationRegEx != null) + return false; + } else if (!validationRegEx.equals(other.validationRegEx)) + return false; + return true; + } + } + + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerResourceDef implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private Long itemId = null; + private String name = null; + private String type = null; + private Integer level = null; + private String parent = null; + private Boolean mandatory = null; + private Boolean lookupSupported = null; + private Boolean recursiveSupported = null; + private Boolean excludesSupported = null; + private String matcher = null; + private Map matcherOptions = null; + private String validationRegEx = null; + private String validationMessage = null; + private String uiHint = null; + private String label = null; + private String description = null; + private String rbKeyLabel = null; + private String rbKeyDescription = null; + private String rbKeyValidationMessage = null; + private Set accessTypeRestrictions = null; + private Boolean isValidLeaf = null; + + public RangerResourceDef() { + this(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); + } + + public RangerResourceDef(RangerResourceDef other) { + setItemId(other.getItemId()); + setName(other.getName()); + setType(other.getType()); + setLevel(other.getLevel()); + setParent(other.getParent()); + setMandatory(other.getMandatory()); + setLookupSupported(other.getLookupSupported()); + setRecursiveSupported(other.getRecursiveSupported()); + setExcludesSupported(other.getExcludesSupported()); + setMatcher(other.getMatcher()); + setMatcherOptions(other.getMatcherOptions()); + setValidationRegEx(other.getValidationRegEx()); + setValidationMessage(other.getValidationMessage()); + setUiHint(other.getUiHint()); + setLabel(other.getLabel()); + setDescription(other.getDescription()); + setRbKeyLabel(other.getRbKeyLabel()); + setRbKeyDescription(other.getRbKeyDescription()); + setRbKeyValidationMessage(other.getRbKeyValidationMessage()); + setAccessTypeRestrictions(other.getAccessTypeRestrictions()); + setIsValidLeaf(other.getIsValidLeaf()); + } + + public RangerResourceDef(Long itemId, String name, String type, Integer level, String parent, Boolean mandatory, Boolean lookupSupported, Boolean recursiveSupported, Boolean excludesSupported, String matcher, Map matcherOptions, String validationRegEx, String validationMessage, String uiHint, String label, String description, String rbKeyLabel, String rbKeyDescription, String rbKeyValidationMessage, Set accessTypeRestrictions, Boolean isValidLeaf) { + setItemId(itemId); + setName(name); + setType(type); + setLevel(level); + setParent(parent); + setMandatory(mandatory); + setLookupSupported(lookupSupported); + setRecursiveSupported(recursiveSupported); + setExcludesSupported(excludesSupported); + setMatcher(matcher); + setMatcherOptions(matcherOptions); + setValidationRegEx(validationRegEx); + setValidationMessage(validationMessage); + setUiHint(uiHint); + setLabel(label); + setDescription(description); + setRbKeyLabel(rbKeyLabel); + setRbKeyDescription(rbKeyDescription); + setRbKeyValidationMessage(rbKeyValidationMessage); + setAccessTypeRestrictions(accessTypeRestrictions); + setIsValidLeaf(isValidLeaf); + } + + /** + * @return the itemId + */ + public Long getItemId() { + return itemId; + } + + /** + * @param itemId the itemId to set + */ + public void setItemId(Long itemId) { + this.itemId = itemId; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the type + */ + public String getType() { + return type; + } + + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + + /** + * @return the level + */ + public Integer getLevel() { + return level; + } + + /** + * @param level the level to set + */ + public void setLevel(Integer level) { + this.level = level == null ? 1 : level; + } + + /** + * @return the parent + */ + public String getParent() { + return parent; + } + + /** + * @param parent the parent to set + */ + public void setParent(String parent) { + this.parent = parent; + } + + /** + * @return the mandatory + */ + public Boolean getMandatory() { + return mandatory; + } + + /** + * @param mandatory the mandatory to set + */ + public void setMandatory(Boolean mandatory) { + this.mandatory = mandatory == null ? Boolean.FALSE : mandatory; + } + + /** + * @return the lookupSupported + */ + public Boolean getLookupSupported() { + return lookupSupported; + } + + /** + * @param lookupSupported the lookupSupported to set + */ + public void setLookupSupported(Boolean lookupSupported) { + this.lookupSupported = lookupSupported == null ? Boolean.FALSE : lookupSupported; + } + + /** + * @return the recursiveSupported + */ + public Boolean getRecursiveSupported() { + return recursiveSupported; + } + + /** + * @param recursiveSupported the recursiveSupported to set + */ + public void setRecursiveSupported(Boolean recursiveSupported) { + this.recursiveSupported = recursiveSupported == null ? Boolean.FALSE : recursiveSupported; + } + + /** + * @return the excludesSupported + */ + public Boolean getExcludesSupported() { + return excludesSupported; + } + + /** + * @param excludesSupported the excludesSupported to set + */ + public void setExcludesSupported(Boolean excludesSupported) { + this.excludesSupported = excludesSupported == null ? Boolean.FALSE : excludesSupported; + } + + /** + * @return the matcher + */ + public String getMatcher() { + return matcher; + } + + /** + * @param matcher the matcher to set + */ + public void setMatcher(String matcher) { + this.matcher = matcher; + } + + /** + * @return the matcherOptions + */ + public Map getMatcherOptions() { + return matcherOptions; + } + + /** + * @param matcherOptions the matcherOptions to set + */ + public void setMatcherOptions(Map matcherOptions) { + this.matcherOptions = matcherOptions == null ? new HashMap() : new HashMap(matcherOptions); + } + + /** + * @return the validationRegEx + */ + public String getValidationRegEx() { + return validationRegEx; + } + + /** + * @param validationRegEx the validationRegEx to set + */ + public void setValidationRegEx(String validationRegEx) { + this.validationRegEx = validationRegEx; + } + + /** + * @return the validationMessage + */ + public String getValidationMessage() { + return validationMessage; + } + + /** + * @param validationMessage the validationMessage to set + */ + public void setValidationMessage(String validationMessage) { + this.validationMessage = validationMessage; + } + + /** + * @return the uiHint + */ + public String getUiHint() { + return uiHint; + } + + /** + * @param uiHint the uiHint to set + */ + public void setUiHint(String uiHint) { + this.uiHint = uiHint; + } + + /** + * @return the label + */ + public String getLabel() { + return label; + } + + /** + * @param label the label to set + */ + public void setLabel(String label) { + this.label = label; + } + + /** + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * @param description the description to set + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * @return the rbKeyLabel + */ + public String getRbKeyLabel() { + return rbKeyLabel; + } + + /** + * @param rbKeyLabel the rbKeyLabel to set + */ + public void setRbKeyLabel(String rbKeyLabel) { + this.rbKeyLabel = rbKeyLabel; + } + + /** + * @return the rbKeyDescription + */ + public String getRbKeyDescription() { + return rbKeyDescription; + } + + /** + * @param rbKeyDescription the rbKeyDescription to set + */ + public void setRbKeyDescription(String rbKeyDescription) { + this.rbKeyDescription = rbKeyDescription; + } + + /** + * @return the rbKeyValidationMessage + */ + public String getRbKeyValidationMessage() { + return rbKeyValidationMessage; + } + + /** + * @param rbKeyValidationMessage the rbKeyValidationMessage to set + */ + public void setRbKeyValidationMessage(String rbKeyValidationMessage) { + this.rbKeyValidationMessage = rbKeyValidationMessage; + } + + public Set getAccessTypeRestrictions() { + return accessTypeRestrictions; + } + + public void setAccessTypeRestrictions(Set accessTypeRestrictions) { + this.accessTypeRestrictions = accessTypeRestrictions == null ? new HashSet() : new HashSet(accessTypeRestrictions); + } + + public Boolean getIsValidLeaf() { return isValidLeaf; } + + public void setIsValidLeaf(Boolean isValidLeaf) { + this.isValidLeaf = isValidLeaf; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerResourceDef={"); + sb.append("itemId={").append(itemId).append("} "); + sb.append("name={").append(name).append("} "); + sb.append("type={").append(type).append("} "); + sb.append("level={").append(level).append("} "); + sb.append("parent={").append(parent).append("} "); + sb.append("mandatory={").append(mandatory).append("} "); + sb.append("lookupSupported={").append(lookupSupported).append("} "); + sb.append("recursiveSupported={").append(recursiveSupported).append("} "); + sb.append("excludesSupported={").append(excludesSupported).append("} "); + sb.append("matcher={").append(matcher).append("} "); + sb.append("matcherOptions={").append(matcherOptions).append("} "); + sb.append("validationRegEx={").append(validationRegEx).append("} "); + sb.append("validationMessage={").append(validationMessage).append("} "); + sb.append("uiHint={").append(uiHint).append("} "); + sb.append("label={").append(label).append("} "); + sb.append("description={").append(description).append("} "); + sb.append("rbKeyLabel={").append(rbKeyLabel).append("} "); + sb.append("rbKeyDescription={").append(rbKeyDescription).append("} "); + sb.append("rbKeyValidationMessage={").append(rbKeyValidationMessage).append("} "); + sb.append("accessTypeRestrictions={").append(accessTypeRestrictions == null ? "null" : accessTypeRestrictions.toString()).append("} "); + sb.append("isValidLeaf={").append(isValidLeaf == null ? "null" : isValidLeaf.toString()).append("} "); + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((description == null) ? 0 : description.hashCode()); + result = prime + * result + + ((excludesSupported == null) ? 0 : excludesSupported + .hashCode()); + result = prime * result + ((label == null) ? 0 : label.hashCode()); + result = prime * result + ((level == null) ? 0 : level.hashCode()); + result = prime + * result + + ((lookupSupported == null) ? 0 : lookupSupported + .hashCode()); + result = prime * result + + ((mandatory == null) ? 0 : mandatory.hashCode()); + result = prime * result + + ((matcher == null) ? 0 : matcher.hashCode()); + result = prime + * result + + ((matcherOptions == null) ? 0 : matcherOptions.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + + ((parent == null) ? 0 : parent.hashCode()); + result = prime + * result + + ((rbKeyDescription == null) ? 0 : rbKeyDescription + .hashCode()); + result = prime * result + + ((rbKeyLabel == null) ? 0 : rbKeyLabel.hashCode()); + result = prime + * result + + ((rbKeyValidationMessage == null) ? 0 + : rbKeyValidationMessage.hashCode()); + result = prime + * result + + ((recursiveSupported == null) ? 0 : recursiveSupported + .hashCode()); + result = prime * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + + ((uiHint == null) ? 0 : uiHint.hashCode()); + result = prime + * result + + ((validationMessage == null) ? 0 : validationMessage + .hashCode()); + result = prime + * result + + ((validationRegEx == null) ? 0 : validationRegEx + .hashCode()); + result = prime + * result + + ((accessTypeRestrictions == null) ? 0 : accessTypeRestrictions.hashCode()); + result = prime + * result + + ((isValidLeaf == null) ? 0 : isValidLeaf.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerResourceDef other = (RangerResourceDef) obj; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (excludesSupported == null) { + if (other.excludesSupported != null) + return false; + } else if (!excludesSupported.equals(other.excludesSupported)) + return false; + if (label == null) { + if (other.label != null) + return false; + } else if (!label.equals(other.label)) + return false; + if (level == null) { + if (other.level != null) + return false; + } else if (!level.equals(other.level)) + return false; + if (lookupSupported == null) { + if (other.lookupSupported != null) + return false; + } else if (!lookupSupported.equals(other.lookupSupported)) + return false; + if (mandatory == null) { + if (other.mandatory != null) + return false; + } else if (!mandatory.equals(other.mandatory)) + return false; + if (matcher == null) { + if (other.matcher != null) + return false; + } else if (!matcher.equals(other.matcher)) + return false; + if (matcherOptions == null) { + if (other.matcherOptions != null) + return false; + } else if (!matcherOptions.equals(other.matcherOptions)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (parent == null) { + if (other.parent != null) + return false; + } else if (!parent.equals(other.parent)) + return false; + if (rbKeyDescription == null) { + if (other.rbKeyDescription != null) + return false; + } else if (!rbKeyDescription.equals(other.rbKeyDescription)) + return false; + if (rbKeyLabel == null) { + if (other.rbKeyLabel != null) + return false; + } else if (!rbKeyLabel.equals(other.rbKeyLabel)) + return false; + if (rbKeyValidationMessage == null) { + if (other.rbKeyValidationMessage != null) + return false; + } else if (!rbKeyValidationMessage + .equals(other.rbKeyValidationMessage)) + return false; + if (recursiveSupported == null) { + if (other.recursiveSupported != null) + return false; + } else if (!recursiveSupported.equals(other.recursiveSupported)) + return false; + if (type == null) { + if (other.type != null) + return false; + } else if (!type.equals(other.type)) + return false; + if (uiHint == null) { + if (other.uiHint != null) + return false; + } else if (!uiHint.equals(other.uiHint)) + return false; + if (validationMessage == null) { + if (other.validationMessage != null) + return false; + } else if (!validationMessage.equals(other.validationMessage)) + return false; + if (validationRegEx == null) { + if (other.validationRegEx != null) + return false; + } else if (!validationRegEx.equals(other.validationRegEx)) + return false; + if (accessTypeRestrictions == null) { + if (other.accessTypeRestrictions != null) + return false; + } else if (!accessTypeRestrictions.equals(other.accessTypeRestrictions)) + return false; + if (isValidLeaf == null) { + if (other.isValidLeaf != null) + return false; + } else if (!isValidLeaf.equals(other.isValidLeaf)) + return false; + return true; + } + + } + + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerAccessTypeDef implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private Long itemId; + private String name; + private String label; + private String rbKeyLabel; + private Collection impliedGrants; + + public RangerAccessTypeDef() { + this(null, null, null, null, null); + } + + public RangerAccessTypeDef(Long itemId, String name, String label, String rbKeyLabel, Collection impliedGrants) { + setItemId(itemId); + setName(name); + setLabel(label); + setRbKeyLabel(rbKeyLabel); + setImpliedGrants(impliedGrants); + } + + public RangerAccessTypeDef(RangerAccessTypeDef other) { + setItemId(other.getItemId()); + setName(other.getName()); + setLabel(other.getLabel()); + setRbKeyLabel(other.getRbKeyLabel()); + setImpliedGrants(other.getImpliedGrants()); + } + + /** + * @return the itemId + */ + public Long getItemId() { + return itemId; + } + + /** + * @param itemId the itemId to set + */ + public void setItemId(Long itemId) { + this.itemId = itemId; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the label + */ + public String getLabel() { + return label; + } + + /** + * @param label the label to set + */ + public void setLabel(String label) { + this.label = label; + } + + /** + * @return the rbKeyLabel + */ + public String getRbKeyLabel() { + return rbKeyLabel; + } + + /** + * @param rbKeyLabel the rbKeyLabel to set + */ + public void setRbKeyLabel(String rbKeyLabel) { + this.rbKeyLabel = rbKeyLabel; + } + + /** + * @return the impliedGrants + */ + public Collection getImpliedGrants() { + return impliedGrants; + } + + /** + * @param impliedGrants the impliedGrants to set + */ + public void setImpliedGrants(Collection impliedGrants) { + if(this.impliedGrants == null) { + this.impliedGrants = new ArrayList<>(); + } + + if(this.impliedGrants == impliedGrants) { + return; + } + + this.impliedGrants.clear(); + + if(impliedGrants != null) { + this.impliedGrants.addAll(impliedGrants); + } + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerAccessTypeDef={"); + sb.append("itemId={").append(itemId).append("} "); + sb.append("name={").append(name).append("} "); + sb.append("label={").append(label).append("} "); + sb.append("rbKeyLabel={").append(rbKeyLabel).append("} "); + + sb.append("impliedGrants={"); + if(impliedGrants != null) { + for(String impliedGrant : impliedGrants) { + if(impliedGrant != null) { + sb.append(impliedGrant).append(" "); + } + } + } + sb.append("} "); + + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((itemId == null) ? 0 : itemId.hashCode()); + result = prime * result + + ((impliedGrants == null) ? 0 : impliedGrants.hashCode()); + result = prime * result + ((label == null) ? 0 : label.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + + ((rbKeyLabel == null) ? 0 : rbKeyLabel.hashCode()); + + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerAccessTypeDef other = (RangerAccessTypeDef) obj; + if (itemId == null) { + if (other.itemId != null) + return false; + } else if (other.itemId == null || !itemId.equals(other.itemId)) + return false; + + if (impliedGrants == null) { + if (other.impliedGrants != null) + return false; + } else if (!impliedGrants.equals(other.impliedGrants)) + return false; + if (label == null) { + if (other.label != null) + return false; + } else if (!label.equals(other.label)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (rbKeyLabel == null) { + if (other.rbKeyLabel != null) + return false; + } else if (!rbKeyLabel.equals(other.rbKeyLabel)) + return false; + return true; + } + } + + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerPolicyConditionDef implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private Long itemId; + private String name; + private String evaluator; + private Map evaluatorOptions; + private String validationRegEx; + private String validationMessage; + private String uiHint; + private String label; + private String description; + private String rbKeyLabel; + private String rbKeyDescription; + private String rbKeyValidationMessage; + + public RangerPolicyConditionDef() { + this(null, null, null, null, null, null, null, null, null, null, null, null); + } + + public RangerPolicyConditionDef(Long itemId, String name, String evaluator, Map evaluatorOptions) { + this(itemId, name, evaluator, evaluatorOptions, null, null, null, null, null, null, null, null); + } + + public RangerPolicyConditionDef(Long itemId, String name, String evaluator, Map evaluatorOptions, String validationRegEx, String vaidationMessage, String uiHint, String label, String description, String rbKeyLabel, String rbKeyDescription, String rbKeyValidationMessage) { //NOPMD + setItemId(itemId); + setName(name); + setEvaluator(evaluator); + setEvaluatorOptions(evaluatorOptions); + setValidationRegEx(validationRegEx); + setValidationMessage(validationMessage); + setUiHint(uiHint); + setLabel(label); + setDescription(description); + setRbKeyLabel(rbKeyLabel); + setRbKeyDescription(rbKeyDescription); + setRbKeyValidationMessage(rbKeyValidationMessage); + } + + /** + * @return the itemId + */ + public Long getItemId() { + return itemId; + } + + /** + * @param itemId the itemId to set + */ + public void setItemId(Long itemId) { + this.itemId = itemId; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the evaluator + */ + public String getEvaluator() { + return evaluator; + } + + /** + * @param evaluator the evaluator to set + */ + public void setEvaluator(String evaluator) { + this.evaluator = evaluator; + } + + /** + * @return the evaluatorOptions + */ + public Map getEvaluatorOptions() { + return evaluatorOptions; + } + + /** + * @param evaluatorOptions the evaluatorOptions to set + */ + public void setEvaluatorOptions(Map evaluatorOptions) { + this.evaluatorOptions = evaluatorOptions == null ? new HashMap() : evaluatorOptions; + } + + /** + * @return the validationRegEx + */ + public String getValidationRegEx() { + return validationRegEx; + } + + /** + * @param validationRegEx the validationRegEx to set + */ + public void setValidationRegEx(String validationRegEx) { + this.validationRegEx = validationRegEx; + } + + /** + * @return the validationMessage + */ + public String getValidationMessage() { + return validationMessage; + } + + /** + * @param validationMessage the validationMessage to set + */ + public void setValidationMessage(String validationMessage) { + this.validationMessage = validationMessage; + } + + /** + * @return the uiHint + */ + public String getUiHint() { + return uiHint; + } + + /** + * @param uiHint the uiHint to set + */ + public void setUiHint(String uiHint) { + this.uiHint = uiHint; + } + + /** + * @return the label + */ + public String getLabel() { + return label; + } + + /** + * @param label the label to set + */ + public void setLabel(String label) { + this.label = label; + } + + /** + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * @param description the description to set + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * @return the rbKeyLabel + */ + public String getRbKeyLabel() { + return rbKeyLabel; + } + + /** + * @param rbKeyLabel the rbKeyLabel to set + */ + public void setRbKeyLabel(String rbKeyLabel) { + this.rbKeyLabel = rbKeyLabel; + } + + /** + * @return the rbKeyDescription + */ + public String getRbKeyDescription() { + return rbKeyDescription; + } + + /** + * @param rbKeyDescription the rbKeyDescription to set + */ + public void setRbKeyDescription(String rbKeyDescription) { + this.rbKeyDescription = rbKeyDescription; + } + + /** + * @return the rbKeyValidationMessage + */ + public String getRbKeyValidationMessage() { + return rbKeyValidationMessage; + } + + /** + * @param rbKeyValidationMessage the rbKeyValidationMessage to set + */ + public void setRbKeyValidationMessage(String rbKeyValidationMessage) { + this.rbKeyValidationMessage = rbKeyValidationMessage; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerPolicyConditionDef={"); + sb.append("itemId={").append(itemId).append("} "); + sb.append("name={").append(name).append("} "); + sb.append("evaluator={").append(evaluator).append("} "); + sb.append("evaluatorOptions={").append(evaluatorOptions).append("} "); + sb.append("validationRegEx={").append(validationRegEx).append("} "); + sb.append("validationMessage={").append(validationMessage).append("} "); + sb.append("uiHint={").append(uiHint).append("} "); + sb.append("label={").append(label).append("} "); + sb.append("description={").append(description).append("} "); + sb.append("rbKeyLabel={").append(rbKeyLabel).append("} "); + sb.append("rbKeyDescription={").append(rbKeyDescription).append("} "); + sb.append("rbKeyValidationMessage={").append(rbKeyValidationMessage).append("} "); + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((itemId == null) ? 0 : itemId.hashCode()); + result = prime * result + + ((description == null) ? 0 : description.hashCode()); + result = prime * result + + ((evaluator == null) ? 0 : evaluator.hashCode()); + result = prime + * result + + ((evaluatorOptions == null) ? 0 : evaluatorOptions + .hashCode()); + result = prime * result + ((label == null) ? 0 : label.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime + * result + + ((rbKeyDescription == null) ? 0 : rbKeyDescription + .hashCode()); + result = prime * result + + ((rbKeyLabel == null) ? 0 : rbKeyLabel.hashCode()); + result = prime + * result + + ((rbKeyValidationMessage == null) ? 0 + : rbKeyValidationMessage.hashCode()); + result = prime * result + + ((uiHint == null) ? 0 : uiHint.hashCode()); + result = prime + * result + + ((validationMessage == null) ? 0 : validationMessage + .hashCode()); + result = prime + * result + + ((validationRegEx == null) ? 0 : validationRegEx + .hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerPolicyConditionDef other = (RangerPolicyConditionDef) obj; + if (itemId == null) { + if (other.itemId != null) + return false; + } else if (other.itemId != null || !itemId.equals(other.itemId)) { + return false; + } + + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (evaluator == null) { + if (other.evaluator != null) + return false; + } else if (!evaluator.equals(other.evaluator)) + return false; + if (evaluatorOptions == null) { + if (other.evaluatorOptions != null) + return false; + } else if (!evaluatorOptions.equals(other.evaluatorOptions)) + return false; + if (label == null) { + if (other.label != null) + return false; + } else if (!label.equals(other.label)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (rbKeyDescription == null) { + if (other.rbKeyDescription != null) + return false; + } else if (!rbKeyDescription.equals(other.rbKeyDescription)) + return false; + if (rbKeyLabel == null) { + if (other.rbKeyLabel != null) + return false; + } else if (!rbKeyLabel.equals(other.rbKeyLabel)) + return false; + if (rbKeyValidationMessage == null) { + if (other.rbKeyValidationMessage != null) + return false; + } else if (!rbKeyValidationMessage + .equals(other.rbKeyValidationMessage)) + return false; + if (uiHint == null) { + if (other.uiHint != null) + return false; + } else if (!uiHint.equals(other.uiHint)) + return false; + if (validationMessage == null) { + if (other.validationMessage != null) + return false; + } else if (!validationMessage.equals(other.validationMessage)) + return false; + if (validationRegEx == null) { + if (other.validationRegEx != null) + return false; + } else if (!validationRegEx.equals(other.validationRegEx)) + return false; + return true; + } + } + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerContextEnricherDef implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private Long itemId; + private String name; + private String enricher; + private Map enricherOptions; + + public RangerContextEnricherDef() { + this(null, null, null, null); + } + + public RangerContextEnricherDef(Long itemId, String name, String enricher, Map enricherOptions) { + setItemId(itemId); + setName(name); + setEnricher(enricher); + setEnricherOptions(enricherOptions); + } + + /** + * @return the itemId + */ + public Long getItemId() { + return itemId; + } + + /** + * @param itemId the itemId to set + */ + public void setItemId(Long itemId) { + this.itemId = itemId; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the enricher + */ + public String getEnricher() { + return enricher; + } + + /** + * @param enricher the enricher to set + */ + public void setEnricher(String enricher) { + this.enricher = enricher; + } + + /** + * @return the enricherOptions + */ + public Map getEnricherOptions() { + return enricherOptions; + } + + /** + * @param enricherOptions the enricherOptions to set + */ + public void setEnricherOptions(Map enricherOptions) { + this.enricherOptions = enricherOptions == null ? new HashMap() : enricherOptions; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerContextEnricherDef={"); + sb.append("itemId={").append(itemId).append("} "); + sb.append("name={").append(name).append("} "); + sb.append("enricher={").append(enricher).append("} "); + sb.append("enricherOptions={").append(enricherOptions).append("} "); + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((itemId == null) ? 0 : itemId.hashCode()); + result = prime * result + + ((enricher == null) ? 0 : enricher.hashCode()); + result = prime + * result + + ((enricherOptions == null) ? 0 : enricherOptions + .hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerContextEnricherDef other = (RangerContextEnricherDef) obj; + if (itemId == null) { + if (other.itemId != null) + return false; + } else if (other.itemId == null || !itemId.equals(other.itemId)) + return false; + + if (enricher == null) { + if (other.enricher != null) + return false; + } else if (!enricher.equals(other.enricher)) + return false; + if (enricherOptions == null) { + if (other.enricherOptions != null) + return false; + } else if (!enricherOptions.equals(other.enricherOptions)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } + } + + + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerDataMaskDef implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private List maskTypes; + private List accessTypes; + private List resources; + + + public RangerDataMaskDef() { + setMaskTypes(null); + setAccessTypes(null); + setResources(null); + } + + public RangerDataMaskDef(List maskTypes, List accessTypes, List resources) { + setMaskTypes(maskTypes); + setAccessTypes(accessTypes); + setResources(resources); + } + + public RangerDataMaskDef(RangerDataMaskDef other) { + setMaskTypes(other.getMaskTypes()); + setAccessTypes(other.getAccessTypes()); + setResources(other.getResources()); + } + + public List getMaskTypes() { + return maskTypes; + } + + public void setMaskTypes(List maskTypes) { + if(this.maskTypes == null) { + this.maskTypes = new ArrayList<>(); + } + + if(this.maskTypes == maskTypes) { + return; + } + + this.maskTypes.clear(); + + if(maskTypes != null) { + this.maskTypes.addAll(maskTypes); + } + } + + public List getAccessTypes() { + return accessTypes; + } + + public void setAccessTypes(List accessTypes) { + if(this.accessTypes == null) { + this.accessTypes = new ArrayList<>(); + } + + if(this.accessTypes == accessTypes) { + return; + } + + this.accessTypes.clear(); + + if(accessTypes != null) { + this.accessTypes.addAll(accessTypes); + } + } + + public List getResources() { + return resources; + } + + public void setResources(List resources) { + if(this.resources == null) { + this.resources = new ArrayList<>(); + } + + if(this.resources == resources) { + return; + } + + this.resources.clear(); + + if(resources != null) { + this.resources.addAll(resources); + } + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerDataMaskDef={"); + + sb.append("maskTypes={"); + if(maskTypes != null) { + for(RangerDataMaskTypeDef maskType : maskTypes) { + if(maskType != null) { + sb.append(maskType).append(" "); + } + } + } + sb.append("} "); + + sb.append("accessTypes={"); + if(accessTypes != null) { + for(RangerAccessTypeDef accessType : accessTypes) { + if(accessType != null) { + accessType.toString(sb).append(" "); + } + } + } + sb.append("} "); + + sb.append("resources={"); + if(resources != null) { + for(RangerResourceDef resource : resources) { + if(resource != null) { + resource.toString(sb).append(" "); + } + } + } + sb.append("} "); + + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((maskTypes == null) ? 0 : maskTypes.hashCode()); + result = prime * result + ((accessTypes == null) ? 0 : accessTypes.hashCode()); + result = prime * result + ((resources == null) ? 0 : resources.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerDataMaskDef other = (RangerDataMaskDef) obj; + if (maskTypes == null) { + if (other.maskTypes != null) + return false; + } else if (other.maskTypes == null || !maskTypes.equals(other.maskTypes)) + return false; + + if (accessTypes == null) { + if (other.accessTypes != null) + return false; + } else if (!accessTypes.equals(other.accessTypes)) + return false; + if (resources == null) { + if (other.resources != null) + return false; + } else if (!resources.equals(other.resources)) + return false; + return true; + } + } + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerDataMaskTypeDef implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private Long itemId; + private String name; + private String label; + private String description; + private String transformer; + private Map dataMaskOptions; + private String rbKeyLabel; + private String rbKeyDescription; + + public RangerDataMaskTypeDef() { + this(null, null, null, null, null, null, null, null); + } + + public RangerDataMaskTypeDef(Long itemId, String name, String label, String description, String transformer, Map dataMaskOptions, String rbKeyLabel, String rbKeyDescription) { + setItemId(itemId); + setName(name); + setLabel(label); + setDescription(description); + setTransformer(transformer); + setDataMaskOptions(dataMaskOptions); + setRbKeyLabel(rbKeyLabel); + setRbKeyDescription(rbKeyDescription); + } + + public RangerDataMaskTypeDef(RangerDataMaskTypeDef other) { + setItemId(other.getItemId()); + setName(other.getName()); + setLabel(other.getLabel()); + setDescription(other.getDescription()); + setTransformer(other.getTransformer()); + setDataMaskOptions(other.getDataMaskOptions()); + setRbKeyLabel(other.getRbKeyLabel()); + setRbKeyDescription(other.getRbKeyDescription()); + } + + /** + * @return the itemId + */ + public Long getItemId() { + return itemId; + } + + /** + * @param itemId the itemId to set + */ + public void setItemId(Long itemId) { + this.itemId = itemId; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the label + */ + public String getLabel() { + return label; + } + + /** + * @param label the label to set + */ + public void setLabel(String label) { + this.label = label; + } + + /** + * @return the description + */ + public String getDescription() { + return description; + } + + /** + * @param description the description to set + */ + public void setDescription(String description) { + this.description = description; + } + + /** + * @return the transformer + */ + public String getTransformer() { + return transformer; + } + + /** + * @param transformer the transformer to set + */ + public void setTransformer(String transformer) { + this.transformer = transformer; + } + + /** + * @return the dataMaskOptions + */ + public Map getDataMaskOptions() { + return dataMaskOptions; + } + + /** + * @param dataMaskOptions the dataMaskOptions to set + */ + public void setDataMaskOptions(Map dataMaskOptions) { + this.dataMaskOptions = dataMaskOptions == null ? new HashMap() : dataMaskOptions; + } + + /** + * @return the rbKeyLabel + */ + public String getRbKeyLabel() { + return rbKeyLabel; + } + + /** + * @param rbKeyLabel the rbKeyLabel to set + */ + public void setRbKeyLabel(String rbKeyLabel) { + this.rbKeyLabel = rbKeyLabel; + } + + /** + * @return the rbKeyDescription + */ + public String getRbKeyDescription() { + return rbKeyDescription; + } + + /** + * @param rbKeyDescription the rbKeyDescription to set + */ + public void setRbKeyDescription(String rbKeyDescription) { + this.rbKeyDescription = rbKeyDescription; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerDataMaskTypeDef={"); + sb.append("itemId={").append(itemId).append("} "); + sb.append("name={").append(name).append("} "); + sb.append("label={").append(label).append("} "); + sb.append("description={").append(description).append("} "); + sb.append("transformer={").append(transformer).append("} "); + sb.append("dataMaskOptions={").append(dataMaskOptions).append("} "); + sb.append("rbKeyLabel={").append(rbKeyLabel).append("} "); + sb.append("rbKeyDescription={").append(rbKeyDescription).append("} "); + + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((itemId == null) ? 0 : itemId.hashCode()); + result = prime * result + + ((dataMaskOptions == null) ? 0 : dataMaskOptions.hashCode()); + result = prime * result + ((label == null) ? 0 : label.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + + ((rbKeyLabel == null) ? 0 : rbKeyLabel.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((transformer == null) ? 0 : transformer.hashCode()); + result = prime * result + ((rbKeyDescription == null) ? 0 : rbKeyDescription.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerDataMaskTypeDef other = (RangerDataMaskTypeDef) obj; + if (itemId == null) { + if (other.itemId != null) + return false; + } else if (other.itemId == null || !itemId.equals(other.itemId)) + return false; + + if (dataMaskOptions == null) { + if (other.dataMaskOptions != null) + return false; + } else if (!dataMaskOptions.equals(other.dataMaskOptions)) + return false; + if (label == null) { + if (other.label != null) + return false; + } else if (!label.equals(other.label)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (rbKeyLabel == null) { + if (other.rbKeyLabel != null) + return false; + } else if (!rbKeyLabel.equals(other.rbKeyLabel)) + return false; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (transformer == null) { + if (other.transformer != null) + return false; + } else if (!transformer.equals(other.transformer)) + return false; + if (rbKeyDescription == null) { + if (other.rbKeyDescription != null) + return false; + } else if (!rbKeyDescription.equals(other.rbKeyDescription)) + return false; + return true; + } + } + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RangerRowFilterDef implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + private List accessTypes; + private List resources; + + + public RangerRowFilterDef() { + setAccessTypes(null); + setResources(null); + } + + public RangerRowFilterDef(List accessTypes, List resources) { + setAccessTypes(accessTypes); + setResources(resources); + } + + public RangerRowFilterDef(RangerRowFilterDef other) { + setAccessTypes(other.getAccessTypes()); + setResources(other.getResources()); + } + + public List getAccessTypes() { + return accessTypes; + } + + public void setAccessTypes(List accessTypes) { + if(this.accessTypes == null) { + this.accessTypes = new ArrayList<>(); + } + + if(this.accessTypes == accessTypes) { + return; + } + + this.accessTypes.clear(); + + if(accessTypes != null) { + this.accessTypes.addAll(accessTypes); + } + } + + public List getResources() { + return resources; + } + + public void setResources(List resources) { + if(this.resources == null) { + this.resources = new ArrayList<>(); + } + + if(this.resources == resources) { + return; + } + + this.resources.clear(); + + if(resources != null) { + this.resources.addAll(resources); + } + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerRowFilterDef={"); + + sb.append("accessTypes={"); + if(accessTypes != null) { + for(RangerAccessTypeDef accessType : accessTypes) { + if(accessType != null) { + accessType.toString(sb).append(" "); + } + } + } + sb.append("} "); + + sb.append("resources={"); + if(resources != null) { + for(RangerResourceDef resource : resources) { + if(resource != null) { + resource.toString(sb).append(" "); + } + } + } + sb.append("} "); + + sb.append("}"); + + return sb; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((accessTypes == null) ? 0 : accessTypes.hashCode()); + result = prime * result + ((resources == null) ? 0 : resources.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RangerRowFilterDef other = (RangerRowFilterDef) obj; + + if (accessTypes == null) { + if (other.accessTypes != null) + return false; + } else if (!accessTypes.equals(other.accessTypes)) + return false; + if (resources == null) { + if (other.resources != null) + return false; + } else if (!resources.equals(other.resources)) + return false; + return true; + } + } +} \ No newline at end of file diff --git a/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerValidityRecurrence.java b/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerValidityRecurrence.java new file mode 100644 index 00000000000..baaa833fbf7 --- /dev/null +++ b/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerValidityRecurrence.java @@ -0,0 +1,224 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; + +@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) + +public class RangerValidityRecurrence implements Serializable { + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class ValidityInterval { + private final int days; + private final int hours; + private final int minutes; + + public static int getValidityIntervalInMinutes(ValidityInterval interval) { + return interval != null ? + (interval.getDays()*24 + interval.getHours())*60 + interval.getMinutes() : 0; + } + + public ValidityInterval() { + this.days = 0; + this.hours = 0; + this.minutes = 0; + } + public ValidityInterval(int days, int hours, int minutes) { + this.days = days; + this.hours = hours; + this.minutes = minutes; + } + public int getDays() { return days; } + public int getHours() { return hours; } + public int getMinutes() { return minutes; } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("ValidityInterval={"); + + sb.append(" Interval={"); + sb.append("days=").append(days); + sb.append(", hours=").append(hours); + sb.append(", minutes=").append(minutes); + sb.append(" }"); + + return sb.toString(); + } + } + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class RecurrenceSchedule { + static final String PERMITTED_SPECIAL_CHARACTERS = "*,-"; + static final String PERMITTED_SPECIAL_CHARACTERS_FOR_MINUTES = ","; + public static final String WILDCARD = "*"; + + public enum ScheduleFieldSpec { + minute(0, 59, PERMITTED_SPECIAL_CHARACTERS_FOR_MINUTES), + hour(0, 23, PERMITTED_SPECIAL_CHARACTERS), + dayOfMonth(1, 31, PERMITTED_SPECIAL_CHARACTERS), + dayOfWeek(1, 7, PERMITTED_SPECIAL_CHARACTERS), + month(0, 11, PERMITTED_SPECIAL_CHARACTERS), + year(2017, 2100, PERMITTED_SPECIAL_CHARACTERS), + ; + + public final int minimum; + public final int maximum; + public final String specialChars; + + ScheduleFieldSpec(int minimum, int maximum, String specialChars) { + this.minimum = minimum; + this.maximum = maximum; + this.specialChars = specialChars; + } + } + + + private String minute; + private String hour; + private String dayOfMonth; + private String dayOfWeek; + private String month; + private String year; + + public RecurrenceSchedule() {} + + public RecurrenceSchedule(String minute, String hour, String dayOfMonth, String dayOfWeek, String month, String year) { + setMinute(minute); + setHour(hour); + setDayOfMonth(dayOfMonth); + setDayOfWeek(dayOfWeek); + setMonth(month); + setYear(year); + } + public String getMinute() { return minute;} + public String getHour() { return hour;} + public String getDayOfMonth() { return dayOfMonth;} + public String getDayOfWeek() { return dayOfWeek;} + public String getMonth() { return month;} + public String getYear() { return year;} + + public void setMinute(String minute) { this.minute = minute;} + public void setHour(String hour) { this.hour = hour;} + public void setDayOfMonth(String dayOfMonth) { this.dayOfMonth = dayOfMonth;} + public void setDayOfWeek(String dayOfWeek) { this.dayOfWeek = dayOfWeek;} + public void setMonth(String month) { this.month = month;} + public void setYear(String year) { this.year = year;} + + public void setFieldValue(ScheduleFieldSpec field, String value) { + switch (field) { + case minute: + setMinute(value); + break; + case hour: + setHour(value); + break; + case dayOfMonth: + setDayOfMonth(value); + break; + case dayOfWeek: + setDayOfWeek(value); + break; + case month: + setMonth(value); + break; + case year: + setYear(value); + break; + default: + break; + } + } + + public String getFieldValue(ScheduleFieldSpec field) { + switch (field) { + case minute: + return getMinute(); + case hour: + return getHour(); + case dayOfMonth: + return getDayOfMonth(); + case dayOfWeek: + return getDayOfWeek(); + case month: + return getMonth(); + case year: + return getYear(); + default: + return null; + } + } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(" Schedule={"); + sb.append(" minute=").append(minute); + sb.append(", hour=").append(hour); + sb.append(", dayOfMonth=").append(dayOfMonth); + sb.append(", dayOfWeek=").append(dayOfWeek); + sb.append(", month=").append(month); + sb.append(", year=").append(year); + sb.append(" }"); + + return sb.toString(); + } + } + + private RecurrenceSchedule schedule; + private ValidityInterval interval; + + public RangerValidityRecurrence() { + } + + public RangerValidityRecurrence(RecurrenceSchedule schedule, ValidityInterval interval) { + setSchedule(schedule); + setInterval(interval); + } + + public void setSchedule(RecurrenceSchedule schedule) { this.schedule = schedule;} + + public void setInterval(ValidityInterval interval) { this.interval = interval; } + + public RecurrenceSchedule getSchedule() { return schedule;} + + public ValidityInterval getInterval() { + return interval; + } + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{RangerValidityRecurrence= {"); + sb.append(schedule).append(interval); + sb.append(" }"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerValiditySchedule.java b/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerValiditySchedule.java new file mode 100644 index 00000000000..4777b0cfa37 --- /dev/null +++ b/auth-common/src/main/java/org/apache/atlas/plugin/model/RangerValiditySchedule.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@JsonAutoDetect(fieldVisibility= JsonAutoDetect.Visibility.ANY) +@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown=true) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) + +public class RangerValiditySchedule implements Serializable { + + public static final String VALIDITY_SCHEDULE_DATE_STRING_SPECIFICATION = "yyyy/MM/dd HH:mm:ss"; + + private String startTime; + private String endTime; + private String timeZone; + + private List recurrences; + + public RangerValiditySchedule(String startTime, String endTime, String timeZone, List recurrences) { + setTimeZone(timeZone); + setStartTime(startTime); + setEndTime(endTime); + setRecurrences(recurrences); + } + + public RangerValiditySchedule() { + this(null, null, null, null); + } + + public String getTimeZone() { return timeZone; } + public String getStartTime() { return startTime;} + public String getEndTime() { return endTime;} + public List getRecurrences() { return recurrences;} + + public void setTimeZone(String timeZone) { this.timeZone = timeZone; } + public void setStartTime(String startTime) { this.startTime = startTime;} + public void setEndTime(String endTime) { this.endTime = endTime;} + public void setRecurrences(List recurrences) { this.recurrences = recurrences == null ? new ArrayList<>() : recurrences;} + + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("RangerValiditySchedule={"); + + sb.append(", startTime=").append(startTime); + sb.append(", endTime=").append(endTime); + sb.append(", timeZone=").append(timeZone); + + sb.append(", recurrences=").append(Arrays.toString(getRecurrences().toArray())); + + sb.append("}"); + + return sb.toString(); + } +} diff --git a/auth-common/src/main/java/org/apache/atlas/plugin/model/UserInfo.java b/auth-common/src/main/java/org/apache/atlas/plugin/model/UserInfo.java new file mode 100644 index 00000000000..c8859bff4f0 --- /dev/null +++ b/auth-common/src/main/java/org/apache/atlas/plugin/model/UserInfo.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.apache.atlas.plugin.util.RangerUserStoreUtil; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class UserInfo extends RangerBaseModelObject implements java.io.Serializable { + + private static final long serialVersionUID = 1L; + private String name; + private String description; + private Map otherAttributes; + private Set groups; + + public UserInfo() { + this(null, null, null); + } + + public UserInfo(String name, String description, Map otherAttributes) { + setName(name); + setDescription(description); + setOtherAttributes(otherAttributes); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Map getOtherAttributes() { + return otherAttributes; + } + + public void setOtherAttributes(Map otherAttributes) { + this.otherAttributes = otherAttributes == null ? new HashMap<>() : otherAttributes; + } + + public Set getGroups(){ + return this.groups; + } + + public void setGroups(Set groups){ + this.groups = groups; + } + + @Override + public String toString() { + return "{name=" + name + + ", description=" + description + + ", otherAttributes=" + RangerUserStoreUtil.getPrintableOptions(otherAttributes) + + ", groups=" + groups + + "}"; + } +} \ No newline at end of file diff --git a/auth-common/src/main/java/org/apache/atlas/plugin/util/RangerRoles.java b/auth-common/src/main/java/org/apache/atlas/plugin/util/RangerRoles.java new file mode 100644 index 00000000000..e03a230ff76 --- /dev/null +++ b/auth-common/src/main/java/org/apache/atlas/plugin/util/RangerRoles.java @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.apache.atlas.plugin.model.RangerRole; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Date; +import java.util.Set; + +@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerRoles implements Serializable { + private static final long serialVersionUID = 1L; + + private String serviceName; + private Long roleVersion; + private Date roleUpdateTime; + private Set rangerRoles; + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public Long getRoleVersion() { + return roleVersion; + } + + public void setRoleVersion(Long roleVersion) { + this.roleVersion = roleVersion; + } + + public Date getRoleUpdateTime() { + return roleUpdateTime; + } + + public void setRoleUpdateTime(Date roleUpdateTime) { + this.roleUpdateTime = roleUpdateTime; + } + + public Set getRangerRoles(){ + return this.rangerRoles; + } + + public void setRangerRoles(Set rangerRoles){ + this.rangerRoles = rangerRoles; + } +} \ No newline at end of file diff --git a/auth-common/src/main/java/org/apache/atlas/plugin/util/RangerUserStore.java b/auth-common/src/main/java/org/apache/atlas/plugin/util/RangerUserStore.java new file mode 100644 index 00000000000..3e6f77f5afd --- /dev/null +++ b/auth-common/src/main/java/org/apache/atlas/plugin/util/RangerUserStore.java @@ -0,0 +1,191 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import com.fasterxml.jackson.annotation.JsonInclude; +import org.apache.atlas.plugin.model.GroupInfo; +import org.apache.atlas.plugin.model.UserInfo; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@XmlRootElement +@XmlAccessorType(XmlAccessType.FIELD) +public class RangerUserStore implements Serializable { + private static final long serialVersionUID = 1L; + public static final String CLOUD_IDENTITY_NAME = "cloud_id"; + + private Long userStoreVersion; + private Date userStoreUpdateTime; + private Map> userAttrMapping; + private Map> groupAttrMapping ; + private Map> userGroupMapping; + private Map userCloudIdMapping; + private Map groupCloudIdMapping; + private String serviceName; + + public RangerUserStore() {this(-1L, null, null, null);} + + public RangerUserStore(Long userStoreVersion, Set users, Set groups, Map> userGroups) { + setUserStoreVersion(userStoreVersion); + setUserStoreUpdateTime(new Date()); + setUserGroupMapping(userGroups); + buildMap(users, groups); + } + + public String getServiceName() { + return serviceName; + } + + public void setServiceName(String serviceName) { + this.serviceName = serviceName; + } + + public Long getUserStoreVersion() { + return userStoreVersion; + } + + public void setUserStoreVersion(Long userStoreVersion) { + this.userStoreVersion = userStoreVersion; + } + + public Date getUserStoreUpdateTime() { + return userStoreUpdateTime; + } + + public void setUserStoreUpdateTime(Date userStoreUpdateTime) { + this.userStoreUpdateTime = userStoreUpdateTime; + } + + public Map> getUserAttrMapping() { + return userAttrMapping; + } + + public void setUserAttrMapping(Map> userAttrMapping) { + this.userAttrMapping = userAttrMapping; + } + + public Map> getGroupAttrMapping() { + return groupAttrMapping; + } + + public void setGroupAttrMapping(Map> groupAttrMapping) { + this.groupAttrMapping = groupAttrMapping; + } + + public Map> getUserGroupMapping() { + return userGroupMapping; + } + + public void setUserGroupMapping(Map> userGroupMapping) { + this.userGroupMapping = userGroupMapping; + } + + public Map getUserCloudIdMapping() { + return userCloudIdMapping; + } + + public void setUserCloudIdMapping(Map userCloudIdMapping) { + this.userCloudIdMapping = userCloudIdMapping; + } + + public Map getGroupCloudIdMapping() { + return groupCloudIdMapping; + } + + public void setGroupCloudIdMapping(Map groupCloudIdMapping) { + this.groupCloudIdMapping = groupCloudIdMapping; + } + + @Override + public String toString( ) { + StringBuilder sb = new StringBuilder(); + + toString(sb); + + return sb.toString(); + } + + public StringBuilder toString(StringBuilder sb) { + sb.append("RangerUserStore={") + .append("userStoreVersion=").append(userStoreVersion).append(", ") + .append("userStoreUpdateTime=").append(userStoreUpdateTime).append(", "); + sb.append("users={"); + if(MapUtils.isNotEmpty(userAttrMapping)) { + for(String user : userAttrMapping.keySet()) { + sb.append(user); + } + } + sb.append("}, "); + sb.append("groups={"); + if(MapUtils.isNotEmpty(groupAttrMapping)) { + for(String group : groupAttrMapping.keySet()) { + sb.append(group); + } + } + sb.append("}"); + sb.append("}"); + + return sb; + } + + private void buildMap(Set users, Set groups) { + if (CollectionUtils.isNotEmpty(users)) { + userAttrMapping = new HashMap<>(); + userCloudIdMapping = new HashMap<>(); + for (UserInfo user : users) { + String username = user.getName(); + Map userAttrs = user.getOtherAttributes(); + if (MapUtils.isNotEmpty(userAttrs)) { + userAttrMapping.put(username, userAttrs); + String cloudId = userAttrs.get(CLOUD_IDENTITY_NAME); + if (StringUtils.isNotEmpty(cloudId)) { + userCloudIdMapping.put(cloudId, username); + } + } + } + } + if (CollectionUtils.isNotEmpty(groups)) { + groupAttrMapping = new HashMap<>(); + groupCloudIdMapping = new HashMap<>(); + for (GroupInfo group : groups) { + String groupname = group.getName(); + Map groupAttrs = group.getOtherAttributes(); + if (MapUtils.isNotEmpty(groupAttrs)) { + groupAttrMapping.put(groupname, groupAttrs); + String cloudId = groupAttrs.get(CLOUD_IDENTITY_NAME); + if (StringUtils.isNotEmpty(cloudId)) { + groupCloudIdMapping.put(cloudId, groupname); + } + } + } + } + } +} diff --git a/auth-common/src/main/java/org/apache/atlas/plugin/util/RangerUserStoreUtil.java b/auth-common/src/main/java/org/apache/atlas/plugin/util/RangerUserStoreUtil.java new file mode 100644 index 00000000000..d45d5f19293 --- /dev/null +++ b/auth-common/src/main/java/org/apache/atlas/plugin/util/RangerUserStoreUtil.java @@ -0,0 +1,58 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.plugin.util; + +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; + +import java.util.Map; + +public class RangerUserStoreUtil { + public static final String CLOUD_IDENTITY_NAME = "cloud_id"; + + public static String getPrintableOptions(Map otherAttributes) { + if (MapUtils.isEmpty(otherAttributes)) return "{}"; + StringBuilder ret = new StringBuilder(); + ret.append("{"); + for (Map.Entry entry : otherAttributes.entrySet()) { + ret.append(entry.getKey()).append(", ").append("[").append(entry.getValue()).append("]").append(","); + } + ret.append("}"); + return ret.toString(); + } + + public static String getAttrVal(Map> attrMap, String name, String attrName) { + String ret = null; + + if (StringUtils.isNotEmpty(name) && StringUtils.isNotEmpty(attrName)) { + Map attrs = attrMap.get(name); + if (MapUtils.isNotEmpty(attrs)) { + ret = attrs.get(attrName); + } + } + return ret; + } + + public String getCloudId(Map> attrMap, String name) { + String cloudId = null; + cloudId = getAttrVal(attrMap, name, CLOUD_IDENTITY_NAME); + return cloudId; + } +} diff --git a/auth-common/src/main/resources/service-defs/atlas-servicedef-atlas.json b/auth-common/src/main/resources/service-defs/atlas-servicedef-atlas.json new file mode 100644 index 00000000000..abfce9b6bc8 --- /dev/null +++ b/auth-common/src/main/resources/service-defs/atlas-servicedef-atlas.json @@ -0,0 +1,522 @@ +{ + "id": 15, + "name": "atlas", + "displayName": "atlas", + "implClass": "org.apache.atlas.services.atlas.RangerServiceAtlas", + "label": "Atlas Metadata Server", + "description": "Atlas Metadata Server", + "guid": "311a79b7-16f5-46f4-9829-a0224b9999c5", + "resources": [ + { + "itemId": 1, + "name": "type-category", + "type": "string", + "level": 10, + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "true" + }, + "label": "Type Catagory", + "description": "Type Catagory" + }, + { + "itemId": 2, + "name": "type", + "type": "string", + "level": 20, + "mandatory": true, + "parent": "type-category", + "isValidLeaf": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "false" + }, + "label": "Type Name", + "description": "Type Name", + "accessTypeRestrictions": ["type-read" ,"type-create", "type-update", "type-delete" ] + }, + { + "itemId": 3, + "name": "entity-type", + "type": "string", + "level": 10, + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "false" + }, + "label": "Entity Type", + "description": "Entity Type" + }, + { + "itemId": 4, + "name": "entity-classification", + "type": "string", + "level": 20, + "mandatory": true, + "parent": "entity-type", + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "false" + }, + "label": "Entity Classification", + "description": "Entity Classification" + }, + { + "itemId": 5, + "name": "entity", + "type": "string", + "level": 30, + "mandatory": true, + "parent": "entity-classification", + "isValidLeaf": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "true" + }, + "label": "Entity ID", + "description": "Entity ID", + "accessTypeRestrictions": ["entity-read", "entity-create", "entity-update", "entity-delete"] + }, + { + "itemId": 6, + "name": "atlas-service", + "type": "string", + "level": 10, + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "true" + }, + "label": "Atlas Service", + "description": "Atlas Service", + "accessTypeRestrictions": ["admin-import", "admin-export", "admin-purge", "admin-audits", "admin-entity-audits", "admin-repair-index", "admin-task-cud"] + }, + { + "itemId": 7, + "name": "relationship-type", + "type": "string", + "level": 10, + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "false" + }, + "label": "Relationship Type", + "description": "Relationship Type" + }, + { + "itemId": 8, + "name": "end-one-entity-type", + "type": "string", + "level": 20, + "mandatory": true, + "parent": "relationship-type", + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "false" + }, + "label": "End1 Entity Type", + "description": "End1 Entity Type" + }, + { + "itemId": 9, + "name": "end-one-entity-classification", + "type": "string", + "level": 30, + "mandatory": true, + "parent": "end-one-entity-type", + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "false" + }, + "label": "End1 Entity Classification", + "description": "End1 Entity Classification" + }, + { + "itemId": 10, + "name": "end-one-entity", + "type": "string", + "level": 40, + "mandatory": true, + "parent": "end-one-entity-classification", + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "true" + }, + "label": "End1 Entity ID", + "description": "End1 Entity ID" + }, + { + "itemId": 11, + "name": "end-two-entity-type", + "type": "string", + "level": 50, + "mandatory": true, + "parent": "end-one-entity", + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "false" + }, + "label": "End2 Entity Type", + "description": "End2 Entity Type" + }, + { + "itemId": 12, + "name": "end-two-entity-classification", + "type": "string", + "level": 60, + "mandatory": true, + "parent": "end-two-entity-type", + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "false" + }, + "label": "End2 Entity Classification", + "description": "End2 Entity Classification" + }, + { + "itemId": 13, + "name": "end-two-entity", + "type": "string", + "level": 70, + "mandatory": true, + "parent": "end-two-entity-classification", + "isValidLeaf": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "true" + }, + "label": "End2 Entity ID", + "description": "End2 Entity ID", + "accessTypeRestrictions": [ + "add-relationship", + "update-relationship", + "remove-relationship" + ] + }, + { + "itemId": 14, + "name": "entity-label", + "type": "string", + "level": 40, + "mandatory": true, + "parent": "entity", + "isValidLeaf": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "true" + }, + "label": "Label", + "description": "Label", + "accessTypeRestrictions": [ + "entity-add-label", + "entity-remove-label" + ] + }, + { + "itemId": 15, + "name": "entity-business-metadata", + "type": "string", + "level": 40, + "mandatory": true, + "parent": "entity", + "isValidLeaf": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "true" + }, + "label": "Business Metadata", + "description": "Business Metadata", + "accessTypeRestrictions": [ + "entity-update-business-metadata" + ] + }, + { + "itemId": 16, + "name": "classification", + "type": "string", + "level": 40, + "mandatory": true, + "parent": "entity", + "isValidLeaf": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { + "wildCard": "true", + "ignoreCase": "false" + }, + "label": "Targetted classifications", + "description": "Targetted classifications", + "accessTypeRestrictions": [ + "entity-add-classification", + "entity-update-classification", + "entity-remove-classification" + ] + } + ], + "accessTypes": [ + { + "itemId": 1, + "name": "type-create", + "label": "Create Type", + "impliedGrants": + [ + "type-read" + ] + }, + { + "itemId": 2, + "name": "type-update", + "label": "Update Type", + "impliedGrants": + [ + "type-read" + ] + }, + { + "itemId": 3, + "name": "type-delete", + "label": "Delete Type", + "impliedGrants": + [ + "type-read" + ] + }, + { + "itemId": 4, + "name": "entity-read", + "label": "Read Entity" + }, + { + "itemId": 5, + "name": "entity-create", + "label": "Create Entity" + }, + { + "itemId": 6, + "name": "entity-update", + "label": "Update Entity" + }, + { + "itemId": 7, + "name": "entity-delete", + "label": "Delete Entity" + }, + { + "itemId": 8, + "name": "entity-add-classification", + "label": "Add Classification" + }, + { + "itemId": 9, + "name": "entity-update-classification", + "label": "Update Classification" + }, + { + "itemId": 10, + "name": "entity-remove-classification", + "label": "Remove Classification" + }, + { + "itemId": 11, + "name": "admin-export", + "label": "Admin Export" + }, + { + "itemId": 12, + "name": "admin-import", + "label": "Admin Import" + }, + { + "itemId": 13, + "name": "add-relationship", + "label": "Add Relationship" + }, + { + "itemId": 14, + "name": "update-relationship", + "label": "Update Relationship" + }, + { + "itemId": 15, + "name": "remove-relationship", + "label": "Remove Relationship" + }, + { + "itemId": 16, + "name": "admin-purge", + "label": "Admin Purge" + }, + { + "itemId": 17, + "name": "entity-add-label", + "label": "Add Label" + }, + { + "itemId": 18, + "name": "entity-remove-label", + "label": "Remove Label" + }, + { + "itemId": 19, + "name": "entity-update-business-metadata", + "label": "Update Business Metadata" + }, + { + "itemId": 20, + "name": "type-read", + "label": "Read Type" + }, + { + "itemId": 21, + "name": "admin-audits", + "label": "Admin Audits" + }, + { + "itemId": 22, + "name": "admin-entity-audits", + "label": "Admin Entity Audits" + }, + { + "itemId": 23, + "name": "admin-repair-index", + "label": "Admin Repair Index" + }, + { + "itemId": 24, + "name": "admin-task-cud", + "label": "Admin task CUD API" + }, + { + "itemId": 25, + "name": "admin-featureFlag-cud", + "label": "Admin featureflag CUD API" + } + + ], + "configs": [ + { + "itemId": 1, + "name": "username", + "type": "string", + "mandatory": true, + "label": "Username" + }, + { + "itemId": 2, + "name": "password", + "type": "password", + "mandatory": true, + "label": "Password" + }, + { + "itemId": 3, + "name": "atlas.rest.address", + "type": "string", + "mandatory": true, + "defaultValue": "http://localhost:21000" + }, + { + "itemId": 4, + "name": "commonNameForCertificate", + "type": "string", + "mandatory": false, + "label": "Common Name for Certificate" + }, + + { + "itemId": 5, + "name": "ranger.plugin.audit.filters", + "type": "string", + "subType": "", + "mandatory": false, + "validationRegEx":"", + "validationMessage": "", + "uiHint":"", + "label": "Ranger Default Audit Filters", + "defaultValue": "[ {'accessResult': 'DENIED', 'isAudited': true}, {'users':['atlas'] ,'isAudited':false} ]" + } + ], + "options": { + "enableDenyAndExceptionsInPolicies": "true" + }, + "policyConditions": [ + { + "itemId": 1, + "name": "excludeRoles", + "evaluator": "org.apache.atlas.plugin.conditionevaluator.AtlanHasAnyRole", + "description": "Roles to exclude for given policy" + }, + { + "itemId": 2, + "name": "excludeEntityTypes", + "evaluator": "org.apache.atlas.plugin.conditionevaluator.AtlanExcludeResourceByType", + "description": "Roles to exclude for given policy" + } + + ] +} diff --git a/auth-common/src/main/resources/service-defs/atlas-servicedef-atlas_tag.json b/auth-common/src/main/resources/service-defs/atlas-servicedef-atlas_tag.json new file mode 100644 index 00000000000..98ff10877f5 --- /dev/null +++ b/auth-common/src/main/resources/service-defs/atlas-servicedef-atlas_tag.json @@ -0,0 +1,94 @@ +{ + "id":100, + "name": "tag", + "displayName": "tag", + "implClass": "org.apache.atlas.services.tag.RangerServiceTag", + "label": "TAG", + "description": "TAG Service Definition", + "guid": "0d047248-baff-4cf9-8e9e-d5d377284b2e", + "options": + { + "ui.pages":"tag-based-policies" + }, + "resources": + [ + { + "itemId":1, + "name": "tag", + "type": "string", + "level": 1, + "parent": "", + "mandatory": true, + "lookupSupported": true, + "recursiveSupported": false, + "excludesSupported": false, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { "wildCard":false, "ignoreCase":false }, + "validationRegEx":"", + "validationMessage": "", + "uiHint":"{ \"singleValue\":true }", + "label": "TAG", + "description": "TAG" + } + ], + + "accessTypes": + [ + + ], + + "configs": + [ + { + "itemId":1, + "name": "ranger.plugin.audit.filters", + "type": "string", + "subType": "", + "mandatory": false, + "validationRegEx":"", + "validationMessage": "", + "uiHint":"", + "label": "Ranger Default Audit Filters", + "defaultValue": "[ {'accessResult': 'DENIED', 'isAudited': true} ]" + } + ], + + "enums": + [ + + ], + + "contextEnrichers": + [ + { + "itemId": 1, + "name" : "TagEnricher", + "enricher" : "org.apache.atlas.plugin.contextenricher.RangerTagEnricher", + "enricherOptions" : { + "tagRetrieverClassName": "org.apache.atlas.plugin.contextenricher.RangerAdminTagRetriever", + "tagRefresherPollingInterval": 60000 + } + } + ], + + "policyConditions": + [ + { + "itemId":1, + "name":"accessed-after-expiry", + "evaluator": "org.apache.atlas.plugin.conditionevaluator.RangerScriptTemplateConditionEvaluator", + "evaluatorOptions" : { "scriptTemplate":"ctx.isAccessedAfter('expiry_date');" }, + "uiHint": "{ \"singleValue\":true }", + "label":"Accessed after expiry_date (yes/no)?", + "description": "Accessed after expiry_date? (yes/no)" + }, + { + "itemId":2, + "name":"expression", + "evaluator": "org.apache.atlas.plugin.conditionevaluator.RangerScriptConditionEvaluator", + "evaluatorOptions" : {"engineName":"JavaScript", "ui.isMultiline":"true"}, + "label":"Enter boolean expression", + "description": "Boolean expression" + } + ] +} diff --git a/auth-common/src/main/resources/service-defs/atlas-servicedef-heka.json b/auth-common/src/main/resources/service-defs/atlas-servicedef-heka.json new file mode 100644 index 00000000000..2edbc1f8bbb --- /dev/null +++ b/auth-common/src/main/resources/service-defs/atlas-servicedef-heka.json @@ -0,0 +1,244 @@ +{ + "name": "heka", + "displayName": "heka", + "implClass": "com.heka.ranger.service.RangerServiceHeka", + "label": "Heka", + "description": "Heka", + "id": 204, + "guid": "379a9fe5-1b6e-4091-a584-4890e245e6c2", + "isEnabled": true, + "createdBy": "Admin", + "updatedBy": "Admin", + "version": 1, + "options": { "enableDenyAndExceptionsInPolicies": "true" }, + "configs": [ + { + "itemId": 1, + "name": "service_url", + "type": "string", + "mandatory": true, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "Service Url" + } + ], + "resources": [ + { + "itemId": 1, + "name": "entity-type", + "type": "string", + "level": 10, + "mandatory": true, + "lookupSupported": false, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { "wildCard": "true", "ignoreCase": "false" }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "Entity Type", + "description": "Entity Type", + "accessTypeRestrictions": [], + "isValidLeaf": true + }, + { + "itemId": 2, + "name": "entity", + "type": "string", + "level": 20, + "parent": "entity-type", + "mandatory": true, + "lookupSupported": false, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { "wildCard": "true", "ignoreCase": "true" }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "Entity ID", + "description": "Entity ID", + "accessTypeRestrictions": [], + "isValidLeaf": true + } + ], + "accessTypes": [ + { "itemId": 1, "name": "select", "label": "Select", "impliedGrants": [] }, + { + "itemId": 12, + "name": "all", + "label": "All", + "impliedGrants": ["select"] + } + ], + "policyConditions": [], + "contextEnrichers": [], + "enums": [], + "dataMaskDef": { + "maskTypes": [ + { + "itemId": 1, + "name": "MASK_REDACT", + "label": "Redact", + "description": "Replace lowercase with \u0027x\u0027, uppercase with \u0027X\u0027, digits with \u00270\u0027", + "transformer": "cast(regexp_replace(regexp_replace(regexp_replace({col},\u0027([A-Z])\u0027, \u0027X\u0027),\u0027([a-z])\u0027,\u0027x\u0027),\u0027([0-9])\u0027,\u00270\u0027) as {type})", + "dataMaskOptions": {} + }, + { + "itemId": 2, + "name": "MASK_SHOW_LAST_4", + "label": "Partial mask: show last 4", + "description": "Show last 4 characters; replace rest with \u0027X\u0027", + "transformer": "cast(concat(regexp_replace(RIGHT({col}, -4), \u0027.\u0027, \u0027X\u0027)), regexp_replace({col}, \u0027(.*)(.{4}$)\u0027, \u0027\\2\u0027)) as {type})", + "dataMaskOptions": {} + }, + { + "itemId": 3, + "name": "MASK_SHOW_FIRST_4", + "label": "Partial mask: show first 4", + "description": "Show first 4 characters; replace rest with \u0027x\u0027", + "transformer": "cast(regexp_replace({col}, \u0027(^.{4})(.*)\u0027, \u0027\\1XXXX\u0027) as {type})", + "dataMaskOptions": {} + }, + { + "itemId": 4, + "name": "MASK_HASH", + "label": "Hash", + "description": "Hash the value of a varchar with sha256", + "transformer": "cast(md5({col}) as {type})", + "dataMaskOptions": {} + }, + { + "itemId": 5, + "name": "MASK_NULL", + "label": "Nullify", + "description": "Replace with NULL", + "dataMaskOptions": {} + }, + { + "itemId": 6, + "name": "MASK_NONE", + "label": "Unmasked (retain original value)", + "description": "No masking", + "dataMaskOptions": {} + }, + { + "itemId": 12, + "name": "MASK_DATE_SHOW_YEAR", + "label": "Date: show only year", + "description": "Date: show only year", + "transformer": "YEAR({col})", + "dataMaskOptions": {} + }, + { + "itemId": 13, + "name": "CUSTOM", + "label": "Custom", + "description": "Custom", + "dataMaskOptions": {} + } + ], + "accessTypes": [ + { + "itemId": 1, + "name": "select", + "label": "Select", + "impliedGrants": [] + } + ], + "resources": [ + { + "itemId": 1, + "name": "entity-type", + "type": "string", + "level": 10, + "mandatory": true, + "lookupSupported": false, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { "wildCard": "true", "ignoreCase": "false" }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "Entity Type", + "description": "Entity Type", + "accessTypeRestrictions": [], + "isValidLeaf": true + }, + { + "itemId": 2, + "name": "entity", + "type": "string", + "level": 20, + "parent": "entity-type", + "mandatory": true, + "lookupSupported": false, + "recursiveSupported": false, + "excludesSupported": true, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { "wildCard": "true", "ignoreCase": "true" }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "", + "label": "Entity ID", + "description": "Entity ID", + "accessTypeRestrictions": [], + "isValidLeaf": true + } + ] + }, + "rowFilterDef": { + "accessTypes": [ + { + "itemId": 1, + "name": "select", + "label": "Select", + "impliedGrants": [] + } + ], + "resources": [ + { + "itemId": 1, + "name": "entity-type", + "type": "string", + "level": 10, + "mandatory": true, + "lookupSupported": false, + "recursiveSupported": false, + "excludesSupported": false, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { "wildCard": "true", "ignoreCase": "false" }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "{ \"singleValue\":true }", + "label": "Entity Type", + "description": "Entity Type", + "accessTypeRestrictions": [], + "isValidLeaf": false + }, + { + "itemId": 2, + "name": "entity", + "type": "string", + "level": 20, + "parent": "entity-type", + "mandatory": true, + "lookupSupported": false, + "recursiveSupported": false, + "excludesSupported": false, + "matcher": "org.apache.atlas.plugin.resourcematcher.RangerDefaultResourceMatcher", + "matcherOptions": { "wildCard": "true", "ignoreCase": "true" }, + "validationRegEx": "", + "validationMessage": "", + "uiHint": "{ \"singleValue\":true }", + "label": "Entity ID", + "description": "Entity ID", + "accessTypeRestrictions": [], + "isValidLeaf": true + } + ] + } +} \ No newline at end of file diff --git a/auth-plugin-atlas/pom.xml b/auth-plugin-atlas/pom.xml new file mode 100644 index 00000000000..ba7f98e5aa7 --- /dev/null +++ b/auth-plugin-atlas/pom.xml @@ -0,0 +1,51 @@ + + + + + apache-atlas + org.apache.atlas + 3.0.0-SNAPSHOT + + 4.0.0 + + auth-plugin-atlas + + + 17 + 17 + + + + + + org.apache.atlas + auth-agents-common + ${project.version} + + + + org.apache.atlas + atlas-authorization + ${project.version} + + + + \ No newline at end of file diff --git a/auth-plugin-atlas/src/main/java/org/apache/atlas/authorization/atlas/authorizer/RangerAtlasAuthorizer.java b/auth-plugin-atlas/src/main/java/org/apache/atlas/authorization/atlas/authorizer/RangerAtlasAuthorizer.java new file mode 100644 index 00000000000..3303fd32e7e --- /dev/null +++ b/auth-plugin-atlas/src/main/java/org/apache/atlas/authorization/atlas/authorizer/RangerAtlasAuthorizer.java @@ -0,0 +1,943 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.authorization.atlas.authorizer; + +import org.apache.atlas.authorize.AtlasAccessRequest; +import org.apache.atlas.authorize.AtlasAccessResult; +import org.apache.atlas.authorize.AtlasAccessorResponse; +import org.apache.atlas.authorize.AtlasAdminAccessRequest; +import org.apache.atlas.authorize.AtlasAuthorizationException; +import org.apache.atlas.authorize.AtlasAuthorizer; +import org.apache.atlas.authorize.AtlasEntityAccessRequest; +import org.apache.atlas.authorize.AtlasPrivilege; +import org.apache.atlas.authorize.AtlasRelationshipAccessRequest; +import org.apache.atlas.authorize.AtlasSearchResultScrubRequest; +import org.apache.atlas.authorize.AtlasTypeAccessRequest; +import org.apache.atlas.authorize.AtlasTypesDefFilterRequest; +import org.apache.atlas.authorizer.AtlasAuthorizationUtils; +import org.apache.atlas.model.discovery.AtlasSearchResult; +import org.apache.atlas.model.instance.AtlasClassification; +import org.apache.atlas.model.instance.AtlasEntityHeader; +import org.apache.atlas.model.typedef.AtlasBaseTypeDef; +import org.apache.atlas.model.typedef.AtlasTypesDef; +import org.apache.atlas.type.AtlasTypeRegistry; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.atlas.audit.model.AuthzAuditEvent; +import org.apache.atlas.plugin.audit.RangerDefaultAuditHandler; +import org.apache.atlas.plugin.contextenricher.RangerTagForEval; +import org.apache.atlas.plugin.model.RangerServiceDef; +import org.apache.atlas.plugin.model.RangerTag; +import org.apache.atlas.plugin.policyengine.RangerAccessRequestImpl; +import org.apache.atlas.plugin.policyengine.RangerAccessResourceImpl; +import org.apache.atlas.plugin.policyengine.RangerAccessResult; +import org.apache.atlas.plugin.policyresourcematcher.RangerPolicyResourceMatcher; +import org.apache.atlas.plugin.service.RangerBasePlugin; +import org.apache.atlas.plugin.util.RangerPerfTracer; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; + +import static org.apache.atlas.authorization.atlas.authorizer.RangerAtlasAuthorizerUtil.*; +import static org.apache.atlas.constants.RangerAtlasConstants.*; + + +public class RangerAtlasAuthorizer implements AtlasAuthorizer { + private static final Log LOG = LogFactory.getLog(RangerAtlasAuthorizer.class); + private static final Log PERF_LOG = RangerPerfTracer.getPerfLogger("atlasauth.request"); + + private static volatile RangerBasePlugin atlasPlugin = null; + private static volatile RangerGroupUtil groupUtil = null; + + static final Set CLASSIFICATION_PRIVILEGES = new HashSet() {{ + add(AtlasPrivilege.ENTITY_ADD_CLASSIFICATION); + add(AtlasPrivilege.ENTITY_REMOVE_CLASSIFICATION); + add(AtlasPrivilege.ENTITY_UPDATE_CLASSIFICATION); + }}; + + @Override + public void init() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerAtlasPlugin.init()"); + } + + RangerBasePlugin plugin = atlasPlugin; + + if (plugin == null) { + synchronized (RangerAtlasPlugin.class) { + plugin = atlasPlugin; + + if (plugin == null) { + plugin = new RangerAtlasPlugin(); + plugin.init(); + + plugin.setResultProcessor(new RangerDefaultAuditHandler(plugin.getConfig())); + + atlasPlugin = plugin; + groupUtil = new RangerGroupUtil(atlasPlugin.getUserStore()); + } + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerAtlasPlugin.init()"); + } + } + + @Override + public void init(AtlasTypeRegistry typeRegistry) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerAtlasPlugin.init(typeRegistry)"); + } + + RangerBasePlugin plugin = atlasPlugin; + + if (plugin == null) { + synchronized (RangerAtlasPlugin.class) { + plugin = atlasPlugin; + + if (plugin == null) { + plugin = new RangerAtlasPlugin(typeRegistry); + + plugin.init(); + + plugin.setResultProcessor(new RangerDefaultAuditHandler(plugin.getConfig())); + + atlasPlugin = plugin; + groupUtil = new RangerGroupUtil(atlasPlugin.getUserStore()); + } + } + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerAtlasPlugin.init(typeRegistry)"); + } + } + + @Override + public void cleanUp() { + if (LOG.isDebugEnabled()) { + LOG.debug("==> cleanUp "); + } + } + + @Override + public AtlasAccessResult isAccessAllowed(AtlasAdminAccessRequest request) throws AtlasAuthorizationException { + if (LOG.isDebugEnabled()) { + LOG.debug("==> isAccessAllowed(" + request + ")"); + } + + final AtlasAccessResult ret; + RangerPerfTracer perf = null; + + try { + if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "RangerAtlasAuthorizer.isAccessAllowed(" + request + ")"); + } + + String action = request.getAction() != null ? request.getAction().getType() : null; + RangerAccessResourceImpl rangerResource = new RangerAccessResourceImpl(Collections.singletonMap(RESOURCE_SERVICE, "*")); + RangerAccessRequestImpl rangerRequest = new RangerAccessRequestImpl(rangerResource, action, request.getUser(), request.getUserGroups(), null); + + rangerRequest.setClientIPAddress(request.getClientIPAddress()); + rangerRequest.setAccessTime(request.getAccessTime()); + rangerRequest.setAction(action); + rangerRequest.setForwardedAddresses(request.getForwardedAddresses()); + rangerRequest.setRemoteIPAddress(request.getRemoteIPAddress()); + + + ret = checkAccess(rangerRequest); + } finally { + RangerPerfTracer.log(perf); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== isAccessAllowed(" + request + "): " + ret); + } + + return ret; + } + + @Override + public AtlasAccessResult isAccessAllowed(AtlasEntityAccessRequest request, boolean isAuditEnabled) throws AtlasAuthorizationException { + if (LOG.isDebugEnabled()) { + LOG.debug("==> isAccessAllowed(" + request + ")"); + } + + AtlasAccessResult ret; + RangerPerfTracer perf = null; + RangerAtlasAuditHandler auditHandler = null; + + try { + if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "RangerAtlasAuthorizer.isAccessAllowed(" + request + ")"); + } + + // not initializing audit handler, so that audits are not logged when entity details are NULL or EMPTY STRING + if (isAuditEnabled && !(StringUtils.isEmpty(request.getEntityId()) && request.getClassification() == null && request.getEntity() == null)) { + auditHandler = new RangerAtlasAuditHandler(request, getServiceDef()); + } + + ret = isAccessAllowed(request, auditHandler); + } finally { + RangerPerfTracer.log(perf); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== isAccessAllowed(" + request + "): " + ret); + } + + return ret; + } + + @Override + public AtlasAccessResult isAccessAllowed(AtlasTypeAccessRequest request) throws AtlasAuthorizationException { + if (LOG.isDebugEnabled()) { + LOG.debug("==> isAccessAllowed(" + request + ")"); + } + + final AtlasAccessResult ret; + RangerPerfTracer perf = null; + + try { + if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "RangerAtlasAuthorizer.isAccessAllowed(" + request + ")"); + } + + final String typeName = request.getTypeDef() != null ? request.getTypeDef().getName() : null; + final String typeCategory = request.getTypeDef() != null && request.getTypeDef().getCategory() != null ? request.getTypeDef().getCategory().name() : null; + final String action = request.getAction() != null ? request.getAction().getType() : null; + + RangerAccessResourceImpl rangerResource = new RangerAccessResourceImpl(); + + rangerResource.setValue(RESOURCE_TYPE_NAME, typeName); + rangerResource.setValue(RESOURCE_TYPE_CATEGORY, typeCategory); + + RangerAccessRequestImpl rangerRequest = new RangerAccessRequestImpl(rangerResource, action, request.getUser(), request.getUserGroups(), null); + rangerRequest.setClientIPAddress(request.getClientIPAddress()); + rangerRequest.setAccessTime(request.getAccessTime()); + rangerRequest.setAction(action); + rangerRequest.setForwardedAddresses(request.getForwardedAddresses()); + rangerRequest.setRemoteIPAddress(request.getRemoteIPAddress()); + + boolean isAuditDisabled = ACCESS_TYPE_TYPE_READ.equalsIgnoreCase(action); + + if (isAuditDisabled) { + ret = checkAccess(rangerRequest, null); + } else { + ret = checkAccess(rangerRequest); + } + + } finally { + RangerPerfTracer.log(perf); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== isAccessAllowed(" + request + "): " + ret); + } + + return ret; + } + + @Override + public AtlasAccessResult isAccessAllowed(AtlasRelationshipAccessRequest request) throws AtlasAuthorizationException { + if (LOG.isDebugEnabled()) { + LOG.debug("==> isAccessAllowed(" + request + ")"); + } + + AtlasAccessResult ret; + RangerPerfTracer perf = null; + + try { + if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "RangerAtlasAuthorizer.isAccessAllowed(" + request + ")"); + } + + final String action = request.getAction() != null ? request.getAction().getType() : null; + final Set end1EntityTypeAndSuperTypes = request.getEnd1EntityTypeAndAllSuperTypes(); + final Set end1Classifications = new HashSet(request.getEnd1EntityClassifications()); + final String end1EntityId = request.getEnd1EntityId(); + + final Set end2EntityTypeAndSuperTypes = request.getEnd2EntityTypeAndAllSuperTypes(); + final Set end2Classifications = new HashSet(request.getEnd2EntityClassifications()); + final String end2EntityId = request.getEnd2EntityId(); + + + String relationShipType = request.getRelationshipType(); + + RangerAccessResourceImpl rangerResource = new RangerAccessResourceImpl(); + + RangerAccessRequestImpl rangerRequest = new RangerAccessRequestImpl(rangerResource, action, request.getUser(), request.getUserGroups(), null); + rangerRequest.setClientIPAddress(request.getClientIPAddress()); + rangerRequest.setAccessTime(request.getAccessTime()); + rangerRequest.setAction(action); + rangerRequest.setForwardedAddresses(request.getForwardedAddresses()); + rangerRequest.setRemoteIPAddress(request.getRemoteIPAddress()); + + rangerResource.setValue(RESOURCE_RELATIONSHIP_TYPE, relationShipType); + + + Set classificationsWithSuperTypesEnd1 = new HashSet(); + + for (AtlasClassification classificationToAuthorize : end1Classifications) { + classificationsWithSuperTypesEnd1.addAll(request.getClassificationTypeAndAllSuperTypes(classificationToAuthorize.getTypeName())); + } + + rangerResource.setValue(RESOURCE_END_ONE_ENTITY_TYPE, end1EntityTypeAndSuperTypes); + rangerResource.setValue(RESOURCE_END_ONE_ENTITY_CLASSIFICATION, classificationsWithSuperTypesEnd1); + rangerResource.setValue(RESOURCE_END_ONE_ENTITY_ID, end1EntityId); + + + Set classificationsWithSuperTypesEnd2 = new HashSet(); + + for (AtlasClassification classificationToAuthorize : end2Classifications) { + classificationsWithSuperTypesEnd2.addAll(request.getClassificationTypeAndAllSuperTypes(classificationToAuthorize.getTypeName())); + } + + rangerResource.setValue(RESOURCE_END_TWO_ENTITY_TYPE, end2EntityTypeAndSuperTypes); + rangerResource.setValue(RESOURCE_END_TWO_ENTITY_CLASSIFICATION, classificationsWithSuperTypesEnd2); + rangerResource.setValue(RESOURCE_END_TWO_ENTITY_ID, end2EntityId); + + ret = checkAccess(rangerRequest); + + if (!ret.isAllowed()) { // if resource based policy access not available fallback to check tag-based access. + setClassificationsToRequestContext(end1Classifications, rangerRequest); + ret = checkAccess(rangerRequest); // tag-based check with end1 classification + LOG.info("End1 checkAccess " + ret); + if (ret.isAllowed()) { // + setClassificationsToRequestContext(end2Classifications, rangerRequest); + ret = checkAccess(rangerRequest); // tag-based check with end2 classification + LOG.info("End2 checkAccess " + ret); + } + } + + } finally { + RangerPerfTracer.log(perf); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== isAccessAllowed(" + request + "): " + ret); + } + + return ret; + } + + @Override + public AtlasAccessorResponse getAccessors(AtlasEntityAccessRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> getAccessors(" + request + ")"); + } + + AtlasAccessorResponse ret = new AtlasAccessorResponse(); + RangerPerfTracer perf = null; + + try { + if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "RangerAtlasAuthorizer.getAccessors(" + request + ")"); + } + + final RangerAccessResourceImpl rangerResource = new RangerAccessResourceImpl(); + final RangerAccessRequestImpl rangerRequest = new RangerAccessRequestImpl(); + + toRangerRequest(request, rangerRequest, rangerResource); + rangerRequest.setAccessorsRequested(true); + + RangerAccessResult result = null; + Set tagNames = request.getEntityClassifications(); + if (CollectionUtils.isNotEmpty(tagNames)) { + setClassificationsToRequestContext(tagNames, rangerRequest); + + // check authorization for each classification + for (AtlasClassification classificationToAuthorize : tagNames) { + rangerResource.setValue(RESOURCE_ENTITY_CLASSIFICATION, request.getClassificationTypeAndAllSuperTypes(classificationToAuthorize.getTypeName())); + + result = getAccessors(rangerRequest); + collectAccessors(result, ret); + } + } else { + rangerResource.setValue(RESOURCE_ENTITY_CLASSIFICATION, ENTITY_NOT_CLASSIFIED); + + result = getAccessors(rangerRequest); + collectAccessors(result, ret); + } + } finally { + RangerPerfTracer.log(perf); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== getAccessors(" + request + "): " + ret); + } + return ret; + } + + @Override + public AtlasAccessorResponse getAccessors(AtlasRelationshipAccessRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> getAccessors(" + request + ")"); + } + + AtlasAccessorResponse ret = new AtlasAccessorResponse(); + RangerPerfTracer perf = null; + RangerAccessResult result = null; + + try { + if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "RangerAtlasAuthorizer.getAccessors(" + request + ")"); + } + + final String action = request.getAction() != null ? request.getAction().getType() : null; + RangerAccessResourceImpl rangerResource = new RangerAccessResourceImpl(); + RangerAccessRequestImpl rangerRequest = new RangerAccessRequestImpl(rangerResource, action, request.getUser(), + request.getUserGroups(), null); + rangerRequest.setAccessorsRequested(true); + + + final Set end1EntityTypeAndSuperTypes = request.getEnd1EntityTypeAndAllSuperTypes(); + final Set end1Classifications = new HashSet(request.getEnd1EntityClassifications()); + final String end1EntityId = request.getEnd1EntityId(); + + final Set end2EntityTypeAndSuperTypes = request.getEnd2EntityTypeAndAllSuperTypes(); + final Set end2Classifications = new HashSet(request.getEnd2EntityClassifications()); + final String end2EntityId = request.getEnd2EntityId(); + + + String relationShipType = request.getRelationshipType(); + + + rangerRequest.setClientIPAddress(request.getClientIPAddress()); + rangerRequest.setAccessTime(request.getAccessTime()); + rangerRequest.setAction(action); + rangerRequest.setForwardedAddresses(request.getForwardedAddresses()); + rangerRequest.setRemoteIPAddress(request.getRemoteIPAddress()); + + rangerResource.setValue(RESOURCE_RELATIONSHIP_TYPE, relationShipType); + + + Set classificationsWithSuperTypesEnd1 = new HashSet(); + + for (AtlasClassification classificationToAuthorize : end1Classifications) { + classificationsWithSuperTypesEnd1.addAll(request.getClassificationTypeAndAllSuperTypes(classificationToAuthorize.getTypeName())); + } + + rangerResource.setValue(RESOURCE_END_ONE_ENTITY_TYPE, end1EntityTypeAndSuperTypes); + rangerResource.setValue(RESOURCE_END_ONE_ENTITY_CLASSIFICATION, classificationsWithSuperTypesEnd1); + rangerResource.setValue(RESOURCE_END_ONE_ENTITY_ID, end1EntityId); + + + Set classificationsWithSuperTypesEnd2 = new HashSet(); + + for (AtlasClassification classificationToAuthorize : end2Classifications) { + classificationsWithSuperTypesEnd2.addAll(request.getClassificationTypeAndAllSuperTypes(classificationToAuthorize.getTypeName())); + } + + rangerResource.setValue(RESOURCE_END_TWO_ENTITY_TYPE, end2EntityTypeAndSuperTypes); + rangerResource.setValue(RESOURCE_END_TWO_ENTITY_CLASSIFICATION, classificationsWithSuperTypesEnd2); + rangerResource.setValue(RESOURCE_END_TWO_ENTITY_ID, end2EntityId); + + result = getAccessors(rangerRequest); + collectAccessors(result, ret); + + // Check tag-based access. + setClassificationsToRequestContext(end1Classifications, rangerRequest); + RangerAccessResult resultEnd1 = getAccessors(rangerRequest); // tag-based accessors with end1 classification + + setClassificationsToRequestContext(end2Classifications, rangerRequest); + RangerAccessResult resultEnd2 = getAccessors(rangerRequest); // tag-based accessors with end2 classification + collectAccessors(resultEnd1, resultEnd2, ret); + } finally { + RangerPerfTracer.log(perf); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== getAccessors(" + request + "): " + ret); + } + + return ret; + } + + @Override + public AtlasAccessorResponse getAccessors(AtlasTypeAccessRequest request) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> getAccessors(" + request + ")"); + } + + AtlasAccessorResponse ret = new AtlasAccessorResponse(); + RangerPerfTracer perf = null; + + try { + if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "RangerAtlasAuthorizer.getAccessors(" + request + ")"); + } + + final String action = request.getAction() != null ? request.getAction().getType() : null; + + RangerAccessResourceImpl rangerResource = new RangerAccessResourceImpl(); + RangerAccessRequestImpl rangerRequest = new RangerAccessRequestImpl(rangerResource, action, request.getUser(), request.getUserGroups(), null); + rangerRequest.setAccessorsRequested(true); + + + final String typeName = request.getTypeDef() != null ? request.getTypeDef().getName() : null; + final String typeCategory = request.getTypeDef() != null && request.getTypeDef().getCategory() != null ? request.getTypeDef().getCategory().name() : null; + + rangerResource.setValue(RESOURCE_TYPE_NAME, typeName); + rangerResource.setValue(RESOURCE_TYPE_CATEGORY, typeCategory); + + rangerRequest.setClientIPAddress(request.getClientIPAddress()); + rangerRequest.setAccessTime(request.getAccessTime()); + rangerRequest.setAction(action); + rangerRequest.setForwardedAddresses(request.getForwardedAddresses()); + rangerRequest.setRemoteIPAddress(request.getRemoteIPAddress()); + + + RangerAccessResult result = getAccessors(rangerRequest); + collectAccessors(result, ret); + + } finally { + RangerPerfTracer.log(perf); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== getAccessors(" + request + "): " + ret); + } + return ret; + } + + @Override + public Set getRolesForCurrentUser(String userName, Set groups) { + Set ret = new HashSet<>(); + + RangerBasePlugin plugin = atlasPlugin; + + ret = plugin.getRolesFromUserAndGroups(userName, groups); + + return ret; + } + + @Override + public void scrubSearchResults(AtlasSearchResultScrubRequest request) throws AtlasAuthorizationException { + if (LOG.isDebugEnabled()) { + LOG.debug("==> scrubSearchResults(" + request + ")"); + } + + RangerPerfTracer perf = null; + + try { + if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) { + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "RangerAtlasAuthorizer.scrubSearchResults(" + request + ")"); + } + + final AtlasSearchResult result = request.getSearchResult(); + + if (CollectionUtils.isNotEmpty(result.getEntities())) { + for (AtlasEntityHeader entity : result.getEntities()) { + checkAccessAndScrub(entity, request); + } + } + + if (CollectionUtils.isNotEmpty(result.getFullTextResult())) { + for (AtlasSearchResult.AtlasFullTextResult fullTextResult : result.getFullTextResult()) { + if (fullTextResult != null) { + checkAccessAndScrub(fullTextResult.getEntity(), request); + } + } + } + + if (MapUtils.isNotEmpty(result.getReferredEntities())) { + for (AtlasEntityHeader entity : result.getReferredEntities().values()) { + checkAccessAndScrub(entity, request); + } + } + } finally { + RangerPerfTracer.log(perf); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== scrubSearchResults(): " + request); + } + } + + @Override + public void scrubSearchResults(AtlasSearchResultScrubRequest request, boolean isScrubAuditEnabled) throws AtlasAuthorizationException { + if (LOG.isDebugEnabled()) + LOG.debug("==> scrubSearchResults(" + request + " " + isScrubAuditEnabled); + RangerPerfTracer perf = null; + try { + if (RangerPerfTracer.isPerfTraceEnabled(PERF_LOG)) + perf = RangerPerfTracer.getPerfTracer(PERF_LOG, "RangerAtlasAuthorizer.scrubSearchResults(" + request + ")"); + AtlasSearchResult result = request.getSearchResult(); + if (CollectionUtils.isNotEmpty(result.getEntities())) { + for (AtlasEntityHeader entity : result.getEntities()) { + checkAccessAndScrub(entity, request, isScrubAuditEnabled); + } + } + if (CollectionUtils.isNotEmpty(result.getFullTextResult())) { + for (AtlasSearchResult.AtlasFullTextResult fullTextResult : result.getFullTextResult()) { + if (fullTextResult != null) + checkAccessAndScrub(fullTextResult.getEntity(), request, isScrubAuditEnabled); + } + } + if (MapUtils.isNotEmpty(result.getReferredEntities())) { + for (AtlasEntityHeader entity : result.getReferredEntities().values()) { + checkAccessAndScrub(entity, request, isScrubAuditEnabled); + } + } + } finally { + RangerPerfTracer.log(perf); + } + if (LOG.isDebugEnabled()) + LOG.debug("<== scrubSearchResults(): " + request + " " + isScrubAuditEnabled); + } + + @Override + public void filterTypesDef(AtlasTypesDefFilterRequest request) throws AtlasAuthorizationException { + + AtlasTypesDef typesDef = request.getTypesDef(); + + filterTypes(request, typesDef.getEnumDefs()); + filterTypes(request, typesDef.getStructDefs()); + filterTypes(request, typesDef.getEntityDefs()); + filterTypes(request, typesDef.getClassificationDefs()); + filterTypes(request, typesDef.getRelationshipDefs()); + filterTypes(request, typesDef.getBusinessMetadataDefs()); + + } + + private void filterTypes(AtlasAccessRequest request, List typeDefs)throws AtlasAuthorizationException { + if (typeDefs != null) { + for (ListIterator iter = typeDefs.listIterator(); iter.hasNext();) { + AtlasBaseTypeDef typeDef = iter.next(); + AtlasTypeAccessRequest typeRequest = new AtlasTypeAccessRequest(request.getAction(), typeDef, request.getUser(), request.getUserGroups()); + + typeRequest.setClientIPAddress(request.getClientIPAddress()); + typeRequest.setForwardedAddresses(request.getForwardedAddresses()); + typeRequest.setRemoteIPAddress(request.getRemoteIPAddress()); + + if (!isAccessAllowed(typeRequest).isAllowed()) { + iter.remove(); + } + } + } + } + + + private RangerServiceDef getServiceDef() { + RangerBasePlugin plugin = atlasPlugin; + + return plugin != null ? plugin.getServiceDef() : null; + } + + // deprecated: isAccessAllowed only checks for atlas and atlas_tag policies, use AuthorizationUtil.isAccessAllowed + // to include the checks for abac policies as well. + private AtlasAccessResult isAccessAllowed(AtlasEntityAccessRequest request, RangerAtlasAuditHandler auditHandler) throws AtlasAuthorizationException { + if (LOG.isDebugEnabled()) { + LOG.debug("==> isAccessAllowed(" + request + ")"); + } + AtlasAccessResult ret = new AtlasAccessResult(false); + + try { + final String action = request.getAction() != null ? request.getAction().getType() : null; + final Set entityTypes = request.getEntityTypeAndAllSuperTypes(); + final String entityId = request.getEntityId(); + final String classification = request.getClassification() != null ? request.getClassification().getTypeName() : null; + final RangerAccessRequestImpl rangerRequest = new RangerAccessRequestImpl(); + final RangerAccessResourceImpl rangerResource = new RangerAccessResourceImpl(); + final String ownerUser = request.getEntity() != null ? (String) request.getEntity().getAttribute(RESOURCE_ENTITY_OWNER) : null; + + rangerResource.setValue(RESOURCE_ENTITY_TYPE, entityTypes); + rangerResource.setValue(RESOURCE_ENTITY_ID, entityId); + rangerResource.setOwnerUser(ownerUser); + rangerRequest.setAccessType(action); + rangerRequest.setAction(action); + rangerRequest.setUser(request.getUser()); + rangerRequest.setUserGroups(request.getUserGroups()); + rangerRequest.setClientIPAddress(request.getClientIPAddress()); + rangerRequest.setAccessTime(request.getAccessTime()); + rangerRequest.setResource(rangerResource); + rangerRequest.setForwardedAddresses(request.getForwardedAddresses()); + rangerRequest.setRemoteIPAddress(request.getRemoteIPAddress()); + + if (AtlasPrivilege.ENTITY_ADD_LABEL.equals(request.getAction()) || AtlasPrivilege.ENTITY_REMOVE_LABEL.equals(request.getAction())) { + rangerResource.setValue(RESOURCE_ENTITY_LABEL, request.getLabel()); + } else if (AtlasPrivilege.ENTITY_UPDATE_BUSINESS_METADATA.equals(request.getAction())) { + rangerResource.setValue(RESOURCE_ENTITY_BUSINESS_METADATA, request.getBusinessMetadata()); + } else if (StringUtils.isNotEmpty(classification) && CLASSIFICATION_PRIVILEGES.contains(request.getAction())) { + rangerResource.setValue(RESOURCE_CLASSIFICATION, request.getClassificationTypeAndAllSuperTypes(classification)); + } + + if (CollectionUtils.isNotEmpty(request.getEntityClassifications())) { + Set entityClassifications = request.getEntityClassifications(); + Map contextOjb = rangerRequest.getContext(); + + Set rangerTagForEval = getRangerServiceTag(entityClassifications); + + if (contextOjb == null) { + Map contextOjb1 = new HashMap(); + contextOjb1.put("CLASSIFICATIONS", rangerTagForEval); + rangerRequest.setContext(contextOjb1); + } else { + contextOjb.put("CLASSIFICATIONS", rangerTagForEval); + rangerRequest.setContext(contextOjb); + } + + // check authorization for each classification + for (AtlasClassification classificationToAuthorize : request.getEntityClassifications()) { + rangerResource.setValue(RESOURCE_ENTITY_CLASSIFICATION, request.getClassificationTypeAndAllSuperTypes(classificationToAuthorize.getTypeName())); + + ret = checkAccess(rangerRequest, auditHandler); + + if (!ret.isAllowed()) { + break; + } + } + } else { + rangerResource.setValue(RESOURCE_ENTITY_CLASSIFICATION, ENTITY_NOT_CLASSIFIED ); + + ret = checkAccess(rangerRequest, auditHandler); + } + + } finally { + if(auditHandler != null) { + auditHandler.flushAudit(); + } + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== isAccessAllowed(" + request + "): " + ret); + } + + return ret; + } + + + private void setClassificationsToRequestContext(Set entityClassifications, RangerAccessRequestImpl rangerRequest) { + Map contextOjb = rangerRequest.getContext(); + + Set rangerTagForEval = getRangerServiceTag(entityClassifications); + + if (contextOjb == null) { + Map contextOjb1 = new HashMap(); + contextOjb1.put("CLASSIFICATIONS", rangerTagForEval); + rangerRequest.setContext(contextOjb1); + } else { + contextOjb.put("CLASSIFICATIONS", rangerTagForEval); + rangerRequest.setContext(contextOjb); + } + } + + Set getRangerServiceTag(Set classifications) { + Set atlasClassificationSet = new HashSet<>(); + for (AtlasClassification classification : classifications) { + RangerTag rangerTag = new RangerTag(null, classification.getTypeName(), getClassificationAttributes(classification), RangerTag.OWNER_SERVICERESOURCE); + RangerTagForEval tagForEval = new RangerTagForEval(rangerTag, RangerPolicyResourceMatcher.MatchType.SELF); + atlasClassificationSet.add(tagForEval); + } + return atlasClassificationSet; + } + + private Map getClassificationAttributes(AtlasClassification classification) { + Map attributes = classification.getAttributes(); + final Map result = new HashMap(); + if(attributes!=null) { + for (final Map.Entry entry : attributes.entrySet()) { + result.put(entry.getKey(), String.valueOf(entry.getValue())); + } + } + return result; + } + + private AtlasAccessResult checkAccess(RangerAccessRequestImpl request) { + AtlasAccessResult result = null; + String userName = request.getUser(); + RangerBasePlugin plugin = atlasPlugin; + + if (plugin != null) { + + groupUtil.setUserStore(atlasPlugin.getUserStore()); + + request.setUserGroups(groupUtil.getContainedGroups(userName)); + + if (LOG.isDebugEnabled()) { + LOG.debug("Setting UserGroup for user: " + userName + " Groups: " + groupUtil.getContainedGroups(userName)); + } + + RangerAccessResult rangerResult = plugin.isAccessAllowed(request); + if (rangerResult != null) { + result = new AtlasAccessResult(rangerResult.getIsAllowed(), rangerResult.getPolicyId(), rangerResult.getPolicyPriority()); + } + + } else { + LOG.warn("RangerAtlasPlugin not initialized. Access blocked!!!"); + } + + return result; + } + + private AtlasAccessResult checkAccess(RangerAccessRequestImpl request, RangerAtlasAuditHandler auditHandler) { + AtlasAccessResult result = null; + + RangerBasePlugin plugin = atlasPlugin; + String userName = request.getUser(); + + if (plugin != null) { + + groupUtil.setUserStore(atlasPlugin.getUserStore()); + + request.setUserGroups(groupUtil.getContainedGroups(userName)); + + if (LOG.isDebugEnabled()) { + LOG.debug("Setting UserGroup for user :" + userName + " Groups: " + groupUtil.getContainedGroups(userName)); + } + + RangerAccessResult rangerResult = plugin.isAccessAllowed(request, auditHandler); + if (rangerResult != null) { + result = new AtlasAccessResult(rangerResult.getIsAllowed(), rangerResult.getPolicyId(), rangerResult.getPolicyPriority()); + } + + } else { + LOG.warn("RangerAtlasPlugin not initialized. Access blocked!!!"); + } + + return result; + } + + private RangerAccessResult getAccessors(RangerAccessRequestImpl request) { + RangerAccessResult result = null; + + RangerBasePlugin plugin = atlasPlugin; + String userName = request.getUser(); + + if (plugin != null) { + + groupUtil.setUserStore(atlasPlugin.getUserStore()); + request.setUserGroups(groupUtil.getContainedGroups(userName)); + + if (LOG.isDebugEnabled()) { + LOG.debug("Setting UserGroup for user :" + userName + " Groups: " + groupUtil.getContainedGroups(userName)); + } + + result = plugin.getAssetAccessors(request); + + } else { + LOG.warn("RangerAtlasPlugin not initialized. Could not find Accessors!!!"); + } + + return result; + } + + private void checkAccessAndScrub(AtlasEntityHeader entity, AtlasSearchResultScrubRequest request) throws AtlasAuthorizationException { + checkAccessAndScrub(entity, request, false); + } + + private void checkAccessAndScrub(AtlasEntityHeader entity, AtlasSearchResultScrubRequest request, boolean isScrubAuditEnabled) throws AtlasAuthorizationException { + if (entity != null && request != null) { + final AtlasEntityAccessRequest entityAccessRequest = new AtlasEntityAccessRequest(request.getTypeRegistry(), AtlasPrivilege.ENTITY_READ, entity, request.getUser(), request.getUserGroups()); + + entityAccessRequest.setClientIPAddress(request.getClientIPAddress()); + entityAccessRequest.setForwardedAddresses(request.getForwardedAddresses()); + entityAccessRequest.setRemoteIPAddress(request.getRemoteIPAddress()); + + boolean isEntityAccessAllowed = AtlasAuthorizationUtils.isAccessAllowed(entityAccessRequest, isScrubAuditEnabled); + if (!isEntityAccessAllowed) { + scrubEntityHeader(entity, request.getTypeRegistry()); + } + } + } + + class RangerAtlasPlugin extends RangerBasePlugin { + RangerAtlasPlugin() { + super("atlas", "atlas"); + } + + RangerAtlasPlugin(AtlasTypeRegistry typeRegistry) { + super("atlas", "atlas", typeRegistry); + } + } + + class RangerAtlasAuditHandler extends RangerDefaultAuditHandler { + private final Map auditEvents; + private final String resourcePath; + private boolean denyExists = false; + + public RangerAtlasAuditHandler(AtlasEntityAccessRequest request, RangerServiceDef serviceDef) { + Collection classifications = request.getEntityClassifications(); + String strClassifications = classifications == null ? "[]" : classifications.toString(); + + if (request.getClassification() != null) { + strClassifications += ("," + request.getClassification().getTypeName()); + } + + RangerAccessResourceImpl rangerResource = new RangerAccessResourceImpl(); + + rangerResource.setServiceDef(serviceDef); + rangerResource.setValue(RESOURCE_ENTITY_TYPE, request.getEntityType()); + rangerResource.setValue(RESOURCE_ENTITY_CLASSIFICATION, strClassifications); + rangerResource.setValue(RESOURCE_ENTITY_ID, request.getEntityId()); + + if (AtlasPrivilege.ENTITY_ADD_LABEL.equals(request.getAction()) || AtlasPrivilege.ENTITY_REMOVE_LABEL.equals(request.getAction())) { + rangerResource.setValue(RESOURCE_ENTITY_LABEL, "label=" + request.getLabel()); + } else if (AtlasPrivilege.ENTITY_UPDATE_BUSINESS_METADATA.equals(request.getAction())) { + rangerResource.setValue(RESOURCE_ENTITY_BUSINESS_METADATA, "business-metadata=" + request.getBusinessMetadata()); + } + + auditEvents = new HashMap<>(); + resourcePath = rangerResource.getAsString(); + } + + @Override + public void processResult(RangerAccessResult result) { + if (denyExists) { // nothing more to do, if a deny already encountered + return; + } + + AuthzAuditEvent auditEvent = super.getAuthzEvents(result); + + if (auditEvent != null) { + // audit event might have list of entity-types and classification-types; overwrite with the values in original request + if (resourcePath != null) { + auditEvent.setResourcePath(resourcePath); + } + + if (!result.getIsAllowed()) { + denyExists = true; + + auditEvents.clear(); + } + + auditEvents.put(auditEvent.getPolicyId() + auditEvent.getAccessType(), auditEvent); + } + } + + + public void flushAudit() { + if (auditEvents != null) { + for (AuthzAuditEvent auditEvent : auditEvents.values()) { + logAuthzAudit(auditEvent); + } + } + } + } +} diff --git a/auth-plugin-atlas/src/main/java/org/apache/atlas/authorization/atlas/authorizer/RangerAtlasAuthorizerUtil.java b/auth-plugin-atlas/src/main/java/org/apache/atlas/authorization/atlas/authorizer/RangerAtlasAuthorizerUtil.java new file mode 100644 index 00000000000..a9dbbc16f9d --- /dev/null +++ b/auth-plugin-atlas/src/main/java/org/apache/atlas/authorization/atlas/authorizer/RangerAtlasAuthorizerUtil.java @@ -0,0 +1,151 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.authorization.atlas.authorizer; + +import org.apache.atlas.authorize.AtlasAccessorResponse; +import org.apache.atlas.authorize.AtlasEntityAccessRequest; +import org.apache.atlas.authorize.AtlasPrivilege; +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.atlas.plugin.model.RangerPolicy; +import org.apache.atlas.plugin.policyengine.RangerAccessRequestImpl; +import org.apache.atlas.plugin.policyengine.RangerAccessResourceImpl; +import org.apache.atlas.plugin.policyengine.RangerAccessResult; +import org.apache.atlas.plugin.policyevaluator.RangerPolicyItemEvaluator; + +import java.util.Set; + +import static org.apache.atlas.authorization.atlas.authorizer.RangerAtlasAuthorizer.CLASSIFICATION_PRIVILEGES; +import static org.apache.atlas.constants.RangerAtlasConstants.RESOURCE_CLASSIFICATION; +import static org.apache.atlas.constants.RangerAtlasConstants.RESOURCE_ENTITY_BUSINESS_METADATA; +import static org.apache.atlas.constants.RangerAtlasConstants.RESOURCE_ENTITY_ID; +import static org.apache.atlas.constants.RangerAtlasConstants.RESOURCE_ENTITY_LABEL; +import static org.apache.atlas.constants.RangerAtlasConstants.RESOURCE_ENTITY_OWNER; +import static org.apache.atlas.constants.RangerAtlasConstants.RESOURCE_ENTITY_TYPE; + + +public class RangerAtlasAuthorizerUtil { + + static void toRangerRequest(AtlasEntityAccessRequest request, RangerAccessRequestImpl rangerRequest, RangerAccessResourceImpl rangerResource){ + + final String action = request.getAction() != null ? request.getAction().getType() : null; + final Set entityTypes = request.getEntityTypeAndAllSuperTypes(); + final String entityId = request.getEntityId(); + final String classification = request.getClassification() != null ? request.getClassification().getTypeName() : null; + final String ownerUser = request.getEntity() != null ? (String) request.getEntity().getAttribute(RESOURCE_ENTITY_OWNER) : null; + + rangerResource.setValue(RESOURCE_ENTITY_TYPE, entityTypes); + rangerResource.setValue(RESOURCE_ENTITY_ID, entityId); + rangerResource.setOwnerUser(ownerUser); + rangerRequest.setAccessType(action); + rangerRequest.setAction(action); + rangerRequest.setUser(request.getUser()); + rangerRequest.setUserGroups(request.getUserGroups()); + rangerRequest.setClientIPAddress(request.getClientIPAddress()); + rangerRequest.setAccessTime(request.getAccessTime()); + rangerRequest.setResource(rangerResource); + rangerRequest.setForwardedAddresses(request.getForwardedAddresses()); + rangerRequest.setRemoteIPAddress(request.getRemoteIPAddress()); + + if (AtlasPrivilege.ENTITY_ADD_LABEL.equals(request.getAction()) || AtlasPrivilege.ENTITY_REMOVE_LABEL.equals(request.getAction())) { + rangerResource.setValue(RESOURCE_ENTITY_LABEL, request.getLabel()); + } else if (AtlasPrivilege.ENTITY_UPDATE_BUSINESS_METADATA.equals(request.getAction())) { + rangerResource.setValue(RESOURCE_ENTITY_BUSINESS_METADATA, request.getBusinessMetadata()); + } else if (StringUtils.isNotEmpty(classification) && CLASSIFICATION_PRIVILEGES.contains(request.getAction())) { + rangerResource.setValue(RESOURCE_CLASSIFICATION, request.getClassificationTypeAndAllSuperTypes(classification)); + } + } + + static void collectAccessors(RangerAccessResult result, AtlasAccessorResponse response) { + if (result != null && CollectionUtils.isNotEmpty(result.getMatchedItemEvaluators())) { + + result.getMatchedItemEvaluators().forEach(x -> { + collectSubjects(response, x); + }); + } + } + + static private void collectSubjects(AtlasAccessorResponse response, RangerPolicyItemEvaluator evaluator) { + + RangerPolicy.RangerPolicyItem policyItem = evaluator.getPolicyItem(); + + if (evaluator.getPolicyItemType() == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_ALLOW) { + response.getUsers().addAll(policyItem.getUsers()); + response.getRoles().addAll(policyItem.getRoles()); + response.getGroups().addAll(policyItem.getGroups()); + + } else if (evaluator.getPolicyItemType() == RangerPolicyItemEvaluator.POLICY_ITEM_TYPE_DENY) { + response.getDenyUsers().addAll(policyItem.getUsers()); + response.getDenyRoles().addAll(policyItem.getRoles()); + response.getDenyGroups().addAll(policyItem.getGroups()); + } + } + + static void collectAccessors(RangerAccessResult resultEnd1, RangerAccessResult resultEnd2, AtlasAccessorResponse accessorResponse) { + + if (resultEnd2 == null || CollectionUtils.isEmpty(resultEnd2.getMatchedItemEvaluators())) { + return; + } + + final AtlasAccessorResponse accessorsEnd1 = new AtlasAccessorResponse(); + final AtlasAccessorResponse accessorsEnd2 = new AtlasAccessorResponse(); + + // Collect lists of accessors for both results + resultEnd1.getMatchedItemEvaluators().forEach(x -> { + collectSubjects(accessorsEnd1, x); + }); + + resultEnd2.getMatchedItemEvaluators().forEach(x -> { + collectSubjects(accessorsEnd2, x); + }); + + // Retain only common accessors + accessorsEnd1.getUsers().retainAll(accessorsEnd2.getUsers()); + accessorsEnd1.getRoles().retainAll(accessorsEnd2.getRoles()); + accessorsEnd1.getGroups().retainAll(accessorsEnd2.getGroups()); + + accessorsEnd1.getDenyUsers().addAll(accessorsEnd2.getDenyUsers()); + accessorsEnd1.getDenyRoles().addAll(accessorsEnd2.getDenyRoles()); + accessorsEnd1.getDenyGroups().addAll(accessorsEnd2.getDenyGroups()); + + // add accessors to the response + accessorResponse.getUsers().addAll(accessorsEnd1.getUsers()); + accessorResponse.getRoles().addAll(accessorsEnd1.getRoles()); + accessorResponse.getGroups().addAll(accessorsEnd1.getGroups()); + + accessorResponse.getDenyUsers().addAll(accessorsEnd1.getDenyUsers()); + accessorResponse.getDenyRoles().addAll(accessorsEnd1.getDenyRoles()); + accessorResponse.getDenyGroups().addAll(accessorsEnd1.getDenyGroups()); + } + + static boolean hasAccessors(RangerAccessResult result) { + if (result == null) { + return false; + } + + for (RangerPolicyItemEvaluator itemEvaluator : result.getMatchedItemEvaluators()) { + RangerPolicy.RangerPolicyItem item = itemEvaluator.getPolicyItem(); + if (CollectionUtils.isNotEmpty(item.getUsers()) || CollectionUtils.isNotEmpty(item.getRoles()) && CollectionUtils.isNotEmpty(item.getGroups())) { + return true; + } + } + return false; + } +} diff --git a/auth-plugin-atlas/src/main/java/org/apache/atlas/authorization/atlas/authorizer/RangerGroupUtil.java b/auth-plugin-atlas/src/main/java/org/apache/atlas/authorization/atlas/authorizer/RangerGroupUtil.java new file mode 100644 index 00000000000..811bce4bbc0 --- /dev/null +++ b/auth-plugin-atlas/src/main/java/org/apache/atlas/authorization/atlas/authorizer/RangerGroupUtil.java @@ -0,0 +1,62 @@ +package org.apache.atlas.authorization.atlas.authorizer; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import org.apache.atlas.plugin.util.RangerUserStore; + +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +public class RangerGroupUtil { + private long UserStoreVersion; + private Map> userGroupMapping; + + public enum GROUP_FOR {USER} + + public RangerGroupUtil(RangerUserStore userStore) { + if (userStore != null) { + UserStoreVersion = userStore.getUserStoreVersion(); + userGroupMapping = userStore.getUserGroupMapping(); + } else { + UserStoreVersion = -1L; + } + } + + public void setUserStore(RangerUserStore userStore) { + this.userGroupMapping = userStore.getUserGroupMapping(); + this.UserStoreVersion = userStore.getUserStoreVersion(); + } + + public long getUserStoreVersion() { return UserStoreVersion; } + + public Set getContainedGroups(String userName) { + Set data = new LinkedHashSet(); + Set tmpData = new LinkedHashSet(); + tmpData = userGroupMapping.get(userName); + if (tmpData != null){ + data = tmpData; + } + return data; + } + +} + + diff --git a/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceEntityResponse.java b/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceEntityResponse.java new file mode 100644 index 00000000000..46a80e1675b --- /dev/null +++ b/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceEntityResponse.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.services.atlas.json.model; + +public class ResourceEntityResponse { + + private String href; + private String name; + private String id; + private String type; + + public String getHref() { + return href; + } + + public void setHref(String href) { + this.href = href; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + +} diff --git a/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceOperationResponse.java b/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceOperationResponse.java new file mode 100644 index 00000000000..e63a033f81c --- /dev/null +++ b/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceOperationResponse.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.services.atlas.json.model; + +import java.util.List; + +public class ResourceOperationResponse { + private String requestId; + private String query; + private String queryType; + private List results; + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public String getQuery() { + return query; + } + + public void setQuery(String query) { + this.query = query; + } + + public String getQueryType() { + return queryType; + } + + public void setQueryType(String queryType) { + this.queryType = queryType; + } + + public List getResults() { + return results; + } + + public void setResults(List results) { + this.results = results; + } + + public class Results { + + private String result; + private String count; + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + + public String getCount() { + return count; + } + + public void setCount(String count) { + this.count = count; + } + } + +} diff --git a/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceTaxonomyResponse.java b/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceTaxonomyResponse.java new file mode 100644 index 00000000000..dad84b21846 --- /dev/null +++ b/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceTaxonomyResponse.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.services.atlas.json.model; + +public class ResourceTaxonomyResponse { + private String href; + private String name; + private String description; + + public String getHref() { + return href; + } + + public void setHref(String href) { + this.href = href; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceTermResponse.java b/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceTermResponse.java new file mode 100644 index 00000000000..c625a93cd1d --- /dev/null +++ b/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceTermResponse.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.services.atlas.json.model; + +public class ResourceTermResponse { + + private String href; + private String name; + private String description; + + public String getHref() { + return href; + } + + public void setHref(String href) { + this.href = href; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceTypeResponse.java b/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceTypeResponse.java new file mode 100644 index 00000000000..bf6b3fc7580 --- /dev/null +++ b/auth-plugin-atlas/src/main/java/org/apache/atlas/services/atlas/json/model/ResourceTypeResponse.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.services.atlas.json.model; + +import java.util.List; + +public class ResourceTypeResponse { + + private List results; + private String count; + private String requestId; + + public String getCount() { + return count; + } + + public void setCount(String count) { + this.count = count; + } + + public String getRequestId() { + return requestId; + } + + public void setRequestId(String requestId) { + this.requestId = requestId; + } + + public List getResults() { + return results; + } + + public void setResults(List results) { + this.results = results; + } + +} diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessRequest.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessRequest.java index c76a8715b76..f133e1268f3 100644 --- a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessRequest.java +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessRequest.java @@ -176,16 +176,16 @@ public String getEntityId(AtlasEntityHeader entity, AtlasTypeRegistry typeRegist return ret == null ? "" : ret.toString(); } - public Set getClassificationNames(AtlasEntityHeader entity) { - final Set ret; + public Set getClassificationNames(AtlasEntityHeader entity) { + final Set ret; if (entity == null || entity.getClassifications() == null) { ret = Collections.emptySet(); } else { ret = new HashSet<>(); - for (AtlasClassification classify : entity.getClassifications()) { - ret.add(classify.getTypeName()); + for (AtlasClassification classification : entity.getClassifications()) { + ret.add(classification); } } diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessResult.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessResult.java new file mode 100644 index 00000000000..954ed1a6dd9 --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessResult.java @@ -0,0 +1,79 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.authorize; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class AtlasAccessResult { + private static Logger LOG = LoggerFactory.getLogger(AtlasAccessResult.class); + + private boolean isAllowed = false; + private String policyId = "-1"; + private int policyPriority = -1; + private boolean explicitDeny = false; + + public AtlasAccessResult() { + + } + + public AtlasAccessResult(boolean isAllowed) { + this.isAllowed = isAllowed; + } + + public AtlasAccessResult(boolean isAllowed, String policyId) { + this(isAllowed); + this.policyId = policyId; + + this.explicitDeny = !isAllowed && !"-1".equals(policyId); + } + + public AtlasAccessResult(boolean isAllowed, String policyId, int policyPriority) { + this(isAllowed, policyId); + this.policyPriority = policyPriority; + } + + public boolean isExplicitDeny() { + return explicitDeny; + } + + public boolean isAllowed() { + return isAllowed; + } + + public int getPolicyPriority() { + return policyPriority; + } + + public void setAllowed(boolean allowed) { + isAllowed = allowed; + } + + public String getPolicyId() { + return policyId; + } + + public void setPolicyId(String policyId) { + this.policyId = policyId; + } + + public void setPolicyPriority(int policyPriority) { + this.policyPriority = policyPriority; + } +} diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessorRequest.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessorRequest.java new file mode 100644 index 00000000000..b3d25fa4df6 --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessorRequest.java @@ -0,0 +1,163 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.authorize; + + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.apache.atlas.model.instance.AtlasEntityHeader; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlRootElement; + +import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; +import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.PUBLIC_ONLY; + +@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE) +@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) +@JsonIgnoreProperties(ignoreUnknown=true) +@XmlRootElement +@XmlAccessorType(XmlAccessType.PROPERTY) +public class AtlasAccessorRequest { + + private String action; + + private String guid; + private String typeName; + private String qualifiedName; + private String label; + private String classification; + private String businessMetadata; + + private String relationshipTypeName; + private String entityQualifiedNameEnd1; + private String entityQualifiedNameEnd2; + private String entityGuidEnd1; + private String entityGuidEnd2; + private String entityTypeEnd1; + private String entityTypeEnd2; + + private AtlasEntityHeader entity = null; + + public String getGuid() { + return guid; + } + + public void setGuid(String guid) { + this.guid = guid; + } + + public String getTypeName() { + return typeName; + } + + public void setTypeName(String typeName) { + this.typeName = typeName; + } + + public String getQualifiedName() { + return qualifiedName; + } + + public void setQualifiedName(String qualifiedName) { + this.qualifiedName = qualifiedName; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + public String getClassification() { + return classification; + } + + public void setClassification(String classification) { + this.classification = classification; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public String getBusinessMetadata() { + return businessMetadata; + } + + public void setBusinessMetadata(String businessMetadata) { + this.businessMetadata = businessMetadata; + } + + public AtlasEntityHeader getEntity() { + return entity; + } + + public void setEntity(AtlasEntityHeader entity) { + this.entity = entity; + } + + public String getRelationshipTypeName() { + return relationshipTypeName; + } + + public String getEntityQualifiedNameEnd1() { + return entityQualifiedNameEnd1; + } + + public String getEntityQualifiedNameEnd2() { + return entityQualifiedNameEnd2; + } + + public String getEntityGuidEnd1() { + return entityGuidEnd1; + } + + public String getEntityGuidEnd2() { + return entityGuidEnd2; + } + + public String getEntityTypeEnd1() { + return entityTypeEnd1; + } + + public String getEntityTypeEnd2() { + return entityTypeEnd2; + } + + @Override + public String toString() { + return "AtlasAccessor{" + + "guid='" + guid + '\'' + + ", typeName='" + typeName + '\'' + + ", qualifiedName='" + qualifiedName + '\'' + + ", label='" + label + '\'' + + ", classification='" + classification + '\'' + + ", businessMetadata='" + businessMetadata + '\'' + + '}'; + } +} + diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessorResponse.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessorResponse.java new file mode 100644 index 00000000000..73e8023c090 --- /dev/null +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAccessorResponse.java @@ -0,0 +1,196 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.authorize; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.util.HashSet; +import java.util.Set; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class AtlasAccessorResponse { + + private String action; + + private String guid; + private String typeName; + private String qualifiedName; + private String label; + private String classification; + private String businessMetadata; + + private String relationshipTypeName; + private String entityGuidEnd1; + private String entityQualifiedNameEnd1; + private String entityTypeEnd1; + private String entityGuidEnd2; + private String entityQualifiedNameEnd2; + private String entityTypeEnd2; + + private Set users = new HashSet<>(); + private Set groups = new HashSet<>(); + private Set roles = new HashSet<>(); + + private Set denyUsers = new HashSet<>(); + private Set denyGroups = new HashSet<>(); + private Set denyRoles = new HashSet<>(); + + public AtlasAccessorResponse() { + + } + + public void populateRequestDetails(AtlasAccessorRequest accessorRequest) { + this.action = accessorRequest.getAction(); + this.guid = accessorRequest.getGuid(); + this.typeName = accessorRequest.getTypeName(); + this.qualifiedName = accessorRequest.getQualifiedName(); + this.label = accessorRequest.getLabel(); + this.classification = accessorRequest.getClassification(); + this.businessMetadata = accessorRequest.getBusinessMetadata(); + + this.relationshipTypeName = accessorRequest.getRelationshipTypeName(); + this.entityGuidEnd1 = accessorRequest.getEntityGuidEnd1(); + this.entityQualifiedNameEnd1 = accessorRequest.getEntityQualifiedNameEnd1(); + this.entityTypeEnd1 = accessorRequest.getEntityTypeEnd1(); + this.entityGuidEnd2 = accessorRequest.getEntityGuidEnd2(); + this.entityQualifiedNameEnd2 = accessorRequest.getEntityQualifiedNameEnd2(); + this.entityTypeEnd2 = accessorRequest.getEntityTypeEnd2(); + } + + public String getAction() { + return action; + } + + public String getGuid() { + return guid; + } + + public String getTypeName() { + return typeName; + } + + public String getQualifiedName() { + return qualifiedName; + } + + public String getLabel() { + return label; + } + + public String getClassification() { + return classification; + } + + public String getBusinessMetadata() { + return businessMetadata; + } + + public String getRelationshipTypeName() { + return relationshipTypeName; + } + + public String getEntityGuidEnd1() { + return entityGuidEnd1; + } + + public String getEntityQualifiedNameEnd1() { + return entityQualifiedNameEnd1; + } + + public String getEntityTypeEnd1() { + return entityTypeEnd1; + } + + public String getEntityGuidEnd2() { + return entityGuidEnd2; + } + + public String getEntityQualifiedNameEnd2() { + return entityQualifiedNameEnd2; + } + + public String getEntityTypeEnd2() { + return entityTypeEnd2; + } + + public Set getUsers() { + return users; + } + + public void setUsers(Set users) { + this.users = users; + } + + public Set getGroups() { + return groups; + } + + public void setGroups(Set groups) { + this.groups = groups; + } + + public Set getRoles() { + return roles; + } + + public void setRoles(Set roles) { + this.roles = roles; + } + + public Set getDenyUsers() { + return denyUsers; + } + + public void setDenyUsers(Set denyUsers) { + this.denyUsers = denyUsers; + } + + public Set getDenyGroups() { + return denyGroups; + } + + public void setDenyGroups(Set denyGroups) { + this.denyGroups = denyGroups; + } + + public Set getDenyRoles() { + return denyRoles; + } + + public void setDenyRoles(Set denyRoles) { + this.denyRoles = denyRoles; + } + + @Override + public String toString() { + return "AtlasAccessorResponse{" + + "guid='" + guid + '\'' + + ", typeName='" + typeName + '\'' + + ", qualifiedName='" + qualifiedName + '\'' + + ", label='" + label + '\'' + + ", classification='" + classification + '\'' + + ", businessMetadata='" + businessMetadata + '\'' + + ", users=" + users + + ", groups=" + groups + + ", roles=" + roles + + ", denyUsers=" + denyUsers + + ", denyGroups=" + denyGroups + + ", denyRoles=" + denyRoles + + '}'; + } +} diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizationUtils.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizationUtils.java deleted file mode 100644 index b1a3eb5fb26..00000000000 --- a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizationUtils.java +++ /dev/null @@ -1,269 +0,0 @@ -/** -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas.authorize; - -import org.apache.atlas.AtlasErrorCode; -import org.apache.atlas.RequestContext; -import org.apache.atlas.exception.AtlasBaseException; -import org.apache.atlas.utils.AtlasPerfMetrics.MetricRecorder; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.context.SecurityContextHolder; - -import javax.servlet.http.HttpServletRequest; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.HashSet; -import java.util.Set; -import java.util.List; -import java.util.Arrays; - -public class AtlasAuthorizationUtils { - private static final Logger LOG = LoggerFactory.getLogger(AtlasAuthorizationUtils.class); - - public static void verifyAccess(AtlasAdminAccessRequest request, Object... errorMsgParams) throws AtlasBaseException { - if (! isAccessAllowed(request)) { - String message = (errorMsgParams != null && errorMsgParams.length > 0) ? StringUtils.join(errorMsgParams) : ""; - - throw new AtlasBaseException(AtlasErrorCode.UNAUTHORIZED_ACCESS, request.getUser(), message); - } - } - - public static void verifyAccess(AtlasTypeAccessRequest request, Object... errorMsgParams) throws AtlasBaseException { - if (! isAccessAllowed(request)) { - String message = (errorMsgParams != null && errorMsgParams.length > 0) ? StringUtils.join(errorMsgParams) : ""; - - throw new AtlasBaseException(AtlasErrorCode.UNAUTHORIZED_ACCESS, request.getUser(), message); - } - } - - public static void verifyAccess(AtlasEntityAccessRequest request, Object... errorMsgParams) throws AtlasBaseException { - if (! isAccessAllowed(request)) { - String message = (errorMsgParams != null && errorMsgParams.length > 0) ? StringUtils.join(errorMsgParams) : ""; - - throw new AtlasBaseException(AtlasErrorCode.UNAUTHORIZED_ACCESS, request.getUser(), message); - } - } - - public static void verifyAccess(AtlasRelationshipAccessRequest request, Object... errorMsgParams) throws AtlasBaseException { - if (!isAccessAllowed(request)) { - String message = (errorMsgParams != null && errorMsgParams.length > 0) ? StringUtils.join(errorMsgParams) : ""; - throw new AtlasBaseException(AtlasErrorCode.UNAUTHORIZED_ACCESS, request.getUser(), message); - } - } - - public static void scrubSearchResults(AtlasSearchResultScrubRequest request) throws AtlasBaseException { - String userName = getCurrentUserName(); - - if (StringUtils.isNotEmpty(userName)) { - try { - AtlasAuthorizer authorizer = AtlasAuthorizerFactory.getAtlasAuthorizer(); - - request.setUser(userName, getCurrentUserGroups()); - request.setClientIPAddress(RequestContext.get().getClientIPAddress()); - request.setForwardedAddresses(RequestContext.get().getForwardedAddresses()); - request.setRemoteIPAddress(RequestContext.get().getClientIPAddress()); - - authorizer.scrubSearchResults(request); - } catch (AtlasAuthorizationException e) { - LOG.error("Unable to obtain AtlasAuthorizer", e); - } - } - } - - public static boolean isAccessAllowed(AtlasAdminAccessRequest request) { - MetricRecorder metric = RequestContext.get().startMetricRecord("isAccessAllowed"); - - boolean ret = false; - String userName = getCurrentUserName(); - - if (StringUtils.isNotEmpty(userName)) { - try { - AtlasAuthorizer authorizer = AtlasAuthorizerFactory.getAtlasAuthorizer(); - - request.setUser(userName, getCurrentUserGroups()); - request.setClientIPAddress(RequestContext.get().getClientIPAddress()); - request.setForwardedAddresses(RequestContext.get().getForwardedAddresses()); - request.setRemoteIPAddress(RequestContext.get().getClientIPAddress()); - ret = authorizer.isAccessAllowed(request); - } catch (AtlasAuthorizationException e) { - LOG.error("Unable to obtain AtlasAuthorizer", e); - } - } else { - ret = true; - } - - RequestContext.get().endMetricRecord(metric); - - return ret; - } - - public static boolean isAccessAllowed(AtlasEntityAccessRequest request) { - MetricRecorder metric = RequestContext.get().startMetricRecord("isAccessAllowed"); - - boolean ret = false; - String userName = getCurrentUserName(); - - if (StringUtils.isNotEmpty(userName) && !RequestContext.get().isImportInProgress()) { - try { - AtlasAuthorizer authorizer = AtlasAuthorizerFactory.getAtlasAuthorizer(); - - request.setUser(getCurrentUserName(), getCurrentUserGroups()); - request.setClientIPAddress(RequestContext.get().getClientIPAddress()); - request.setForwardedAddresses(RequestContext.get().getForwardedAddresses()); - request.setRemoteIPAddress(RequestContext.get().getClientIPAddress()); - ret = authorizer.isAccessAllowed(request); - } catch (AtlasAuthorizationException e) { - LOG.error("Unable to obtain AtlasAuthorizer", e); - } - } else { - ret = true; - } - - RequestContext.get().endMetricRecord(metric); - - return ret; - } - - public static boolean isAccessAllowed(AtlasTypeAccessRequest request) { - MetricRecorder metric = RequestContext.get().startMetricRecord("isAccessAllowed"); - - boolean ret = false; - String userName = getCurrentUserName(); - - if (StringUtils.isNotEmpty(userName) && !RequestContext.get().isImportInProgress()) { - try { - AtlasAuthorizer authorizer = AtlasAuthorizerFactory.getAtlasAuthorizer(); - - request.setUser(getCurrentUserName(), getCurrentUserGroups()); - request.setClientIPAddress(RequestContext.get().getClientIPAddress()); - request.setForwardedAddresses(RequestContext.get().getForwardedAddresses()); - request.setRemoteIPAddress(RequestContext.get().getClientIPAddress()); - ret = authorizer.isAccessAllowed(request); - } catch (AtlasAuthorizationException e) { - LOG.error("Unable to obtain AtlasAuthorizer", e); - } - } else { - ret = true; - } - - RequestContext.get().endMetricRecord(metric); - - return ret; - } - - public static boolean isAccessAllowed(AtlasRelationshipAccessRequest request) { - MetricRecorder metric = RequestContext.get().startMetricRecord("isAccessAllowed"); - - boolean ret = false; - String userName = getCurrentUserName(); - - if (StringUtils.isNotEmpty(userName) && !RequestContext.get().isImportInProgress()) { - try { - AtlasAuthorizer authorizer = AtlasAuthorizerFactory.getAtlasAuthorizer(); - - request.setUser(getCurrentUserName(), getCurrentUserGroups()); - request.setClientIPAddress(RequestContext.get().getClientIPAddress()); - request.setForwardedAddresses(RequestContext.get().getForwardedAddresses()); - request.setRemoteIPAddress(RequestContext.get().getClientIPAddress()); - ret = authorizer.isAccessAllowed(request); - } catch (AtlasAuthorizationException e) { - LOG.error("Unable to obtain AtlasAuthorizer", e); - } - } else { - ret = true; - } - - RequestContext.get().endMetricRecord(metric); - - return ret; - } - - public static void filterTypesDef(AtlasTypesDefFilterRequest request) { - MetricRecorder metric = RequestContext.get().startMetricRecord("filterTypesDef"); - String userName = getCurrentUserName(); - - if (StringUtils.isNotEmpty(userName) && !RequestContext.get().isImportInProgress()) { - try { - AtlasAuthorizer authorizer = AtlasAuthorizerFactory.getAtlasAuthorizer(); - - request.setUser(getCurrentUserName(), getCurrentUserGroups()); - request.setClientIPAddress(RequestContext.get().getClientIPAddress()); - request.setForwardedAddresses(RequestContext.get().getForwardedAddresses()); - request.setRemoteIPAddress(RequestContext.get().getClientIPAddress()); - - authorizer.filterTypesDef(request); - } catch (AtlasAuthorizationException e) { - LOG.error("Unable to obtain AtlasAuthorizer", e); - } - } - - RequestContext.get().endMetricRecord(metric); - } - - public static List getForwardedAddressesFromRequest(HttpServletRequest httpServletRequest){ - String ipAddress = httpServletRequest.getHeader("X-FORWARDED-FOR"); - String[] forwardedAddresses = null ; - - if(!StringUtils.isEmpty(ipAddress)){ - forwardedAddresses = ipAddress.split(","); - } - return forwardedAddresses != null ? Arrays.asList(forwardedAddresses) : null; - } - - public static String getRequestIpAddress(HttpServletRequest httpServletRequest) { - String ret = ""; - - try { - InetAddress inetAddr = InetAddress.getByName(httpServletRequest.getRemoteAddr()); - - ret = inetAddr.getHostAddress(); - } catch (UnknownHostException ex) { - LOG.error("Failed to retrieve client IP address", ex); - } - - return ret; - } - - - - public static String getCurrentUserName() { - Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - - return auth != null ? auth.getName() : ""; - } - - public static Set getCurrentUserGroups() { - Set ret = new HashSet<>(); - - Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - - if (auth != null) { - for (GrantedAuthority c : auth.getAuthorities()) { - ret.add(c.getAuthority()); - } - } - - return ret; - } -} diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizer.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizer.java index 21b8cf905d2..47f98ea6c3c 100644 --- a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizer.java +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizer.java @@ -20,6 +20,11 @@ import org.apache.atlas.model.instance.AtlasEntityHeader; +import org.apache.atlas.type.AtlasEntityType; +import org.apache.atlas.type.AtlasStructType; +import org.apache.atlas.type.AtlasTypeRegistry; + +import java.util.Set; public interface AtlasAuthorizer { /** @@ -38,7 +43,7 @@ public interface AtlasAuthorizer { * @return * @throws AtlasAuthorizationException */ - boolean isAccessAllowed(AtlasAdminAccessRequest request) throws AtlasAuthorizationException; + AtlasAccessResult isAccessAllowed(AtlasAdminAccessRequest request) throws AtlasAuthorizationException; /** * authorize operations on an entity @@ -46,7 +51,11 @@ public interface AtlasAuthorizer { * @return * @throws AtlasAuthorizationException */ - boolean isAccessAllowed(AtlasEntityAccessRequest request) throws AtlasAuthorizationException; + default AtlasAccessResult isAccessAllowed(AtlasEntityAccessRequest request) throws AtlasAuthorizationException { + return isAccessAllowed(request, true); + } + + AtlasAccessResult isAccessAllowed(AtlasEntityAccessRequest request, boolean auditLogEnabled) throws AtlasAuthorizationException; /** * authorize operations on a type @@ -54,7 +63,15 @@ public interface AtlasAuthorizer { * @return * @throws AtlasAuthorizationException */ - boolean isAccessAllowed(AtlasTypeAccessRequest request) throws AtlasAuthorizationException; + AtlasAccessResult isAccessAllowed(AtlasTypeAccessRequest request) throws AtlasAuthorizationException; + + AtlasAccessorResponse getAccessors(AtlasEntityAccessRequest request); + + AtlasAccessorResponse getAccessors(AtlasRelationshipAccessRequest request); + + AtlasAccessorResponse getAccessors(AtlasTypeAccessRequest request); + + Set getRolesForCurrentUser(String userName, Set groups); /** * authorize relationship type @@ -63,8 +80,9 @@ public interface AtlasAuthorizer { * @throws AtlasAuthorizationException */ default - boolean isAccessAllowed(AtlasRelationshipAccessRequest request) throws AtlasAuthorizationException { - return true; + AtlasAccessResult isAccessAllowed(AtlasRelationshipAccessRequest request) throws AtlasAuthorizationException { + AtlasAccessResult result = new AtlasAccessResult(true); + return result; } /** @@ -77,6 +95,16 @@ boolean isAccessAllowed(AtlasRelationshipAccessRequest request) throws AtlasAuth void scrubSearchResults(AtlasSearchResultScrubRequest request) throws AtlasAuthorizationException { } + /** + * scrub search-results to handle entities for which the user doesn't have access + * @param request + * @return + * @throws AtlasAuthorizationException + */ + default + void scrubSearchResults(AtlasSearchResultScrubRequest request, boolean isScrubAuditEnabled) throws AtlasAuthorizationException { + } + default void scrubEntityHeader(AtlasEntityHeader entity) { entity.setGuid("-1"); @@ -102,7 +130,33 @@ void scrubEntityHeader(AtlasEntityHeader entity) { } } + default void scrubEntityHeader(AtlasEntityHeader entity, AtlasTypeRegistry typeRegistry) { + + AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entity.getTypeName()); + boolean isScrubbed = false; + + if (entityType != null) { + if (entity.getAttributes() != null) { + for (AtlasStructType.AtlasAttribute attribute : entityType.getAllAttributes().values()) { + if (!attribute.getAttributeDef().getSkipScrubbing()) { + entity.getAttributes().remove(attribute.getAttributeDef().getName()); + isScrubbed = true; + } + } + } + } + + entity.setScrubbed(isScrubbed); + + } + + default void filterTypesDef(AtlasTypesDefFilterRequest request) throws AtlasAuthorizationException { } + + default + public void init(AtlasTypeRegistry typeRegistry) { + + } } diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizerFactory.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizerFactory.java index 72037eabbe0..0678dfd4086 100644 --- a/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizerFactory.java +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasAuthorizerFactory.java @@ -21,6 +21,7 @@ import org.apache.atlas.ApplicationProperties; import org.apache.atlas.AtlasException; import org.apache.atlas.authorize.simple.AtlasSimpleAuthorizer; +import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.commons.configuration.Configuration; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; @@ -33,10 +34,14 @@ public class AtlasAuthorizerFactory { private static final String NONE_AUTHORIZER = AtlasNoneAuthorizer.class.getName(); private static final String SIMPLE_AUTHORIZER = AtlasSimpleAuthorizer.class.getName(); private static final String RANGER_AUTHORIZER = "org.apache.ranger.authorization.atlas.authorizer.RangerAtlasAuthorizer"; + private static final String ATLAS_AUTHORIZER = "org.apache.atlas.authorization.atlas.authorizer.RangerAtlasAuthorizer"; private static volatile AtlasAuthorizer INSTANCE = null; - public static AtlasAuthorizer getAtlasAuthorizer() throws AtlasAuthorizationException { + public static String CURRENT_AUTHORIZER_IMPL; + public static final String ATLAS_AUTHORIZER_IMPL = "atlas"; + + public static AtlasAuthorizer getAtlasAuthorizer(AtlasTypeRegistry typeRegistry) throws AtlasAuthorizationException { AtlasAuthorizer ret = INSTANCE; if (ret == null) { @@ -50,14 +55,17 @@ public static AtlasAuthorizer getAtlasAuthorizer() throws AtlasAuthorizationExce LOG.error("Exception while fetching configuration", e); } - String authorizerClass = configuration != null ? configuration.getString("atlas.authorizer.impl") : "SIMPLE"; + CURRENT_AUTHORIZER_IMPL = configuration != null ? configuration.getString("atlas.authorizer.impl") : "SIMPLE"; + String authorizerClass = RANGER_AUTHORIZER; - if (StringUtils.isNotEmpty(authorizerClass)) { - if (StringUtils.equalsIgnoreCase(authorizerClass, "SIMPLE")) { + if (StringUtils.isNotEmpty(CURRENT_AUTHORIZER_IMPL)) { + if (StringUtils.equalsIgnoreCase(CURRENT_AUTHORIZER_IMPL, "SIMPLE")) { authorizerClass = SIMPLE_AUTHORIZER; - } else if (StringUtils.equalsIgnoreCase(authorizerClass, "RANGER")) { + } else if (StringUtils.equalsIgnoreCase(CURRENT_AUTHORIZER_IMPL, "RANGER")) { authorizerClass = RANGER_AUTHORIZER; - } else if (StringUtils.equalsIgnoreCase(authorizerClass, "NONE")) { + } else if (StringUtils.equalsIgnoreCase(CURRENT_AUTHORIZER_IMPL, ATLAS_AUTHORIZER_IMPL)) { + authorizerClass = ATLAS_AUTHORIZER; + } else if (StringUtils.equalsIgnoreCase(CURRENT_AUTHORIZER_IMPL, "NONE")) { authorizerClass = NONE_AUTHORIZER; } } else { @@ -72,7 +80,11 @@ public static AtlasAuthorizer getAtlasAuthorizer() throws AtlasAuthorizationExce if (authorizerMetaObject != null) { INSTANCE = (AtlasAuthorizer) authorizerMetaObject.newInstance(); - INSTANCE.init(); + if (StringUtils.equalsIgnoreCase(CURRENT_AUTHORIZER_IMPL, ATLAS_AUTHORIZER_IMPL)) { + INSTANCE.init(typeRegistry); + } else { + INSTANCE.init(); + } } } catch (Exception e) { LOG.error("Error while creating authorizer of type {}", authorizerClass, e); @@ -87,4 +99,8 @@ public static AtlasAuthorizer getAtlasAuthorizer() throws AtlasAuthorizationExce return ret; } + + public static AtlasAuthorizer getAtlasAuthorizer() throws AtlasAuthorizationException { + return INSTANCE; + } } diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasEntityAccessRequest.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasEntityAccessRequest.java index 6d49d54b11a..df164864e74 100644 --- a/authorization/src/main/java/org/apache/atlas/authorize/AtlasEntityAccessRequest.java +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasEntityAccessRequest.java @@ -32,42 +32,47 @@ public class AtlasEntityAccessRequest extends AtlasAccessRequest { private final String businessMetadata; private final String attributeName; private final AtlasTypeRegistry typeRegistry; - private final Set entityClassifications; + private final Set entityClassifications; + private final boolean auditEnabled; public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, AtlasPrivilege action) { - this(typeRegistry, action, null, null, null, null, null, null, null); + this(typeRegistry, action, null, null, null, null, null, null, null, true); } public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, AtlasPrivilege action, AtlasEntityHeader entity) { - this(typeRegistry, action, entity, null, null, null, null, null, null); + this(typeRegistry, action, entity, null, null, null, null, null, null, true); + } + + public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, AtlasPrivilege action, AtlasEntityHeader entity, boolean auditEnabled) { + this(typeRegistry, action, entity, null, null, null, null, null, null, auditEnabled); } public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, AtlasPrivilege action, AtlasEntityHeader entity, AtlasClassification classification) { - this(typeRegistry, action, entity, classification, null, null, null, null, null); + this(typeRegistry, action, entity, classification, null, null, null, null, null, true); } public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, AtlasPrivilege action, AtlasEntityHeader entity, String attributeName) { - this(typeRegistry, action, entity, null, attributeName, null, null, null, null); + this(typeRegistry, action, entity, null, attributeName, null, null, null, null, true); } public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, AtlasPrivilege action, AtlasEntityHeader entity, String userName, Set userGroups) { - this(typeRegistry, action, entity, null, null, null, null, userName, userGroups); + this(typeRegistry, action, entity, null, null, null, null, userName, userGroups, true); } public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, AtlasPrivilege action, AtlasEntityHeader entity, AtlasClassification classification, String userName, Set userGroups) { - this(typeRegistry, action, entity, classification, null, null, null, userName, userGroups); + this(typeRegistry, action, entity, classification, null, null, null, userName, userGroups, true); } public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, AtlasPrivilege action, AtlasEntityHeader entity, String attributeName, String userName, Set userGroups) { - this(typeRegistry, action, entity, null, attributeName, null, null, userName, userGroups); + this(typeRegistry, action, entity, null, attributeName, null, null, userName, userGroups, true); } public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, AtlasPrivilege action, AtlasEntityHeader entity, AtlasClassification classification, String attributeName, String userName, Set userGroups) { - this(typeRegistry, action, entity, classification, attributeName, null, null, userName, userGroups); + this(typeRegistry, action, entity, classification, attributeName, null, null, userName, userGroups, true); } - public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, AtlasPrivilege action, AtlasEntityHeader entity, AtlasClassification classification, String attributeName, String label, String businessMetadata, String userName, Set userGroups) { + public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, AtlasPrivilege action, AtlasEntityHeader entity, AtlasClassification classification, String attributeName, String label, String businessMetadata, String userName, Set userGroups, boolean auditEnabled) { super(action, userName, userGroups); this.entity = entity; @@ -78,12 +83,15 @@ public AtlasEntityAccessRequest(AtlasTypeRegistry typeRegistry, AtlasPrivilege a this.attributeName = attributeName; this.typeRegistry = typeRegistry; this.entityClassifications = super.getClassificationNames(entity); + this.auditEnabled = auditEnabled; } public AtlasEntityHeader getEntity() { return entity; } + public boolean isAuditEnabled() {return auditEnabled;} + public String getEntityId() { return entityId; } @@ -108,7 +116,7 @@ public String getEntityType() { return entity == null ? StringUtils.EMPTY : entity.getTypeName(); } - public Set getEntityClassifications() { + public Set getEntityClassifications() { return entityClassifications; } @@ -122,7 +130,7 @@ public Set getClassificationTypeAndAllSuperTypes(String classificationNa @Override public String toString() { - return "AtlasEntityAccessRequest[entity=" + entity + ", classification=" + classification + ", label=" + label + ", businessMetadata=" + businessMetadata + ", attributeName=" + attributeName + + return "AtlasEntityAccessRequest[auditEnabled=" + auditEnabled + ", entity=" + entity + ", classification=" + classification + ", label=" + label + ", businessMetadata=" + businessMetadata + ", attributeName=" + attributeName + ", action=" + getAction() + ", accessTime=" + getAccessTime() + ", user=" + getUser() + ", userGroups=" + getUserGroups() + ", clientIPAddress=" + getClientIPAddress() + ", forwardedAddresses=" + getForwardedAddresses() + ", remoteIPAddress=" + getRemoteIPAddress() + "]"; @@ -138,6 +146,7 @@ public static class AtlasEntityAccessRequestBuilder { private String label; private String businessMetadata; private String attributeName; + private boolean auditEnabled; public AtlasEntityAccessRequestBuilder(AtlasTypeRegistry typeRegistry, AtlasPrivilege action) { this.typeRegistry = typeRegistry; @@ -150,6 +159,13 @@ public AtlasEntityAccessRequestBuilder(AtlasTypeRegistry typeRegistry, AtlasPriv this.entity = entity; } + public AtlasEntityAccessRequestBuilder(AtlasTypeRegistry typeRegistry, AtlasPrivilege action, AtlasEntityHeader entity, boolean auditEnabled) { + this.typeRegistry = typeRegistry; + this.action = action; + this.entity = entity; + this.auditEnabled = auditEnabled; + } + public AtlasEntityAccessRequestBuilder setUserName(String userName) { this.userName = userName; @@ -193,9 +209,8 @@ public AtlasEntityAccessRequestBuilder setAttributeName(String attributeName) { } public AtlasEntityAccessRequest build() { - return new AtlasEntityAccessRequest(typeRegistry, action, entity, classification, attributeName, label, businessMetadata, userName, userGroups); + return new AtlasEntityAccessRequest(typeRegistry, action, entity, classification, attributeName, label, businessMetadata, userName, userGroups, auditEnabled); } } } - diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasNoneAuthorizer.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasNoneAuthorizer.java index a371049441b..810ec6bff5c 100644 --- a/authorization/src/main/java/org/apache/atlas/authorize/AtlasNoneAuthorizer.java +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasNoneAuthorizer.java @@ -21,6 +21,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Set; + public class AtlasNoneAuthorizer implements AtlasAuthorizer { private static final Logger LOG = LoggerFactory.getLogger(AtlasNoneAuthorizer.class); @@ -33,21 +35,45 @@ public void cleanUp() { LOG.info("AtlasNoneAuthorizer.cleanUp()"); } - public boolean isAccessAllowed(AtlasAdminAccessRequest request) throws AtlasAuthorizationException { - return true; + public AtlasAccessResult isAccessAllowed(AtlasAdminAccessRequest request) throws AtlasAuthorizationException { + AtlasAccessResult result = new AtlasAccessResult(true); + return result; + } + + public AtlasAccessResult isAccessAllowed(AtlasEntityAccessRequest request, boolean isAuditEnabled) throws AtlasAuthorizationException { + AtlasAccessResult result = new AtlasAccessResult(true); + return result; } - public boolean isAccessAllowed(AtlasEntityAccessRequest request) throws AtlasAuthorizationException { - return true; + public AtlasAccessResult isAccessAllowed(AtlasTypeAccessRequest request) throws AtlasAuthorizationException { + AtlasAccessResult result = new AtlasAccessResult(true); + return result; } - public boolean isAccessAllowed(AtlasTypeAccessRequest request) throws AtlasAuthorizationException { - return true; + @Override + public AtlasAccessorResponse getAccessors(AtlasEntityAccessRequest request) { + return null; + } + + @Override + public AtlasAccessorResponse getAccessors(AtlasRelationshipAccessRequest request) { + return null; + } + + @Override + public AtlasAccessorResponse getAccessors(AtlasTypeAccessRequest request) { + return null; + } + + @Override + public Set getRolesForCurrentUser(String userName, Set groups) { + return null; } @Override - public boolean isAccessAllowed(AtlasRelationshipAccessRequest request) throws AtlasAuthorizationException { - return true; + public AtlasAccessResult isAccessAllowed(AtlasRelationshipAccessRequest request) throws AtlasAuthorizationException { + AtlasAccessResult result = new AtlasAccessResult(true); + return result; } public void scrubSearchResults(AtlasSearchResultScrubRequest request) throws AtlasAuthorizationException { diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasPrivilege.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasPrivilege.java index 5d06e1b29dc..29d332cad1d 100644 --- a/authorization/src/main/java/org/apache/atlas/authorize/AtlasPrivilege.java +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasPrivilege.java @@ -46,8 +46,14 @@ public enum AtlasPrivilege { TYPE_READ("type-read"), - ADMIN_AUDITS("admin-audits"); + ADMIN_AUDITS("admin-audits"), + ADMIN_ENTITY_AUDITS("admin-entity-audits"), + ADMIN_REPAIR_INDEX("admin-repair-index"), + + ADMIN_TASK_CUD("admin-task-cud"), + + ADMIN_FEATURE_FLAG_CUD("admin-featureFlag-cud"); private final String type; AtlasPrivilege(String actionType){ diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasRelationshipAccessRequest.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasRelationshipAccessRequest.java index b530c01dd4b..bd1a0634c70 100644 --- a/authorization/src/main/java/org/apache/atlas/authorize/AtlasRelationshipAccessRequest.java +++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasRelationshipAccessRequest.java @@ -18,6 +18,7 @@ package org.apache.atlas.authorize; +import org.apache.atlas.model.instance.AtlasClassification; import org.apache.atlas.model.instance.AtlasEntityHeader; import org.apache.atlas.type.AtlasTypeRegistry; @@ -60,7 +61,7 @@ public Set getEnd1EntityTypeAndAllSuperTypes() { return super.getEntityTypeAndAllSuperTypes(end1Entity == null ? null : end1Entity.getTypeName(), typeRegistry); } - public Set getEnd1EntityClassifications() { + public Set getEnd1EntityClassifications() { return super.getClassificationNames(end1Entity); } @@ -72,7 +73,7 @@ public Set getEnd2EntityTypeAndAllSuperTypes() { return super.getEntityTypeAndAllSuperTypes(end2Entity == null ? null : end2Entity.getTypeName(), typeRegistry); } - public Set getEnd2EntityClassifications() { + public Set getEnd2EntityClassifications() { return super.getClassificationNames(end2Entity); } diff --git a/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthorizer.java b/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthorizer.java index 7b99e97c1d7..6b33ea10f39 100644 --- a/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthorizer.java +++ b/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasSimpleAuthorizer.java @@ -32,6 +32,8 @@ import org.apache.atlas.authorize.simple.AtlasSimpleAuthzPolicy.*; import org.apache.atlas.model.discovery.AtlasSearchResult; import org.apache.atlas.model.discovery.AtlasSearchResult.AtlasFullTextResult; +import org.apache.atlas.authorize.AtlasAccessorResponse; +import org.apache.atlas.model.instance.AtlasClassification; import org.apache.atlas.model.instance.AtlasEntityHeader; import org.apache.atlas.model.typedef.AtlasBaseTypeDef; import org.apache.atlas.model.typedef.AtlasTypesDef; @@ -107,7 +109,7 @@ public void cleanUp() { } @Override - public boolean isAccessAllowed(AtlasAdminAccessRequest request) throws AtlasAuthorizationException { + public AtlasAccessResult isAccessAllowed(AtlasAdminAccessRequest request) throws AtlasAuthorizationException { if (LOG.isDebugEnabled()) { LOG.debug("==> SimpleAtlasAuthorizer.isAccessAllowed({})", request); } @@ -136,11 +138,11 @@ public boolean isAccessAllowed(AtlasAdminAccessRequest request) throws AtlasAuth LOG.debug("<== SimpleAtlasAuthorizer.isAccessAllowed({}): {}", request, ret); } - return ret; + return new AtlasAccessResult(ret); } @Override - public boolean isAccessAllowed(AtlasTypeAccessRequest request) throws AtlasAuthorizationException { + public AtlasAccessResult isAccessAllowed(AtlasTypeAccessRequest request) throws AtlasAuthorizationException { if (LOG.isDebugEnabled()) { LOG.debug("==> SimpleAtlasAuthorizer.isAccessAllowed({})", request); } @@ -173,18 +175,41 @@ public boolean isAccessAllowed(AtlasTypeAccessRequest request) throws AtlasAutho LOG.debug("<== SimpleAtlasAuthorizer.isAccessAllowed({}): {}", request, ret); } - return ret; + return new AtlasAccessResult(ret); + } + + @Override + public AtlasAccessorResponse getAccessors(AtlasEntityAccessRequest request) { + //TODO: implement method + return null; + } + + @Override + public AtlasAccessorResponse getAccessors(AtlasRelationshipAccessRequest request) { + //TODO: implement method + return null; } @Override - public boolean isAccessAllowed(AtlasRelationshipAccessRequest request) throws AtlasAuthorizationException { + public AtlasAccessorResponse getAccessors(AtlasTypeAccessRequest request) { + //TODO: implement method + return null; + } + + @Override + public Set getRolesForCurrentUser(String userName, Set groups) { + return null; + } + + @Override + public AtlasAccessResult isAccessAllowed(AtlasRelationshipAccessRequest request) throws AtlasAuthorizationException { final Set roles = getRoles(request.getUser(), request.getUserGroups()); final String relationShipType = request.getRelationshipType(); final Set end1EntityTypeAndSuperTypes = request.getEnd1EntityTypeAndAllSuperTypes(); - final Set end1Classifications = new HashSet<>(request.getEnd1EntityClassifications()); + final Set end1Classifications = new HashSet<>(request.getEnd1EntityClassifications()); final String end1EntityId = request.getEnd1EntityId(); final Set end2EntityTypeAndSuperTypes = request.getEnd2EntityTypeAndAllSuperTypes(); - final Set end2Classifications = new HashSet<>(request.getEnd2EntityClassifications()); + final Set end2Classifications = new HashSet<>(request.getEnd2EntityClassifications()); final String end2EntityId = request.getEnd2EntityId(); final String action = request.getAction() != null ? request.getAction().getType() : null; @@ -203,10 +228,10 @@ public boolean isAccessAllowed(AtlasRelationshipAccessRequest request) throws At //End1 permission check if (!hasEnd1EntityAccess) { if (isMatchAny(end1EntityTypeAndSuperTypes, permission.getEnd1EntityType()) && isMatch(end1EntityId, permission.getEnd1EntityId())) { - for (Iterator iter = end1Classifications.iterator(); iter.hasNext();) { - String entityClassification = iter.next(); + for (Iterator iter = end1Classifications.iterator(); iter.hasNext();) { + AtlasClassification entityClassification = iter.next(); - if (isMatchAny(request.getClassificationTypeAndAllSuperTypes(entityClassification), permission.getEnd1EntityClassification())) { + if (isMatchAny(request.getClassificationTypeAndAllSuperTypes(entityClassification.getTypeName()), permission.getEnd1EntityClassification())) { iter.remove(); } } @@ -218,10 +243,10 @@ public boolean isAccessAllowed(AtlasRelationshipAccessRequest request) throws At //End2 permission chech if (!hasEnd2EntityAccess) { if (isMatchAny(end2EntityTypeAndSuperTypes, permission.getEnd2EntityType()) && isMatch(end2EntityId, permission.getEnd2EntityId())) { - for (Iterator iter = end2Classifications.iterator(); iter.hasNext();) { - String entityClassification = iter.next(); + for (Iterator iter = end2Classifications.iterator(); iter.hasNext();) { + AtlasClassification entityClassification = iter.next(); - if (isMatchAny(request.getClassificationTypeAndAllSuperTypes(entityClassification), permission.getEnd2EntityClassification())) { + if (isMatchAny(request.getClassificationTypeAndAllSuperTypes(entityClassification.getTypeName()), permission.getEnd2EntityClassification())) { iter.remove(); } } @@ -233,11 +258,11 @@ public boolean isAccessAllowed(AtlasRelationshipAccessRequest request) throws At } } - return hasEnd1EntityAccess && hasEnd2EntityAccess; + return new AtlasAccessResult(hasEnd1EntityAccess && hasEnd2EntityAccess); } @Override - public boolean isAccessAllowed(AtlasEntityAccessRequest request) throws AtlasAuthorizationException { + public AtlasAccessResult isAccessAllowed(AtlasEntityAccessRequest request, boolean isAuditEnabled) throws AtlasAuthorizationException { if (LOG.isDebugEnabled()) { LOG.debug("==> SimpleAtlasAuthorizer.isAccessAllowed({})", request); } @@ -247,7 +272,7 @@ public boolean isAccessAllowed(AtlasEntityAccessRequest request) throws AtlasAut final Set entityTypes = request.getEntityTypeAndAllSuperTypes(); final String entityId = request.getEntityId(); final String attribute = request.getAttributeName(); - final Set entClsToAuthz = new HashSet<>(request.getEntityClassifications()); + final Set entClsToAuthz = new HashSet<>(request.getEntityClassifications()); final Set roles = getRoles(request.getUser(), request.getUserGroups()); for (String role : roles) { @@ -263,10 +288,10 @@ public boolean isAccessAllowed(AtlasEntityAccessRequest request) throws AtlasAut // 2. access for these classifications could be granted by multiple AtlasEntityPermission entries // 3. classifications allowed by the current permission will be removed from entClsToAuthz // 4. request will be allowed once entClsToAuthz is empty i.e. user has permission for all classifications - for (Iterator iter = entClsToAuthz.iterator(); iter.hasNext(); ) { - String entityClassification = iter.next(); + for (Iterator iter = entClsToAuthz.iterator(); iter.hasNext(); ) { + AtlasClassification entityClassification = iter.next(); - if (isMatchAny(request.getClassificationTypeAndAllSuperTypes(entityClassification), permission.getEntityClassifications())) { + if (isMatchAny(request.getClassificationTypeAndAllSuperTypes(entityClassification.getTypeName()), permission.getEntityClassifications())) { iter.remove(); } } @@ -289,7 +314,7 @@ public boolean isAccessAllowed(AtlasEntityAccessRequest request) throws AtlasAut LOG.debug("<== SimpleAtlasAuthorizer.isAccessAllowed({}): {}", request, ret); } - return ret; + return new AtlasAccessResult(ret); } @Override @@ -478,8 +503,9 @@ private void checkAccessAndScrub(AtlasEntityHeader entity, AtlasSearchResultScru entityAccessRequest.setClientIPAddress(request.getClientIPAddress()); - if (!isAccessAllowed(entityAccessRequest)) { - scrubEntityHeader(entity); + + if (!isAccessAllowed(entityAccessRequest, true).isAllowed()) { + scrubEntityHeader(entity, request.getTypeRegistry()); } } } @@ -506,7 +532,7 @@ private void filterTypes(AtlasAccessRequest request, List + + + + + apache-atlas + org.apache.atlas + 3.0.0-SNAPSHOT + + 4.0.0 + + client-auth + + + 17 + 17 + 26.1.0 + + + + + org.keycloak + keycloak-core + ${keycloak-admin-client.version} + + + * + * + + + + + + com.squareup.okhttp3 + okhttp + ${okhttp3.version} + + + com.squareup.retrofit2 + retrofit + ${retrofit.version} + + + com.squareup.retrofit2 + converter-jackson + ${retrofit.version} + + + com.squareup.okhttp3 + logging-interceptor + ${okhttp3.version} + + + org.apache.atlas + atlas-common + + + + \ No newline at end of file diff --git a/client-auth/src/main/java/org/apache/atlas/auth/client/auth/AbstractAuthClient.java b/client-auth/src/main/java/org/apache/atlas/auth/client/auth/AbstractAuthClient.java new file mode 100644 index 00000000000..bd6153f4bec --- /dev/null +++ b/client-auth/src/main/java/org/apache/atlas/auth/client/auth/AbstractAuthClient.java @@ -0,0 +1,151 @@ +package org.apache.atlas.auth.client.auth; + +import io.micrometer.core.instrument.Timer; +import org.apache.atlas.auth.client.config.AuthConfig; +import org.apache.atlas.auth.client.heracles.RetrofitHeraclesClient; +import org.apache.atlas.auth.client.keycloak.RetrofitKeycloakClient; +import okhttp3.*; +import okhttp3.logging.HttpLoggingInterceptor; +import org.apache.atlas.AtlasErrorCode; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.service.metrics.MetricUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.lang.NonNull; +import retrofit2.Retrofit; +import retrofit2.converter.jackson.JacksonConverterFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import static java.net.HttpURLConnection.HTTP_BAD_REQUEST; +import static java.net.HttpURLConnection.HTTP_NOT_FOUND; +import static org.apache.atlas.AtlasErrorCode.BAD_REQUEST; +import static org.apache.atlas.AtlasErrorCode.RESOURCE_NOT_FOUND; + +public class AbstractAuthClient { + + private final static Logger LOG = LoggerFactory.getLogger(AbstractAuthClient.class); + private static final Map ERROR_CODE_MAP = new HashMap<>(); + + private static final int DEFAULT_RETRY = 3; + private static final String AUTHORIZATION = "Authorization"; + private static final String BEARER = "Bearer "; + private static final int TIMEOUT_IN_SEC = 60; + private static final String INTEGRATION = "integration"; + private static final String KEYCLOAK = "keycloak"; + + protected final AuthConfig authConfig; + protected final RetrofitKeycloakClient retrofitKeycloakClient; + protected final RetrofitHeraclesClient retrofitHeraclesClient; + + private final KeycloakAuthenticationService authService; + private MetricUtils metricUtils = null; + + static { + ERROR_CODE_MAP.put(HTTP_NOT_FOUND, RESOURCE_NOT_FOUND); + ERROR_CODE_MAP.put(HTTP_BAD_REQUEST, BAD_REQUEST); + } + + public AbstractAuthClient(AuthConfig authConfig) { + this.authConfig = authConfig; + this.metricUtils = new MetricUtils(); + HttpLoggingInterceptor httpInterceptor = new HttpLoggingInterceptor(); + httpInterceptor.setLevel(HttpLoggingInterceptor.Level.NONE); + OkHttpClient okHttpClient = new OkHttpClient.Builder() + .addInterceptor(accessTokenInterceptor) + .addInterceptor(httpInterceptor) + .addInterceptor(responseLoggingInterceptor) + .authenticator(authInterceptor) + .connectTimeout(TIMEOUT_IN_SEC, TimeUnit.SECONDS) + .callTimeout(TIMEOUT_IN_SEC, TimeUnit.SECONDS) + .writeTimeout(TIMEOUT_IN_SEC, TimeUnit.SECONDS) + .readTimeout(TIMEOUT_IN_SEC, TimeUnit.SECONDS) + .build(); + this.retrofitKeycloakClient = new Retrofit.Builder().client(okHttpClient) + .baseUrl(this.authConfig.getAuthServerUrl()) + .addConverterFactory(JacksonConverterFactory.create(ObjectMapperUtils.KEYCLOAK_OBJECT_MAPPER)).build() + .create(RetrofitKeycloakClient.class); + this.retrofitHeraclesClient = new Retrofit.Builder().client(okHttpClient) + .baseUrl(this.authConfig.getHeraclesApiServerUrl()) + .addConverterFactory(JacksonConverterFactory.create(ObjectMapperUtils.HERACLES_OBJECT_MAPPER)).build() + .create(RetrofitHeraclesClient.class); + authService = new KeycloakAuthenticationService(authConfig); + } + + /** + * Basic interceptor for logging. + */ + Interceptor responseLoggingInterceptor = chain -> { + Request request = chain.request(); + String rawPath = request.url().uri().getRawPath(); + Timer.Sample timerSample = this.metricUtils.start(rawPath); + okhttp3.Response response = chain.proceed(request); + this.metricUtils.recordHttpTimer(timerSample, request.method(), rawPath, response.code(), + INTEGRATION, KEYCLOAK); + return response; + }; + + /** + * Called for every request made to keycloak + */ + Interceptor accessTokenInterceptor = new Interceptor() { + @NonNull + @Override + public Response intercept(@NonNull Chain chain) throws IOException { + Request request = chain.request().newBuilder() + .header(AUTHORIZATION, BEARER + authService.getAuthToken()) + .build(); + return chain.proceed(request); + } + }; + /** + * Called only during auth failures. + */ + Authenticator authInterceptor = new Authenticator() { + @Override + public Request authenticate(Route route, @NonNull Response response) { + if (responseCount(response) > DEFAULT_RETRY) { + LOG.warn("Auth Client: Falling back, retried {} times", DEFAULT_RETRY); + return null; + } + LOG.info("Auth Client: Current keycloak token status, Expired: {}", authService.isTokenExpired()); + return response.request().newBuilder() + .addHeader(AUTHORIZATION, BEARER + authService.getAuthToken()) + .build(); + } + + private int responseCount(Response response) { + int retryCount = 1; + while ((response = response.priorResponse()) != null) { + retryCount++; + } + return retryCount; + } + + }; + + /** + * Process incoming request, and error handling. + */ + protected retrofit2.Response processResponse(retrofit2.Call req) throws AtlasBaseException { + try { + retrofit2.Response response = req.execute(); + if (Objects.isNull(response.errorBody())) { + return response; + } + String errMsg = response.errorBody().string(); + LOG.error("Auth Client: Client request processing failed code {} message:{}, request: {} {}", + response.code(), errMsg, req.request().method(), req.request().url()); + throw new AtlasBaseException(ERROR_CODE_MAP.getOrDefault(response.code(), BAD_REQUEST), errMsg); + } catch (Exception e) { + LOG.error("Auth Client: request failed, request: {} {}, Exception: {}", req.request().method(), req.request().url(), e); + throw new AtlasBaseException(BAD_REQUEST, "Auth request failed"); + } + } + + +} diff --git a/client-auth/src/main/java/org/apache/atlas/auth/client/auth/KeycloakAuthenticationService.java b/client-auth/src/main/java/org/apache/atlas/auth/client/auth/KeycloakAuthenticationService.java new file mode 100644 index 00000000000..6a2850e2ed3 --- /dev/null +++ b/client-auth/src/main/java/org/apache/atlas/auth/client/auth/KeycloakAuthenticationService.java @@ -0,0 +1,106 @@ +package org.apache.atlas.auth.client.auth; + +import okhttp3.*; +import okhttp3.logging.HttpLoggingInterceptor; +import org.apache.atlas.auth.client.config.AuthConfig; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.auth.client.keycloak.RetrofitKeycloakClient; +import org.jetbrains.annotations.NotNull; +import org.keycloak.representations.AccessTokenResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import retrofit2.Retrofit; +import retrofit2.converter.jackson.JacksonConverterFactory; + +import java.time.OffsetDateTime; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import static org.apache.atlas.AtlasErrorCode.BAD_REQUEST; + +public final class KeycloakAuthenticationService { + + public final static Logger LOG = LoggerFactory.getLogger(KeycloakAuthenticationService.class); + + private final static String GRANT_TYPE = "grant_type"; + private static final String CLIENT_ID = "client_id"; + private static final String CLIENT_SECRET = "client_secret"; + private static final int EXPIRY_OFFSET_SEC = 600; + private static final int TIMEOUT_IN_SECS = 60; + + private final RetrofitKeycloakClient retrofit; + private final AuthConfig authConfig; + private AccessTokenResponse currentAccessToken; + private long expirationTime = -1; + + public KeycloakAuthenticationService(AuthConfig authConfig) { + this.authConfig = authConfig; + this.retrofit = new Retrofit.Builder().client(getOkHttpClient()) + .baseUrl(this.authConfig.getAuthServerUrl()) + .addConverterFactory(JacksonConverterFactory.create(ObjectMapperUtils.KEYCLOAK_OBJECT_MAPPER)).build() + .create(RetrofitKeycloakClient.class); + } + + @NotNull + private OkHttpClient getOkHttpClient() { + HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); + interceptor.setLevel(HttpLoggingInterceptor.Level.NONE); + return new OkHttpClient.Builder() + .addInterceptor(interceptor) + .addInterceptor(responseLoggingInterceptor) + .connectTimeout(TIMEOUT_IN_SECS, TimeUnit.SECONDS) + .callTimeout(TIMEOUT_IN_SECS, TimeUnit.SECONDS) + .writeTimeout(TIMEOUT_IN_SECS, TimeUnit.SECONDS) + .readTimeout(TIMEOUT_IN_SECS, TimeUnit.SECONDS) + .build(); + } + + Interceptor responseLoggingInterceptor = chain -> { + Request request = chain.request(); + okhttp3.Response response = chain.proceed(request); + LOG.info("Auth Client: Auth Request for url {} Status: {}", request.url(), response.code()); + return response; + }; + + public String getAuthToken() { + if (!isTokenExpired()) { + return currentAccessToken.getToken(); + } + synchronized (this) { + if (isTokenExpired()) { + try { + retrofit2.Response resp = this.retrofit.grantToken(this.authConfig.getRealmId(), getTokenRequest()).execute(); + if (resp.isSuccessful()) { + currentAccessToken = resp.body(); + expirationTime = currentTime() + currentAccessToken.getExpiresIn() - EXPIRY_OFFSET_SEC; + LOG.info("Auth Client: Auth token fetched with expiry:{} sec", expirationTime); + } else { + throw new AtlasBaseException(BAD_REQUEST, resp.errorBody().string()); + } + } catch (Exception e) { + LOG.error("Auth Client: Error while fetching access token for keycloak client.", e); + throw new RuntimeException(e); + } + } + } + return currentAccessToken.getToken(); + } + + public boolean isTokenExpired() { + synchronized (this) { + if (Objects.isNull(currentAccessToken)) { + return true; + } + return currentTime() >= expirationTime; + } + } + + private RequestBody getTokenRequest() { + return new FormBody.Builder().addEncoded(CLIENT_ID, this.authConfig.getClientId()).addEncoded(CLIENT_SECRET, this.authConfig.getClientSecret()).addEncoded(GRANT_TYPE, this.authConfig.getGrantType()).build(); + } + + private long currentTime() { + return OffsetDateTime.now().toEpochSecond(); + } + +} diff --git a/client-auth/src/main/java/org/apache/atlas/auth/client/auth/ObjectMapperUtils.java b/client-auth/src/main/java/org/apache/atlas/auth/client/auth/ObjectMapperUtils.java new file mode 100644 index 00000000000..5d41a6c13f4 --- /dev/null +++ b/client-auth/src/main/java/org/apache/atlas/auth/client/auth/ObjectMapperUtils.java @@ -0,0 +1,31 @@ +package org.apache.atlas.auth.client.auth; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Utility class providing shared ObjectMapper instances for auth clients. + * Using static instances to avoid expensive ObjectMapper creation overhead. + */ +final class ObjectMapperUtils { + + /** + * ObjectMapper configured for Keycloak clients - ignores unknown properties. + * This handles cases where the Keycloak API returns additional fields not defined in client representation classes. + * Example: Keycloak admin events returning "id" field not present in AdminEventRepresentation. + */ + static final ObjectMapper KEYCLOAK_OBJECT_MAPPER = new ObjectMapper() + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + + /** + * ObjectMapper configured for Heracles clients - ignores ignored properties. + * This handles cases where JSON contains fields marked with @JsonIgnore in the target class. + * Preserves the original behavior for Heracles client compatibility. + */ + static final ObjectMapper HERACLES_OBJECT_MAPPER = new ObjectMapper() + .disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES); + + private ObjectMapperUtils() { + // Utility class - prevent instantiation + } +} \ No newline at end of file diff --git a/client-auth/src/main/java/org/apache/atlas/auth/client/config/AuthConfig.java b/client-auth/src/main/java/org/apache/atlas/auth/client/config/AuthConfig.java new file mode 100644 index 00000000000..33d98de0492 --- /dev/null +++ b/client-auth/src/main/java/org/apache/atlas/auth/client/config/AuthConfig.java @@ -0,0 +1,100 @@ +package org.apache.atlas.auth.client.config; + +import org.apache.atlas.AtlasErrorCode; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.commons.lang.StringUtils; +import org.codehaus.jettison.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.Optional; + +import static org.apache.atlas.ApplicationProperties.ATLAS_CONFIGURATION_DIRECTORY_PROPERTY; + +public class AuthConfig { + private static final Logger LOG = LoggerFactory.getLogger(AuthConfig.class); + + public String authServerUrl; + public String realmId; + public String clientId; + public String clientSecret; + public String grantType; + public String heraclesApiServerUrl; + + private static final String KEYCLOAK_PROPERTIES = "keycloak.json"; + private static final String DEFAULT_GRANT_TYPE = "client_credentials"; + private static final String KEY_REALM_ID = "realm"; + private static final String KEY_AUTH_SERVER_URL = "auth-server-url"; + private static final String KEY_CLIENT_ID = "resource"; + private static final String KEY_CREDENTIALS = "credentials"; + private static final String KEY_SECRET = "secret"; + + public String getAuthServerUrl() { + return authServerUrl; + } + + public String getRealmId() { + return realmId; + } + + public String getClientId() { + return clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public String getGrantType() { + return grantType; + } + + public String getHeraclesApiServerUrl() { + return heraclesApiServerUrl; + } + + public static AuthConfig getConfig() throws AtlasBaseException { + String confLocation = System.getProperty(ATLAS_CONFIGURATION_DIRECTORY_PROPERTY); + Optional confFile = getConfigurationFile(confLocation); + + if (confFile.isPresent()) { + try { + JSONObject object = new JSONObject(readFileToString(confFile.get())); + return buildAuthConfigFromJson(object); + } catch (Exception e) { + LOG.error("Error parsing Keycloak configuration: ", e); + throw new AtlasBaseException(AtlasErrorCode.KEYCLOAK_INIT_FAILED, "Error parsing Keycloak configuration"); + } + } else { + throw new AtlasBaseException(AtlasErrorCode.KEYCLOAK_INIT_FAILED, "Keycloak configuration file not found in location " + confLocation); + } + } + + private static Optional getConfigurationFile(String confLocation) { + if (StringUtils.isNotEmpty(confLocation)) { + File confFile = new File(confLocation, KEYCLOAK_PROPERTIES); + if (confFile.exists()) { + return Optional.of(confFile); + } + } + return Optional.empty(); + } + + private static String readFileToString(File file) throws Exception { + return new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8); + } + + private static AuthConfig buildAuthConfigFromJson(JSONObject object) throws Exception { + String realmId = object.getString(KEY_REALM_ID); + String authServerUrl = object.getString(KEY_AUTH_SERVER_URL) + "/"; + String clientId = object.getString(KEY_CLIENT_ID); + String grantType = DEFAULT_GRANT_TYPE; + String clientSecret = object.getJSONObject(KEY_CREDENTIALS).getString(KEY_SECRET); + + LOG.info("Keycloak configuration: REALM_ID:{}, AUTH_SERVER_URL:{}", realmId, authServerUrl); + return AuthConfigBuilder.builder().realId(realmId).authServerUrl(authServerUrl).clientId(clientId).grantType(grantType).clientSecret(clientSecret).build(); + } +} diff --git a/client-auth/src/main/java/org/apache/atlas/auth/client/config/AuthConfigBuilder.java b/client-auth/src/main/java/org/apache/atlas/auth/client/config/AuthConfigBuilder.java new file mode 100644 index 00000000000..552033d2c15 --- /dev/null +++ b/client-auth/src/main/java/org/apache/atlas/auth/client/config/AuthConfigBuilder.java @@ -0,0 +1,55 @@ +package org.apache.atlas.auth.client.config; + +import org.apache.atlas.AtlasConfiguration; + +public class AuthConfigBuilder { + + private String authServerUrl; + private String realmId; + private String clientId; + private String clientSecret; + private String grantType = "client_credentials"; + + private AuthConfigBuilder() { + } + + public static AuthConfigBuilder builder() { + return new AuthConfigBuilder(); + } + + public AuthConfigBuilder authServerUrl(String authServerUrl) { + this.authServerUrl = authServerUrl; + return this; + } + + public AuthConfigBuilder realId(String realId) { + this.realmId = realId; + return this; + } + + public AuthConfigBuilder clientId(String clientId) { + this.clientId = clientId; + return this; + } + + public AuthConfigBuilder clientSecret(String clientSecret) { + this.clientSecret = clientSecret; + return this; + } + + public AuthConfigBuilder grantType(String grantType) { + this.grantType = grantType; + return this; + } + + public AuthConfig build() { + AuthConfig authConfig = new AuthConfig(); + authConfig.authServerUrl = authServerUrl; + authConfig.realmId = realmId; + authConfig.clientId = clientId; + authConfig.clientSecret = clientSecret; + authConfig.grantType = grantType; + authConfig.heraclesApiServerUrl= AtlasConfiguration.HERACLES_API_SERVER_URL.getString()+"/"; + return authConfig; + } +} diff --git a/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/AtlasHeraclesClient.java b/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/AtlasHeraclesClient.java new file mode 100644 index 00000000000..6c0c4b7d564 --- /dev/null +++ b/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/AtlasHeraclesClient.java @@ -0,0 +1,59 @@ +package org.apache.atlas.auth.client.heracles; + +import org.apache.atlas.auth.client.config.AuthConfig; +import org.apache.atlas.auth.client.heracles.models.HeraclesRoleViewRepresentation; +import org.apache.atlas.auth.client.heracles.models.HeraclesUserViewRepresentation; +import org.apache.atlas.exception.AtlasBaseException; +import org.keycloak.representations.idm.UserRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class AtlasHeraclesClient { + public final static Logger LOG = LoggerFactory.getLogger(AtlasHeraclesClient.class); + + private static HeraclesRestClient HERACLES; + private static AtlasHeraclesClient HERACLES_CLIENT; + + public AtlasHeraclesClient() {} + + public static AtlasHeraclesClient getHeraclesClient() { + if(Objects.isNull(HERACLES_CLIENT)) { + LOG.info("Initializing Heracles client.."); + try{ + init(AuthConfig.getConfig()); + } catch (Exception e) { + LOG.error("Error initializing Heracles client", e); + } + } + return HERACLES_CLIENT; + } + + private static void init(AuthConfig authConfig) { + synchronized (AtlasHeraclesClient.class) { + if (HERACLES == null) { + HERACLES = new HeraclesRestClient(authConfig); + HERACLES_CLIENT = new AtlasHeraclesClient(); + } + } + } + + public List getUsersMappings(int start, int size, String[] columns) throws AtlasBaseException {; + List views = HERACLES.getUsersMappings(start, size, HeraclesUserViewRepresentation.sortBy, columns).body(); + return views.stream().map(x -> { + UserRepresentation userRepresentation = new UserRepresentation(); + userRepresentation.setId(x.getId()); + userRepresentation.setUsername(x.getUsername()); + userRepresentation.setRealmRoles(x.getRoles()); + userRepresentation.setGroups(x.getGroups()); + return userRepresentation; + }).collect(Collectors.toList()); + } + + public List getRolesMappings(int start, int size, String[] columns) throws AtlasBaseException { + return HERACLES.getRolesMappings(start, size, HeraclesRoleViewRepresentation.sortBy, columns).body(); + } +} diff --git a/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/HeraclesRestClient.java b/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/HeraclesRestClient.java new file mode 100644 index 00000000000..c6fbbcb935d --- /dev/null +++ b/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/HeraclesRestClient.java @@ -0,0 +1,25 @@ +package org.apache.atlas.auth.client.heracles; + +import org.apache.atlas.auth.client.config.AuthConfig; +import org.apache.atlas.auth.client.auth.AbstractAuthClient; +import org.apache.atlas.auth.client.heracles.models.HeraclesRoleViewRepresentation; +import org.apache.atlas.auth.client.heracles.models.HeraclesUserViewRepresentation; +import org.apache.atlas.exception.AtlasBaseException; +import retrofit2.Response; + +import java.util.List; + +public class HeraclesRestClient extends AbstractAuthClient { + + public HeraclesRestClient(final AuthConfig authConfig) { + super(authConfig); + } + public Response> getUsersMappings(int offset, int limit, String sort, String[] columns) throws AtlasBaseException { + return processResponse(this.retrofitHeraclesClient.getUsersMapping(offset, limit,sort, columns)); + } + + public Response> getRolesMappings(int offset, int limit, String sort, String[] columns) throws AtlasBaseException { + return processResponse(this.retrofitHeraclesClient.getRolesMapping(offset, limit, sort, columns)); + } + +} \ No newline at end of file diff --git a/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/RetrofitHeraclesClient.java b/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/RetrofitHeraclesClient.java new file mode 100644 index 00000000000..b9fd8de6ca4 --- /dev/null +++ b/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/RetrofitHeraclesClient.java @@ -0,0 +1,24 @@ +package org.apache.atlas.auth.client.heracles; + +import org.apache.atlas.auth.client.heracles.models.HeraclesRoleViewRepresentation; +import org.apache.atlas.auth.client.heracles.models.HeraclesUserViewRepresentation; +import retrofit2.Call; +import retrofit2.http.GET; +import retrofit2.http.Headers; +import retrofit2.http.Query; + +import java.util.List; + +public interface RetrofitHeraclesClient { + @Headers({"Accept: application/json,text/plain", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("/users/mappings") + Call> getUsersMapping(@Query("offset") Integer offset, @Query("limit") Integer limit, @Query("sort") String sort, + @Query("columns") String[] columns); + + @Headers({"Accept: application/json,text/plain", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("/roles/mappings") + Call> getRolesMapping(@Query("offset") Integer offset, @Query("limit") Integer limit, @Query("sort") String sort, + @Query("columns") String[] columns); + + +} diff --git a/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/models/HeraclesRoleViewRepresentation.java b/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/models/HeraclesRoleViewRepresentation.java new file mode 100644 index 00000000000..5b695bcf715 --- /dev/null +++ b/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/models/HeraclesRoleViewRepresentation.java @@ -0,0 +1,60 @@ +package org.apache.atlas.auth.client.heracles.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class HeraclesRoleViewRepresentation { + protected String id; + protected String name; + protected String realmId; + protected List roles; + protected List groups; + + public static String sortBy = "name"; + + public HeraclesRoleViewRepresentation() { + } + + public String getId() { + return id; + } + + public String getName() { + return name; + } + + public String getRealmId() { + return realmId; + } + + public List getRoles() { + return roles == null ? new ArrayList<>() : roles; + } + + public List getGroups() { + return groups == null ? new ArrayList<>() : groups; + } + + public void setId(String id) { + this.id = id; + } + + public void setName(String name) { + this.name = name; + } + + public void setRealmId(String realmId) { + this.realmId = realmId; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + public void setGroups(List groups) { + this.groups = groups; + } +} diff --git a/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/models/HeraclesUserViewRepresentation.java b/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/models/HeraclesUserViewRepresentation.java new file mode 100644 index 00000000000..bf65b2043bd --- /dev/null +++ b/client-auth/src/main/java/org/apache/atlas/auth/client/heracles/models/HeraclesUserViewRepresentation.java @@ -0,0 +1,62 @@ +package org.apache.atlas.auth.client.heracles.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import org.keycloak.representations.idm.UserRepresentation; + +import java.util.ArrayList; +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +public class HeraclesUserViewRepresentation { + protected String id; + protected String username; + protected boolean enabled; + protected List roles; + protected List groups; + + public static String sortBy = "username"; + + public HeraclesUserViewRepresentation() { + } + + public String getId() { + return id; + } + + public String getUsername() { + return username; + } + + public boolean isEnabled() { + return enabled; + } + + public List getRoles() { + return roles == null ? new ArrayList<>() : roles; + } + + public List getGroups() { + return groups == null ? new ArrayList<>() : groups; + } + + public void setId(String id) { + this.id = id; + } + + public void setUsername(String username) { + this.username = username; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void setRoles(List roles) { + this.roles = roles; + } + + public void setGroups(List groups) { + this.groups = groups; + } + +} diff --git a/client-auth/src/main/java/org/apache/atlas/auth/client/keycloak/AtlasKeycloakClient.java b/client-auth/src/main/java/org/apache/atlas/auth/client/keycloak/AtlasKeycloakClient.java new file mode 100644 index 00000000000..9ec43428e62 --- /dev/null +++ b/client-auth/src/main/java/org/apache/atlas/auth/client/keycloak/AtlasKeycloakClient.java @@ -0,0 +1,188 @@ +package org.apache.atlas.auth.client.keycloak; + +import org.apache.atlas.auth.client.config.AuthConfig; +import org.apache.atlas.AtlasErrorCode; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.commons.collections.CollectionUtils; +import org.keycloak.representations.idm.*; +import org.keycloak.representations.oidc.TokenMetadataRepresentation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +/** + * Keycloak client, deals with token creation refresh. + */ +public final class AtlasKeycloakClient { + + public final static Logger LOG = LoggerFactory.getLogger(AtlasKeycloakClient.class); + + private static KeycloakRestClient KEYCLOAK; + private static AtlasKeycloakClient KEYCLOAK_CLIENT; + + private AtlasKeycloakClient() { + } + + public List searchUserByUserName(String username) throws AtlasBaseException { + return KEYCLOAK.searchUserByUserName(username).body(); + } + + public Set getRoleUserMembers(String roleName, int start, int size) throws AtlasBaseException { + return KEYCLOAK.getRoleUserMembers(roleName, start, size).body(); + } + + public List getRoleUserMembers(String roleName) throws AtlasBaseException { + return KEYCLOAK.getRoleUserMembers(roleName).body(); + } + + public List getAllUsers() throws AtlasBaseException { + int start = 0; + int size = 500; + boolean found = true; + + List ret = new ArrayList<>(0); + + do { + List userRepresentations = KEYCLOAK.getAllUsers(start, size).body(); + if (CollectionUtils.isNotEmpty(userRepresentations)) { + ret.addAll(userRepresentations); + start += size; + } else { + found = false; + } + + } while (found && ret.size() % size == 0); + + return ret; + } + + public List searchGroupByName(String groupName, Integer start, Integer size) throws AtlasBaseException { + return KEYCLOAK.searchGroupByName(groupName, start, size).body(); + } + + public List getRoleGroupMembers(String roleName) throws AtlasBaseException { + return KEYCLOAK.getRoleGroupMembers(roleName).body(); + } + + public Set getRoleGroupMembers(String roleName, Integer start, Integer size) throws AtlasBaseException { + return KEYCLOAK.getRoleGroupMembers(roleName, start, size).body(); + } + + public List getGroupsForUserById(String userId) throws AtlasBaseException { + return KEYCLOAK.getGroupsForUserById(userId).body(); + } + + public void addRealmLevelRoleMappingsForGroup(String groupId, List roles) throws AtlasBaseException { + KEYCLOAK.addRealmLevelRoleMappingsForGroup(groupId, roles); + } + + public void deleteRealmLevelRoleMappingsForGroup(String groupId, List roles) throws AtlasBaseException { + KEYCLOAK.deleteRealmLevelRoleMappingsForGroup(groupId, roles); + } + + public List getAllRoles() throws AtlasBaseException { + int start = 0; + int size = 500; + boolean found = true; + + List ret = new ArrayList<>(0); + do { + List roleRepresentations = KEYCLOAK.getAllRoles(start, size).body(); + if (CollectionUtils.isNotEmpty(roleRepresentations)) { + ret.addAll(roleRepresentations); + start += size; + } else { + found = false; + } + } while (found && ret.size() % size == 0); + + return ret; + } + + public void deleteRoleById(String roleId) throws AtlasBaseException { + KEYCLOAK.deleteRoleById(roleId); + } + + public void deleteRoleByName(String roleName) throws AtlasBaseException { + KEYCLOAK.deleteRoleByName(roleName); + } + + + public List addRealmLevelRoleMappingsForUser(String userId, List roles) throws AtlasBaseException { + return KEYCLOAK.addRealmLevelRoleMappingsForUser(userId, roles).body(); + } + + public void deleteRealmLevelRoleMappingsForUser(String userId, List roles) throws AtlasBaseException { + KEYCLOAK.deleteRealmLevelRoleMappingsForUser(userId, roles); + } + + public void createRole(RoleRepresentation roleRepresentation) throws AtlasBaseException { + KEYCLOAK.createRole(roleRepresentation); + } + + public void updateRole(String roleId, RoleRepresentation roleRepresentation) throws AtlasBaseException { + KEYCLOAK.updateRole(roleId, roleRepresentation); + } + + + public RoleRepresentation getRoleById(String roleId) throws AtlasBaseException { + return KEYCLOAK.getRoleById(roleId).body(); + } + + public RoleRepresentation getRoleByName(String roleName) throws AtlasBaseException { + return KEYCLOAK.getRoleByName(roleName).body(); + } + + public Set getRoleComposites(String roleName) throws AtlasBaseException { + return KEYCLOAK.getRoleComposites(roleName).body(); + } + + public void addComposites(String roleName, List roles) throws AtlasBaseException { + KEYCLOAK.addComposites(roleName, roles); + } + + public void deleteComposites(String roleName, List roles) throws AtlasBaseException { + KEYCLOAK.deleteComposites(roleName, roles); + } + + public List getAdminEvents(List operationTypes, String authRealm, String authClient, String authUser, String authIpAddress, String resourcePath, String dateFrom, String dateTo, Integer first, Integer max) throws AtlasBaseException { + return KEYCLOAK.getAdminEvents(operationTypes, authRealm, authClient, authUser, authIpAddress, resourcePath, dateFrom, dateTo, first, max).body(); + } + + public List getEvents(List type, String client, String user, String dateFrom, String dateTo, String ipAddress, Integer first, Integer max) throws AtlasBaseException { + return KEYCLOAK.getEvents(type, client, user, dateFrom, dateTo, ipAddress, first, max).body(); + } + + public TokenMetadataRepresentation introspectToken(String token) throws AtlasBaseException { + return KEYCLOAK.introspectToken(token).body(); + } + + public static AtlasKeycloakClient getKeycloakClient() throws AtlasBaseException { + if (Objects.isNull(KEYCLOAK_CLIENT)) { + LOG.info("Initializing Keycloak client.."); + try { + init(AuthConfig.getConfig()); + } catch (Exception e) { + LOG.error("Failed to connect to Keycloak {}", e.getMessage()); + throw new AtlasBaseException(AtlasErrorCode.KEYCLOAK_INIT_FAILED, e.getMessage()); + } + + LOG.info("Initialized Keycloak client.."); + } + + return KEYCLOAK_CLIENT; + } + + private static void init(AuthConfig config) { + synchronized (AtlasKeycloakClient.class) { + if (KEYCLOAK_CLIENT == null) { + KEYCLOAK = new KeycloakRestClient(config); + KEYCLOAK_CLIENT = new AtlasKeycloakClient(); + } + } + } +} diff --git a/client-auth/src/main/java/org/apache/atlas/auth/client/keycloak/KeycloakRestClient.java b/client-auth/src/main/java/org/apache/atlas/auth/client/keycloak/KeycloakRestClient.java new file mode 100644 index 00000000000..b6f58982e60 --- /dev/null +++ b/client-auth/src/main/java/org/apache/atlas/auth/client/keycloak/KeycloakRestClient.java @@ -0,0 +1,143 @@ +package org.apache.atlas.auth.client.keycloak; + +import org.apache.atlas.auth.client.auth.AbstractAuthClient; +import okhttp3.FormBody; +import okhttp3.RequestBody; +import org.apache.atlas.auth.client.config.AuthConfig; +import org.apache.atlas.exception.AtlasBaseException; +import org.keycloak.representations.idm.*; +import org.keycloak.representations.oidc.TokenMetadataRepresentation; +import retrofit2.Response; + +import java.util.List; +import java.util.Set; + +/** + * Keycloak Rest client wrapper used in atlas metastore + */ +public final class KeycloakRestClient extends AbstractAuthClient { + + private static final String TOKEN = "token"; + private static final String CLIENT_ID = "client_id"; + private static final String CLIENT_SECRET = "client_secret"; + public KeycloakRestClient(final AuthConfig authConfig) { + super(authConfig); + } + + public Response> searchUserByUserName(String username) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.searchUserByUserName(this.authConfig.getRealmId(), username)); + } + + public Response> getAllUsers(int start, int size) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.getAllUsers(this.authConfig.getRealmId(), start, size)); + } + + public Response> getRoleUserMembers(String roleName) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.getRoleUserMembers(this.authConfig.getRealmId(), roleName)); + } + + public Response> getRoleUserMembers(String roleName, Integer start, Integer size) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.getRoleUserMembers(this.authConfig.getRealmId(), roleName, start, size)); + } + + public Response> searchGroupByName(String groupName, Integer start, Integer size) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.searchGroupByName(this.authConfig.getRealmId(), groupName, start, size)); + } + + public Response> getRoleGroupMembers(String roleName) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.getRoleGroupMembers(this.authConfig.getRealmId(), roleName)); + } + + public Response> getRoleGroupMembers(String roleName, Integer first, Integer size) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.getRoleGroupMembers(this.authConfig.getRealmId(), roleName, first, size)); + } + + public Response> getGroupsForUserById(String userId) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.getGroupsForUserById(this.authConfig.getRealmId(), userId)); + } + + public void addRealmLevelRoleMappingsForGroup(String groupId, List roles) throws AtlasBaseException { + processResponse(this.retrofitKeycloakClient.addRealmLevelRoleMappingsForGroup(this.authConfig.getRealmId(), groupId, roles)); + } + + public void deleteRealmLevelRoleMappingsForGroup(String groupId, List roles) throws AtlasBaseException { + processResponse(this.retrofitKeycloakClient.deleteRealmLevelRoleMappingsForGroup(this.authConfig.getRealmId(), groupId, roles)); + } + + public Response> getAllRoles(int start, int size) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.getAllRoles(this.authConfig.getRealmId(), start, size)); + } + + public void deleteRoleById(String roleId) throws AtlasBaseException { + processResponse(this.retrofitKeycloakClient.deleteRoleById(this.authConfig.getRealmId(), roleId)); + } + + public void deleteRoleByName(String roleName) throws AtlasBaseException { + processResponse(this.retrofitKeycloakClient.deleteRoleByName(this.authConfig.getRealmId(), roleName)); + } + + public Response> addRealmLevelRoleMappingsForUser(String userId, List roles) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.addRealmLevelRoleMappingsForUser(this.authConfig.getRealmId(), userId, roles)); + } + + public void deleteRealmLevelRoleMappingsForUser(String userId, List roles) throws AtlasBaseException { + processResponse(this.retrofitKeycloakClient.deleteRealmLevelRoleMappingsForUser(this.authConfig.getRealmId(), userId, roles)); + } + + public void createRole(RoleRepresentation roleRepresentation) throws AtlasBaseException { + processResponse(this.retrofitKeycloakClient.createRole(this.authConfig.getRealmId(), roleRepresentation)); + } + + public void updateRole(String roleId, RoleRepresentation roleRepresentation) throws AtlasBaseException { + processResponse(this.retrofitKeycloakClient.updateRole(this.authConfig.getRealmId(), roleId, roleRepresentation)); + } + + public Response getRoleById(String roleId) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.getRoleById(this.authConfig.getRealmId(), roleId)); + } + + public Response getRoleByName(String roleName) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.getRoleByName(this.authConfig.getRealmId(), roleName)); + } + + public Response> getAllRoles(Integer first, Integer max) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.getAllRoles(this.authConfig.getRealmId(), first, max)); + } + + public Response> getRoleComposites(String roleName) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.getRoleComposites(this.authConfig.getRealmId(), roleName)); + } + + public void addComposites(String roleName, List roles) throws AtlasBaseException { + processResponse(this.retrofitKeycloakClient.addComposites(this.authConfig.getRealmId(), roleName, roles)); + } + + public void deleteComposites(String roleName, List roles) throws AtlasBaseException { + processResponse(this.retrofitKeycloakClient.deleteComposites(this.authConfig.getRealmId(), roleName, roles)); + } + + public Response> getAdminEvents(List operationTypes, String authRealm, + String authClient, String authUser, String authIpAddress, + String resourcePath, String dateFrom, String dateTo, + Integer first, Integer max) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.getAdminEvents(this.authConfig.getRealmId(), operationTypes, + authRealm, authClient, authUser, authIpAddress, resourcePath, dateFrom, dateTo, first, max)); + } + + public Response> getEvents(List type, String client, String user, String dateFrom, + String dateTo, String ipAddress, Integer first, Integer max) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.getEvents(this.authConfig.getRealmId(), type, client, user, dateFrom, dateTo, ipAddress, first, max)); + } + + public Response introspectToken(String token) throws AtlasBaseException { + return processResponse(this.retrofitKeycloakClient.introspectToken(this.authConfig.getRealmId(), getIntrospectTokenRequest(token))); + } + + private RequestBody getIntrospectTokenRequest(String token) { + return new FormBody.Builder() + .addEncoded(TOKEN, token) + .addEncoded(CLIENT_ID, this.authConfig.getClientId()) + .addEncoded(CLIENT_SECRET, this.authConfig.getClientSecret()) + .build(); + } +} diff --git a/client-auth/src/main/java/org/apache/atlas/auth/client/keycloak/RetrofitKeycloakClient.java b/client-auth/src/main/java/org/apache/atlas/auth/client/keycloak/RetrofitKeycloakClient.java new file mode 100644 index 00000000000..4fe8bb6ff51 --- /dev/null +++ b/client-auth/src/main/java/org/apache/atlas/auth/client/keycloak/RetrofitKeycloakClient.java @@ -0,0 +1,150 @@ +package org.apache.atlas.auth.client.keycloak; + +import okhttp3.RequestBody; +import org.keycloak.representations.AccessTokenResponse; +import org.keycloak.representations.idm.*; +import org.keycloak.representations.oidc.TokenMetadataRepresentation; +import retrofit2.Call; +import retrofit2.http.*; + +import java.util.List; +import java.util.Set; + +public interface RetrofitKeycloakClient { + + /* Keycloak Users */ + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("admin/realms/{realmId}/users") + Call> searchUserByUserName(@Path("realmId") String realmId, @Query("username") String username); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("admin/realms/{realmId}/users") + Call> getAllUsers(@Path("realmId") String realmId, @Query("first") Integer first, + @Query("max") Integer max); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("admin/realms/{realmId}/roles/{role-name}/users") + Call> getRoleUserMembers(@Path("realmId") String realmId, @Path("role-name") String roleName); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("admin/realms/{realmId}/roles/{role-name}/users") + Call> getRoleUserMembers(@Path("realmId") String realmId, @Path("role-name") String roleName, + @Query("first") Integer first, @Query("max") Integer max); + + + /* Keycloak Groups */ + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("admin/realms/{realmId}/groups") + Call> searchGroupByName(@Path("realmId") String realmId, @Query("search") String groupName, + @Query("first") Integer first, @Query("max") Integer max); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("admin/realms/{realmId}/roles/{role-name}/groups") + Call> getRoleGroupMembers(@Path("realmId") String realmId, @Path("role-name") String roleName); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("admin/realms/{realmId}/roles/{role-name}/groups") + Call> getRoleGroupMembers(@Path("realmId") String realmId, @Path("role-name") String roleName, + @Query("first") Integer first, @Query("max") Integer max); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("admin/realms/{realmId}/users/{id}/groups") + Call> getGroupsForUserById(@Path("realmId") String realmId, @Path("id") String userId); + + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @POST("admin/realms/{realmId}/groups/{id}/role-mappings/realm") + Call addRealmLevelRoleMappingsForGroup(@Path("realmId") String realmId, @Path("id") String groupId, @Body List roles); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @HTTP( method = "DELETE", path = "admin/realms/{realmId}/groups/{id}/role-mappings/realm", hasBody = true) + Call deleteRealmLevelRoleMappingsForGroup(@Path("realmId") String realmId, @Path("id") String groupId, @Body List roles); + + + /* Keycloak Roles */ + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @POST("admin/realms/{realmId}/users/{id}/role-mappings/realm") + Call> addRealmLevelRoleMappingsForUser(@Path("realmId") String realmId, @Path("id") String userId, + @Body List roles); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @HTTP( method = "DELETE", path = "admin/realms/{realmId}/users/{id}/role-mappings/realm", hasBody = true) + Call deleteRealmLevelRoleMappingsForUser(@Path("realmId") String realmId, @Path("id") String userId, + @Body List roles); + + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @POST("admin/realms/{realmId}/roles") + Call createRole(@Path("realmId") String realmId, @Body RoleRepresentation role); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @PUT("admin/realms/{realmId}/roles-by-id/{role-id}") + Call updateRole(@Path("realmId") String realmId, @Path("role-id") String roleId, @Body RoleRepresentation role); + + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("admin/realms/{realmId}/roles-by-id/{role-id}") + Call getRoleById(@Path("realmId") String realmId, @Path("role-id") String roleId); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("admin/realms/{realmId}/roles/{role-name}") + Call getRoleByName(@Path("realmId") String realmId, @Path("role-name") String roleName); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("admin/realms/{realmId}/roles") + Call> getAllRoles(@Path("realmId") String realmId, @Query("first") Integer first, + @Query("max") Integer max); + + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @DELETE("admin/realms/{realmId}/roles-by-id/{role-id}") + Call deleteRoleById(@Path("realmId") String realmId, @Path("role-id") String roleId); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @DELETE("admin/realms/{realmId}/roles/{role-name}") + Call deleteRoleByName(@Path("realmId") String realmId, @Path("role-name") String roleName); + + /* Keycloak composites */ + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("admin/realms/{realmId}/roles/{role-name}/composites") + Call> getRoleComposites(@Path("realmId") String realmId, @Path("role-name") String roleName); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @POST("admin/realms/{realmId}/roles/{role-name}/composites") + Call addComposites(@Path("realmId") String realmId, @Path("role-name") String roleName, @Body List roles); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @HTTP( method = "DELETE", path = "admin/realms/{realmId}/roles/{role-name}/composites", hasBody = true) + Call deleteComposites(@Path("realmId") String realmId, @Path("role-name") String roleName, @Body List roles); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("admin/realms/{realmId}/admin-events") + Call> getAdminEvents(@Path("realmId") String realmId, @Query("operationTypes") List operationTypes, + @Query("authRealm") String authRealm, @Query("authClient") String authClient, + @Query("authUser") String authUser, @Query("authIpAddress") String authIpAddress, + @Query("resourcePath") String resourcePath, @Query("dateFrom") String dateFrom, + @Query("dateTo") String dateTo, @Query("first") Integer first, @Query("max") Integer max); + + @Headers({"Accept: application/json", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @GET("admin/realms/{realmId}/events") + Call> getEvents(@Path("realmId") String realmId, @Query("type") List types, + @Query("client") String client, @Query("user") String user, + @Query("dateFrom") String dateFrom, @Query("dateTo") String dateTo, + @Query("ipAddress") String ipAddress, @Query("first") Integer first, + @Query("max") Integer max); + + /* Access token */ + + @Headers({"Accept: application/json", "Content-Type: application/x-www-form-urlencoded", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @POST("realms/{realmId}/protocol/openid-connect/token") + Call grantToken(@Path("realmId") String realmId, @Body RequestBody request); + + @Headers({"Accept: application/json", "Content-Type: application/x-www-form-urlencoded", "Cache-Control: no-store", "Cache-Control: no-cache"}) + @POST("realms/{realmId}/protocol/openid-connect/token/introspect") + Call introspectToken(@Path("realmId") String realmId, @Body RequestBody request); + +} diff --git a/client-heracles/pom.xml b/client-heracles/pom.xml new file mode 100644 index 00000000000..63276fcfd46 --- /dev/null +++ b/client-heracles/pom.xml @@ -0,0 +1,75 @@ + + + + + + apache-atlas + org.apache.atlas + 3.0.0-SNAPSHOT + + 4.0.0 + + client-heracles + + + 17 + 17 + + + + + org.keycloak + keycloak-core + ${keycloak-admin-client.version} + + + * + * + + + + + com.squareup.okhttp3 + okhttp + ${okhttp3.version} + + + com.squareup.retrofit2 + retrofit + ${retrofit.version} + + + com.squareup.retrofit2 + converter-jackson + ${retrofit.version} + + + com.squareup.okhttp3 + logging-interceptor + ${okhttp3.version} + + + org.apache.atlas + atlas-common + + + + \ No newline at end of file diff --git a/client-heracles/src/main/java/heracles/client/config/HeraclesConfigBuilder.java b/client-heracles/src/main/java/heracles/client/config/HeraclesConfigBuilder.java new file mode 100644 index 00000000000..863eec00218 --- /dev/null +++ b/client-heracles/src/main/java/heracles/client/config/HeraclesConfigBuilder.java @@ -0,0 +1,30 @@ +package main.java.heracles.client.config; + +public class HeraclesConfigBuilder { + + String authServerUrl; + String realmId; + String clientId; + String clientSecret; + String grantType; + + public String getAuthServerUrl() { + return authServerUrl; + } + + public String getRealmId() { + return realmId; + } + + public String getClientId() { + return clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public String getGrantType() { + return grantType; + } +} diff --git a/client/client-v1/pom.xml b/client/client-v1/pom.xml deleted file mode 100644 index 7d017cfa682..00000000000 --- a/client/client-v1/pom.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - atlas-client - org.apache.atlas - 3.0.0-SNAPSHOT - - 4.0.0 - - atlas-client-v1 - - - - org.apache.atlas - atlas-client-common - ${project.version} - - - org.apache.atlas - atlas-common - ${project.version} - - - diff --git a/client/client-v1/src/main/java/org/apache/atlas/AtlasAdminClient.java b/client/client-v1/src/main/java/org/apache/atlas/AtlasAdminClient.java deleted file mode 100644 index d22963d470c..00000000000 --- a/client/client-v1/src/main/java/org/apache/atlas/AtlasAdminClient.java +++ /dev/null @@ -1,174 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas; - -import org.apache.atlas.model.metrics.AtlasMetrics; -import org.apache.atlas.type.AtlasType; -import org.apache.atlas.utils.AuthenticationUtil; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.CommandLineParser; -import org.apache.commons.cli.GnuParser; -import org.apache.commons.cli.HelpFormatter; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; -import org.apache.commons.configuration.Configuration; - -import java.util.Arrays; - - -/** - * An application that allows users to run admin commands against an Atlas server. - * - * The application uses {@link AtlasClient} to send REST requests to the Atlas server. The details of connections - * and other configuration is specified in the Atlas properties file. - * Exit status of the application will be as follows: - *

  • 0: successful execution
  • - *
  • 1: error in options used for the application
  • - *
  • -1/255: application error
  • - */ -public class AtlasAdminClient { - - private static final Option STATUS = new Option("status", false, "Get the status of an atlas instance"); - private static final Option STATS = new Option("stats", false, "Get the metrics of an atlas instance"); - private static final Option CREDENTIALS = new Option("u", true, "Authorized atlas user credentials (:)"); - - private static final Options OPTIONS = new Options(); - - private static final int INVALID_OPTIONS_STATUS = 1; - private static final int PROGRAM_ERROR_STATUS = -1; - - static { - OPTIONS.addOption(STATUS); - OPTIONS.addOption(STATS); - OPTIONS.addOption(CREDENTIALS); - } - - public static void main(String[] args) throws AtlasException, ParseException { - AtlasAdminClient atlasAdminClient = new AtlasAdminClient(); - int result = atlasAdminClient.run(args); - System.exit(result); - } - - private int run(String[] args) throws AtlasException { - CommandLine commandLine = parseCommandLineOptions(args); - Configuration configuration = ApplicationProperties.get(); - String[] atlasServerUri = configuration.getStringArray(AtlasConstants.ATLAS_REST_ADDRESS_KEY); - - if (atlasServerUri == null || atlasServerUri.length == 0) { - atlasServerUri = new String[] { AtlasConstants.DEFAULT_ATLAS_REST_ADDRESS }; - } - - return handleCommand(commandLine, atlasServerUri); - } - - private int handleCommand(CommandLine commandLine, String[] atlasServerUri) throws AtlasException { - AtlasClient atlasClient; - - String[] providedUserPassword = getUserPassword(commandLine); - - int cmdStatus = PROGRAM_ERROR_STATUS; - if (commandLine.hasOption(STATUS.getOpt())) { - atlasClient = initAtlasClient(atlasServerUri, providedUserPassword); // Status is open API, no auth needed - try { - System.out.println(atlasClient.getAdminStatus()); - cmdStatus = 0; - } catch (AtlasServiceException e) { - System.err.println("Could not retrieve status of the server at " + Arrays.toString(atlasServerUri)); - printStandardHttpErrorDetails(e); - } - } else if (commandLine.hasOption(STATS.getOpt())) { - atlasClient = initAtlasClient(atlasServerUri, providedUserPassword); // Stats/metrics is open API, no auth needed - try { - AtlasMetrics atlasMetrics = atlasClient.getAtlasMetrics(); - String json = AtlasType.toJson(atlasMetrics); - System.out.println(json); - cmdStatus = 0; - } catch (AtlasServiceException e) { - System.err.println("Could not retrieve metrics of the server at " + Arrays.toString(atlasServerUri)); - printStandardHttpErrorDetails(e); - } - } else { - System.err.println("Unsupported option. Refer to usage for valid options."); - printUsage(); - } - - return cmdStatus; - } - - private String[] getUserPassword(CommandLine commandLine) { - String[] basicAuthUsernamePassword = null; - - // Parse the provided username password - if (commandLine.hasOption(CREDENTIALS.getOpt())) { - String value = commandLine.getOptionValue(CREDENTIALS.getOpt()); - if (value != null) { - basicAuthUsernamePassword = value.split(":"); - } - } - if (basicAuthUsernamePassword == null || basicAuthUsernamePassword.length != 2) { - System.err.println("Invalid credentials. Format: :"); - } - return basicAuthUsernamePassword; - } - - private AtlasClient initAtlasClient(final String[] atlasServerUri, final String[] providedUserNamePassword) throws AtlasException { - AtlasClient atlasClient; - - if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { - if (providedUserNamePassword == null || providedUserNamePassword.length < 2) { - atlasClient = new AtlasClient(atlasServerUri, AuthenticationUtil.getBasicAuthenticationInput()); - } else { - atlasClient = new AtlasClient(atlasServerUri, providedUserNamePassword); - } - } else { - atlasClient = new AtlasClient(atlasServerUri); - } - return atlasClient; - } - - private void printStandardHttpErrorDetails(AtlasServiceException e) { - System.err.println("Error details: "); - System.err.println("HTTP Status: " + e.getStatus().getStatusCode() + "," - + e.getStatus().getReasonPhrase()); - System.err.println("Exception message: " + e.getMessage()); - } - - private CommandLine parseCommandLineOptions(String[] args) { - if (args.length == 0) { - printUsage(); - } - CommandLineParser parser = new GnuParser(); - CommandLine commandLine = null; - try { - commandLine = parser.parse(OPTIONS, args); - } catch (ParseException e) { - System.err.println("Could not parse command line options. " + e.getMessage()); - printUsage(); - } - return commandLine; - } - - private void printUsage() { - HelpFormatter helpFormatter = new HelpFormatter(); - helpFormatter.printHelp("atlas_admin.py", OPTIONS); - System.exit(AtlasAdminClient.INVALID_OPTIONS_STATUS); - } - -} diff --git a/client/client-v1/src/main/java/org/apache/atlas/AtlasClient.java b/client/client-v1/src/main/java/org/apache/atlas/AtlasClient.java deleted file mode 100644 index c132afc487c..00000000000 --- a/client/client-v1/src/main/java/org/apache/atlas/AtlasClient.java +++ /dev/null @@ -1,938 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.annotations.VisibleForTesting; -import com.sun.jersey.api.client.WebResource; -import org.apache.atlas.model.legacy.EntityResult; -import org.apache.atlas.v1.model.instance.Referenceable; -import org.apache.atlas.v1.model.instance.Struct; -import org.apache.atlas.v1.model.typedef.AttributeDefinition; -import org.apache.atlas.v1.model.typedef.TraitTypeDefinition; -import org.apache.atlas.v1.model.typedef.TypesDef; -import org.apache.atlas.v1.typesystem.types.utils.TypesUtil; -import org.apache.atlas.utils.AtlasJson; -import org.apache.atlas.type.AtlasType; -import org.apache.atlas.typesystem.types.DataTypes; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.lang.StringUtils; -import org.apache.hadoop.security.UserGroupInformation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.ws.rs.HttpMethod; -import javax.ws.rs.core.Cookie; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; -import java.io.IOException; -import java.util.*; - -/** - * Client for metadata. - */ -@Deprecated -public class AtlasClient extends AtlasBaseClient { - private static final Logger LOG = LoggerFactory.getLogger(AtlasClient.class); - - public static final String TYPE = "type"; - public static final String TYPENAME = "typeName"; - public static final String GUID = "GUID"; - public static final String ENTITIES = "entities"; - public static final String GUID_ASSIGNMENTS = "guidAssignments"; - - public static final String DEFINITION = "definition"; - public static final String ERROR = "error"; - public static final String STACKTRACE = "stackTrace"; - public static final String REQUEST_ID = "requestId"; - public static final String RESULTS = "results"; - public static final String COUNT = "count"; - public static final String ROWS = "rows"; - public static final String DATATYPE = "dataType"; - public static final String STATUS = "Status"; - - public static final String EVENTS = "events"; - public static final String START_KEY = "startKey"; - public static final String NUM_RESULTS = "count"; - - public static final String URI_ENTITY = "entities"; - public static final String URI_ENTITY_AUDIT = "audit"; - public static final String URI_SEARCH = "discovery/search"; - public static final String URI_NAME_LINEAGE = "lineage/hive/table"; - public static final String URI_LINEAGE = "lineage/"; - public static final String URI_TRAITS = "traits"; - public static final String TRAITS = "traits"; - public static final String TRAIT_DEFINITIONS = "traitDefinitions"; - - - public static final String QUERY_TYPE = "queryType"; - public static final String ATTRIBUTE_NAME = "property"; - public static final String ATTRIBUTE_VALUE = "value"; - - public static final String SUPERTYPE = "supertype"; - public static final String NOT_SUPERTYPE = "notsupertype"; - - public static final String ASSET_TYPE = "Asset"; - public static final String NAME = "name"; - public static final String DESCRIPTION = "description"; - public static final String OWNER = "owner"; - public static final String CREATE_TIME = "createTime"; - - public static final String INFRASTRUCTURE_SUPER_TYPE = "Infrastructure"; - public static final String DATA_SET_SUPER_TYPE = "DataSet"; - public static final String PROCESS_SUPER_TYPE = "Process"; - public static final String PROCESS_ATTRIBUTE_INPUTS = "inputs"; - public static final String PROCESS_ATTRIBUTE_OUTPUTS = "outputs"; - - public static final String REFERENCEABLE_SUPER_TYPE = "Referenceable"; - public static final String QUALIFIED_NAME = "qualifiedName"; - public static final String REFERENCEABLE_ATTRIBUTE_NAME = QUALIFIED_NAME; - - public static final String UNKNOWN_STATUS = "Unknown status"; - - /** - * Constructor for AtlasClient with cookie params as header - * @param baseUrl - * @param cookieName - * @param value - * @param path - * @param domain - */ - - public AtlasClient(String[] baseUrl, String cookieName, String value, String path, String domain) { - super(baseUrl, new Cookie(cookieName, value, path, domain)); - } - - /** - * Constructor for AtlasClient with cookie as header - * @param baseUrl - * @param cookie - */ - - public AtlasClient(String[] baseUrl, Cookie cookie) { - super(baseUrl, cookie); - } - - - // New constructor for Basic auth - public AtlasClient(String[] baseUrl, String[] basicAuthUserNamePassword) { - super(baseUrl, basicAuthUserNamePassword); - } - - /** - * Create a new Atlas client. - * @param baseUrls A list of URLs that point to an ensemble of Atlas servers working in - * High Availability mode. The client will automatically determine the - * active instance on startup and also when there is a scenario of - * failover. - */ - public AtlasClient(String... baseUrls) throws AtlasException { - this(getCurrentUGI(), baseUrls); - } - - /** - * Create a new Atlas client. - * @param ugi UserGroupInformation - * @param doAsUser - * @param baseUrls A list of URLs that point to an ensemble of Atlas servers working in - * High Availability mode. The client will automatically determine the - * active instance on startup and also when there is a scenario of - * failover. - */ - public AtlasClient(UserGroupInformation ugi, String doAsUser, String... baseUrls) { - initializeState(baseUrls, ugi, doAsUser); - } - - private AtlasClient(UserGroupInformation ugi, String[] baseUrls) { - this(ugi, ugi.getShortUserName(), baseUrls); - } - - //Used by LocalAtlasClient - protected AtlasClient() { - //Do nothing - } - - @VisibleForTesting - public AtlasClient(Configuration configuration, String[] baseUrl, String[] basicAuthUserNamePassword) { - super(configuration, baseUrl, basicAuthUserNamePassword); - } - - @Override - protected API formatPathParameters(final API api, final String... params) { - return new API(String.format(api.getPath(), params), api.getMethod(), api.getExpectedStatus()); - } - - @VisibleForTesting - public AtlasClient(Configuration configuration, String... baseUrls) throws AtlasException { - initializeState(configuration, baseUrls, getCurrentUGI(), getCurrentUGI().getShortUserName()); - } - - @VisibleForTesting - AtlasClient(WebResource service, Configuration configuration) { - super(service, configuration); - } - - public WebResource getResource() { - return service; - } - - public static class API_V1 extends API { - //Admin operations - public static final API_V1 VERSION = new API_V1(BASE_URI + ADMIN_VERSION, HttpMethod.GET, Response.Status.OK); - public static final API_V1 STATUS = new API_V1(BASE_URI + ADMIN_STATUS, HttpMethod.GET, Response.Status.OK); - - //Type operations - public static final API_V1 CREATE_TYPE = new API_V1(BASE_URI + TYPES, HttpMethod.POST, Response.Status.CREATED); - public static final API_V1 UPDATE_TYPE = new API_V1(BASE_URI + TYPES, HttpMethod.PUT, Response.Status.OK); - public static final API_V1 GET_TYPE = new API_V1(BASE_URI + TYPES, HttpMethod.GET, Response.Status.OK); - public static final API_V1 LIST_TYPES = new API_V1(BASE_URI + TYPES, HttpMethod.GET, Response.Status.OK); - public static final API_V1 LIST_TRAIT_TYPES = new API_V1(BASE_URI + TYPES + "?type=trait", HttpMethod.GET, Response.Status.OK); - - //Entity operations - public static final API_V1 CREATE_ENTITY = new API_V1(BASE_URI + URI_ENTITY, HttpMethod.POST, Response.Status.CREATED); - public static final API_V1 GET_ENTITY = new API_V1(BASE_URI + URI_ENTITY, HttpMethod.GET, Response.Status.OK); - public static final API_V1 UPDATE_ENTITY = new API_V1(BASE_URI + URI_ENTITY, HttpMethod.PUT, Response.Status.OK); - public static final API_V1 UPDATE_ENTITY_PARTIAL = new API_V1(BASE_URI + URI_ENTITY, HttpMethod.POST, Response.Status.OK); - public static final API_V1 LIST_ENTITIES = new API_V1(BASE_URI + URI_ENTITY, HttpMethod.GET, Response.Status.OK); - public static final API_V1 DELETE_ENTITIES = new API_V1(BASE_URI + URI_ENTITY, HttpMethod.DELETE, Response.Status.OK); - public static final API_V1 DELETE_ENTITY = new API_V1(BASE_URI + URI_ENTITY, HttpMethod.DELETE, Response.Status.OK); - - //audit operation - public static final API_V1 LIST_ENTITY_AUDIT = new API_V1(BASE_URI + URI_ENTITY, HttpMethod.GET, Response.Status.OK); - - //Trait operations - public static final API_V1 ADD_TRAITS = new API_V1(BASE_URI + URI_ENTITY, HttpMethod.POST, Response.Status.CREATED); - public static final API_V1 DELETE_TRAITS = new API_V1(BASE_URI + URI_ENTITY, HttpMethod.DELETE, Response.Status.OK); - public static final API_V1 LIST_TRAITS = new API_V1(BASE_URI + URI_ENTITY, HttpMethod.GET, Response.Status.OK); - public static final API_V1 GET_ALL_TRAIT_DEFINITIONS = new API_V1(BASE_URI + URI_ENTITY, HttpMethod.GET, Response.Status.OK); - public static final API_V1 GET_TRAIT_DEFINITION = new API_V1(BASE_URI + URI_ENTITY, HttpMethod.GET, Response.Status.OK); - - //Search operations - public static final API_V1 SEARCH = new API_V1(BASE_URI + URI_SEARCH, HttpMethod.GET, Response.Status.OK); - public static final API_V1 SEARCH_DSL = new API_V1(BASE_URI + URI_SEARCH + "/dsl", HttpMethod.GET, Response.Status.OK); - public static final API_V1 SEARCH_FULL_TEXT = new API_V1(BASE_URI + URI_SEARCH + "/fulltext", HttpMethod.GET, Response.Status.OK); - public static final API_V1 GREMLIN_SEARCH = new API_V1(BASE_URI + URI_SEARCH + "/gremlin", HttpMethod.GET, Response.Status.OK); - - //Lineage operations based on dataset name - public static final API_V1 NAME_LINEAGE_INPUTS_GRAPH = new API_V1(BASE_URI + URI_NAME_LINEAGE, HttpMethod.GET, Response.Status.OK); - public static final API_V1 NAME_LINEAGE_OUTPUTS_GRAPH = new API_V1(BASE_URI + URI_NAME_LINEAGE, HttpMethod.GET, Response.Status.OK); - public static final API_V1 NAME_LINEAGE_SCHEMA = new API_V1(BASE_URI + URI_NAME_LINEAGE, HttpMethod.GET, Response.Status.OK); - - //Lineage operations based on entity id of the dataset - public static final API_V1 LINEAGE_INPUTS_GRAPH = new API_V1(BASE_URI + URI_LINEAGE, HttpMethod.GET, Response.Status.OK); - public static final API_V1 LINEAGE_OUTPUTS_GRAPH = new API_V1(BASE_URI + URI_LINEAGE, HttpMethod.GET, Response.Status.OK); - public static final API_V1 LINEAGE_SCHEMA = new API_V1(BASE_URI + URI_LINEAGE, HttpMethod.GET, Response.Status.OK); - - private API_V1(String path, String method, Response.Status status) { - super(path, method, status); - } - } - - /** - * Register the given type(meta model) - * @param typeAsJson type definition a jaon - * @return result json object - * @throws AtlasServiceException - */ - public List createType(String typeAsJson) throws AtlasServiceException { - LOG.debug("Creating type definition: {}", typeAsJson); - ObjectNode response = callAPIWithBody(API_V1.CREATE_TYPE, typeAsJson); - List results = extractResults(response, AtlasClient.TYPES, new ExtractOperation() { - @Override - String extractElement(ObjectNode element) { - return element.get(AtlasClient.NAME).asText(); - } - }); - LOG.debug("Create type definition returned results: {}", results); - return results; - } - - /** - * Register the given type(meta model) - * @param typeDef type definition - * @return result json object - * @throws AtlasServiceException - */ - public List createType(TypesDef typeDef) throws AtlasServiceException { - return createType(AtlasType.toV1Json(typeDef)); - } - - /** - * Creates trait type with specifiedName, superTraits and attributes - * @param traitName the name of the trait type - * @param superTraits the list of super traits from which this trait type inherits attributes - * @param attributeDefinitions the list of attributes of the trait type - * @return the list of types created - * @throws AtlasServiceException - */ - public List createTraitType(String traitName, Set superTraits, AttributeDefinition... attributeDefinitions) throws AtlasServiceException { - TraitTypeDefinition piiTrait = TypesUtil.createTraitTypeDef(traitName, null, superTraits, Arrays.asList(attributeDefinitions)); - TypesDef typesDef = new TypesDef(Collections.emptyList(), Collections.emptyList(), Collections.singletonList(piiTrait), - Collections.emptyList()); - - LOG.debug("Creating trait type {} {}", traitName, AtlasType.toV1Json(piiTrait)); - - return createType(AtlasType.toV1Json(typesDef)); - } - - /** - * Creates simple trait type with specifiedName with no superTraits or attributes - * @param traitName the name of the trait type - * @return the list of types created - * @throws AtlasServiceException - */ - public List createTraitType(String traitName) throws AtlasServiceException { - return createTraitType(traitName, null); - } - - /** - * Register the given type(meta model) - * @param typeAsJson type definition a jaon - * @return result json object - * @throws AtlasServiceException - */ - public List updateType(String typeAsJson) throws AtlasServiceException { - LOG.debug("Updating type definition: {}", typeAsJson); - ObjectNode response = callAPIWithBody(API_V1.UPDATE_TYPE, typeAsJson); - List results = extractResults(response, AtlasClient.TYPES, new ExtractOperation() { - @Override - String extractElement(ObjectNode element) { - return element.get(AtlasClient.NAME).asText(); - } - }); - LOG.debug("Update type definition returned results: {}", results); - return results; - } - - /** - * Register the given type(meta model) - * @param typeDef type definition - * @return result json object - * @throws AtlasServiceException - */ - public List updateType(TypesDef typeDef) throws AtlasServiceException { - return updateType(AtlasType.toV1Json(typeDef)); - } - - /** - * Returns all type names in the system - * @return list of type names - * @throws AtlasServiceException - */ - public List listTypes() throws AtlasServiceException { - final ObjectNode jsonResponse = callAPIWithQueryParams(API_V1.LIST_TYPES, null); - return extractStringList(jsonResponse); - } - - /** - * Returns all type names with the given category - * @param category - * @return list of type names - * @throws AtlasServiceException - */ - public List listTypes(final DataTypes.TypeCategory category) throws AtlasServiceException { - final API api = API_V1.LIST_TYPES; - ObjectNode response = callAPIWithRetries(api, null, new ResourceCreator() { - @Override - public WebResource createResource() { - WebResource resource = getResource(api.getNormalizedPath()); - resource = resource.queryParam(TYPE, category.name()); - return resource; - } - }); - return extractResults(response, AtlasClient.RESULTS, new ExtractOperation()); - } - - /** - * Return the list of type names in the type system which match the specified filter. - * - * @param category returns types whose category is the given typeCategory - * @param superType returns types which contain the given supertype - * @param notSupertype returns types which do not contain the given supertype - * - * Its possible to specify combination of these filters in one request and the conditions are combined with AND - * For example, typeCategory = TRAIT && supertype contains 'X' && supertype !contains 'Y' - * If there is no filter, all the types are returned - * @return list of type names - */ - public List listTypes(final DataTypes.TypeCategory category, final String superType, - final String notSupertype) throws AtlasServiceException { - final API api = API_V1.LIST_TYPES; - ObjectNode response = callAPIWithRetries(api, null, new ResourceCreator() { - @Override - public WebResource createResource() { - WebResource resource = getResource(api); - resource = resource.queryParam(TYPE, category.name()); - resource = resource.queryParam(SUPERTYPE, superType); - resource = resource.queryParam(NOT_SUPERTYPE, notSupertype); - return resource; - } - }); - return extractStringList(response); - } - - public TypesDef getType(String typeName) throws AtlasServiceException { - ObjectNode response = callAPIWithBodyAndParams(API_V1.GET_TYPE, null, typeName); - String typeJson = AtlasType.toJson(response.get(DEFINITION)); - return AtlasType.fromV1Json(typeJson, TypesDef.class); - } - - /** - * Create the given entity - * @param entities entity(type instance) as json - * @return json array of guids - * @throws AtlasServiceException - */ - protected List createEntity(ArrayNode entities) throws AtlasServiceException { - LOG.debug("Creating entities: {}", entities); - ObjectNode response = callAPIWithBody(API_V1.CREATE_ENTITY, entities.toString()); - List results = extractEntityResult(response).getCreatedEntities(); - LOG.debug("Create entities returned results: {}", results); - return results; - } - - protected EntityResult extractEntityResult(ObjectNode response) throws AtlasServiceException { - return EntityResult.fromString(response.toString()); - } - - /** - * Create the given entity - * @param entitiesAsJson entity(type instance) as json - * @return json array of guids - * @throws AtlasServiceException - */ - public List createEntity(String... entitiesAsJson) throws AtlasServiceException { - try { - return createEntity(AtlasJson.parseToV1ArrayNode(Arrays.asList(entitiesAsJson))); - } catch (IOException excp) { - throw new AtlasServiceException(excp); - } - } - - public List createEntity(Referenceable... entities) throws AtlasServiceException { - return createEntity(Arrays.asList(entities)); - } - - public List createEntity(Collection entities) throws AtlasServiceException { - ArrayNode entityArray = getEntitiesArray(entities); - return createEntity(entityArray); - } - - private ArrayNode getEntitiesArray(Collection entities) { - ArrayNode entityArray = AtlasJson.createV1ArrayNode(); - for (Referenceable entity : entities) { - entityArray.add(AtlasType.toV1Json(entity)); - } - return entityArray; - } - - /** - * Replaces entity definitions identified by their guid or unique attribute - * Updates properties set in the definition for the entity corresponding to guid - * @param entities entities to be updated - * @return json array of guids which were updated/created - * @throws AtlasServiceException - */ - public EntityResult updateEntities(Referenceable... entities) throws AtlasServiceException { - return updateEntities(Arrays.asList(entities)); - } - - protected EntityResult updateEntities(ArrayNode entities) throws AtlasServiceException { - LOG.debug("Updating entities: {}", entities); - ObjectNode response = callAPIWithBody(API_V1.UPDATE_ENTITY, entities.toString()); - EntityResult results = extractEntityResult(response); - LOG.debug("Update entities returned results: {}", results); - return results; - } - - public EntityResult updateEntities(Collection entities) throws AtlasServiceException { - ArrayNode entitiesArray = getEntitiesArray(entities); - return updateEntities(entitiesArray); - } - - /** - * Supports Partial updates - * Updates property for the entity corresponding to guid - * @param guid guid - * @param attribute property key - * @param value property value - */ - public EntityResult updateEntityAttribute(final String guid, final String attribute, String value) - throws AtlasServiceException { - LOG.debug("Updating entity id: {}, attribute name: {}, attribute value: {}", guid, attribute, value); - final API api = API_V1.UPDATE_ENTITY_PARTIAL; - ObjectNode response = callAPIWithRetries(api, value, new ResourceCreator() { - @Override - public WebResource createResource() { - WebResource resource = getResource(api, guid); - resource = resource.queryParam(ATTRIBUTE_NAME, attribute); - return resource; - } - }); - return extractEntityResult(response); - } - - /** - * Supports Partial updates - * Updates properties set in the definition for the entity corresponding to guid - * @param guid guid - * @param entity entity definition - */ - public EntityResult updateEntity(String guid, Referenceable entity) throws AtlasServiceException { - String entityJson = AtlasType.toV1Json(entity); - LOG.debug("Updating entity id {} with {}", guid, entityJson); - ObjectNode response = callAPIWithBodyAndParams(API_V1.UPDATE_ENTITY_PARTIAL, entityJson, guid); - return extractEntityResult(response); - } - - /** - * Associate trait to an entity - * - * @param guid guid - * @param traitDefinition trait definition - */ - public void addTrait(String guid, Struct traitDefinition) throws AtlasServiceException { - String traitJson = AtlasType.toV1Json(traitDefinition); - LOG.debug("Adding trait to entity with id {} {}", guid, traitJson); - callAPIWithBodyAndParams(API_V1.ADD_TRAITS, traitJson, guid, URI_TRAITS); - } - - /** - * Delete a trait from the given entity - * @param guid guid of the entity - * @param traitName trait to be deleted - * @throws AtlasServiceException - */ - public void deleteTrait(String guid, String traitName) throws AtlasServiceException { - callAPIWithBodyAndParams(API_V1.DELETE_TRAITS, null, guid, TRAITS, traitName); - } - - /** - * Supports Partial updates - * Updates properties set in the definition for the entity corresponding to guid - * @param entityType Type of the entity being updated - * @param uniqueAttributeName Attribute Name that uniquely identifies the entity - * @param uniqueAttributeValue Attribute Value that uniquely identifies the entity - * @param entity entity definition - */ - public EntityResult updateEntity(final String entityType, final String uniqueAttributeName, - final String uniqueAttributeValue, - Referenceable entity) throws AtlasServiceException { - final API api = API_V1.UPDATE_ENTITY_PARTIAL; - String entityJson = AtlasType.toV1Json(entity); - LOG.debug("Updating entity type: {}, attributeName: {}, attributeValue: {}, entity: {}", entityType, - uniqueAttributeName, uniqueAttributeValue, entityJson); - ObjectNode response = callAPIWithRetries(api, entityJson, new ResourceCreator() { - @Override - public WebResource createResource() { - WebResource resource = getResource(api, QUALIFIED_NAME); - resource = resource.queryParam(TYPE, entityType); - resource = resource.queryParam(ATTRIBUTE_NAME, uniqueAttributeName); - resource = resource.queryParam(ATTRIBUTE_VALUE, uniqueAttributeValue); - return resource; - } - }); - EntityResult result = extractEntityResult(response); - LOG.debug("Update entity returned result: {}", result); - return result; - } - - protected String getString(ObjectNode jsonObject, String parameter) throws AtlasServiceException { - return jsonObject.get(parameter).asText(); - } - - /** - * Delete the specified entities from the repository - * - * @param guids guids of entities to delete - * @return List of entity ids updated/deleted - * @throws AtlasServiceException - */ - public EntityResult deleteEntities(final String... guids) throws AtlasServiceException { - LOG.debug("Deleting entities: {}", guids); - final API api = API_V1.DELETE_ENTITIES; - ObjectNode jsonResponse = callAPIWithRetries(api, null, new ResourceCreator() { - @Override - public WebResource createResource() { - WebResource resource = getResource(api); - for (String guid : guids) { - resource = resource.queryParam(GUID.toLowerCase(), guid); - } - return resource; - } - }); - EntityResult results = extractEntityResult(jsonResponse); - LOG.debug("Delete entities returned results: {}", results); - return results; - } - - /** - * Supports Deletion of an entity identified by its unique attribute value - * @param entityType Type of the entity being deleted - * @param uniqueAttributeName Attribute Name that uniquely identifies the entity - * @param uniqueAttributeValue Attribute Value that uniquely identifies the entity - * @return List of entity ids updated/deleted(including composite references from that entity) - */ - public EntityResult deleteEntity(String entityType, String uniqueAttributeName, String uniqueAttributeValue) - throws AtlasServiceException { - LOG.debug("Deleting entity type: {}, attributeName: {}, attributeValue: {}", entityType, uniqueAttributeName, - uniqueAttributeValue); - API api = API_V1.DELETE_ENTITIES; - WebResource resource = getResource(api); - resource = resource.queryParam(TYPE, entityType); - resource = resource.queryParam(ATTRIBUTE_NAME, uniqueAttributeName); - resource = resource.queryParam(ATTRIBUTE_VALUE, uniqueAttributeValue); - ObjectNode jsonResponse = callAPIWithResource(api, resource); - EntityResult results = extractEntityResult(jsonResponse); - LOG.debug("Delete entities returned results: {}", results); - return results; - } - - /** - * Get an entity given the entity id - * @param guid entity id - * @return result object - * @throws AtlasServiceException - */ - public Referenceable getEntity(String guid) throws AtlasServiceException { - ObjectNode jsonResponse = callAPIWithBodyAndParams(API_V1.GET_ENTITY, null, guid); - String entityInstanceDefinition = AtlasType.toJson(jsonResponse.get(AtlasClient.DEFINITION)); - return AtlasType.fromV1Json(entityInstanceDefinition, Referenceable.class); - } - - public static String toString(ArrayNode jsonArray) { - ArrayList resultsList = new ArrayList<>(); - for (int index = 0; index < jsonArray.size(); index++) { - resultsList.add(jsonArray.get(index).asText()); - } - return StringUtils.join(resultsList, ","); - } - - /** - * Get an entity given the entity id - * @param entityType entity type name - * @param attribute qualified name of the entity - * @param value - * @return result object - * @throws AtlasServiceException - */ - public Referenceable getEntity(final String entityType, final String attribute, final String value) - throws AtlasServiceException { - final API api = API_V1.GET_ENTITY; - ObjectNode jsonResponse = callAPIWithRetries(api, null, new ResourceCreator() { - @Override - public WebResource createResource() { - WebResource resource = getResource(api); - resource = resource.queryParam(TYPE, entityType); - resource = resource.queryParam(ATTRIBUTE_NAME, attribute); - resource = resource.queryParam(ATTRIBUTE_VALUE, value); - return resource; - } - }); - String entityInstanceDefinition = AtlasType.toJson(jsonResponse.get(AtlasClient.DEFINITION)); - return AtlasType.fromV1Json(entityInstanceDefinition, Referenceable.class); - } - - /** - * List entities for a given entity type - * @param entityType - * @return - * @throws AtlasServiceException - */ - public List listEntities(final String entityType) throws AtlasServiceException { - ObjectNode jsonResponse = callAPIWithRetries(API_V1.LIST_ENTITIES, null, new ResourceCreator() { - @Override - public WebResource createResource() { - WebResource resource = getResource(API_V1.LIST_ENTITIES); - resource = resource.queryParam(TYPE, entityType); - return resource; - } - }); - return extractStringList(jsonResponse); - } - - /** - * List traits for a given entity identified by its GUID - * @param guid GUID of the entity - * @return List - traitnames associated with entity - * @throws AtlasServiceException - */ - public List listTraits(final String guid) throws AtlasServiceException { - ObjectNode jsonResponse = callAPIWithBodyAndParams(API_V1.LIST_TRAITS, null, guid, URI_TRAITS); - return extractStringList(jsonResponse); - } - - /** - * Get all trait definitions for an entity - * @param guid GUID of the entity - * @return List trait definitions of the traits associated to the entity - * @throws AtlasServiceException - */ - public List listTraitDefinitions(final String guid) throws AtlasServiceException { - ObjectNode jsonResponse = callAPIWithBodyAndParams(API_V1.GET_ALL_TRAIT_DEFINITIONS, null, guid, TRAIT_DEFINITIONS); - List traitDefList = extractResults(jsonResponse, AtlasClient.RESULTS, new ExtractOperation()); - ArrayList traitStructList = new ArrayList<>(); - for (ObjectNode traitDef : traitDefList) { - Struct traitStruct = AtlasType.fromV1Json(traitDef.toString(), Struct.class); - traitStructList.add(traitStruct); - } - return traitStructList; - } - - /** - * Get trait definition for a given entity and traitname - * @param guid GUID of the entity - * @param traitName - * @return trait definition - * @throws AtlasServiceException - */ - public Struct getTraitDefinition(final String guid, final String traitName) throws AtlasServiceException { - ObjectNode jsonResponse = callAPIWithBodyAndParams(API_V1.GET_TRAIT_DEFINITION, null, guid, TRAIT_DEFINITIONS, traitName); - - return AtlasType.fromV1Json(AtlasType.toJson(jsonResponse.get(AtlasClient.RESULTS)), Struct.class); - } - - protected class ExtractOperation { - T extractElement(U element) { - return (T) element; - } - } - - protected List extractResults(ObjectNode jsonResponse, String key, ExtractOperation extractInterafce) - throws AtlasServiceException { - ArrayNode results = (ArrayNode)jsonResponse.get(key); - ArrayList resultsList = new ArrayList<>(); - for (int index = 0; index < results.size(); index++) { - Object element = results.get(index); - resultsList.add(extractInterafce.extractElement((U) element)); - } - return resultsList; - } - - /** - * Get the latest numResults entity audit events in decreasing order of timestamp for the given entity id - * @param entityId entity id - * @param numResults number of results to be returned - * @return list of audit events for the entity id - * @throws AtlasServiceException - */ - public List getEntityAuditEvents(String entityId, short numResults) - throws AtlasServiceException { - return getEntityAuditEvents(entityId, null, numResults); - } - - /** - * Get the entity audit events in decreasing order of timestamp for the given entity id - * @param entityId entity id - * @param startKey key for the first event to be returned, used for pagination - * @param numResults number of results to be returned - * @return list of audit events for the entity id - * @throws AtlasServiceException - */ - public List getEntityAuditEvents(String entityId, String startKey, short numResults) - throws AtlasServiceException { - WebResource resource = getResource(API_V1.LIST_ENTITY_AUDIT, entityId, URI_ENTITY_AUDIT); - if (StringUtils.isNotEmpty(startKey)) { - resource = resource.queryParam(START_KEY, startKey); - } - resource = resource.queryParam(NUM_RESULTS, String.valueOf(numResults)); - - ObjectNode jsonResponse = callAPIWithResource(API_V1.LIST_ENTITY_AUDIT, resource); - return extractResults(jsonResponse, AtlasClient.EVENTS, new ExtractOperation() { - @Override - EntityAuditEvent extractElement(ObjectNode element) { - return AtlasType.fromV1Json(element.toString(), EntityAuditEvent.class); - } - }); - - } - - /** - * Search using dsl/full text - * @param searchQuery - * @param limit number of rows to be returned in the result, used for pagination. maxlimit > limit > 0. -1 maps to atlas.search.defaultlimit property value - * @param offset offset to the results returned, used for pagination. offset >= 0. -1 maps to offset 0 - * @return Query results - * @throws AtlasServiceException - */ - public JsonNode search(final String searchQuery, final int limit, final int offset) throws AtlasServiceException { - final API api = API_V1.SEARCH; - ObjectNode result = callAPIWithRetries(api, null, new ResourceCreator() { - @Override - public WebResource createResource() { - WebResource resource = getResource(api); - resource = resource.queryParam(QUERY, searchQuery); - resource = resource.queryParam(LIMIT, String.valueOf(limit)); - resource = resource.queryParam(OFFSET, String.valueOf(offset)); - return resource; - } - }); - return result.get(RESULTS); - } - - /** - * Search given query DSL - * @param query DSL query - * @param limit number of rows to be returned in the result, used for pagination. maxlimit > limit > 0. -1 maps to atlas.search.defaultlimit property value - * @param offset offset to the results returned, used for pagination. offset >= 0. -1 maps to offset 0 - * @return result json object - * @throws AtlasServiceException - */ - public ArrayNode searchByDSL(final String query, final int limit, final int offset) throws AtlasServiceException { - LOG.debug("DSL query: {}", query); - final API api = API_V1.SEARCH_DSL; - ObjectNode response = callAPIWithRetries(api, null, new ResourceCreator() { - @Override - public WebResource createResource() { - WebResource resource = getResource(api); - resource = resource.queryParam(QUERY, query); - resource = resource.queryParam(LIMIT, String.valueOf(limit)); - resource = resource.queryParam(OFFSET, String.valueOf(offset)); - return resource; - } - }); - - JsonNode results = response.get(RESULTS); - - return (results.isNull()) ? AtlasJson.createV1ArrayNode(): (ArrayNode) response.get(RESULTS); - } - - /** - * Search given full text search - * @param query Query - * @param limit number of rows to be returned in the result, used for pagination. maxlimit > limit > 0. -1 maps to atlas.search.defaultlimit property value - * @param offset offset to the results returned, used for pagination. offset >= 0. -1 maps to offset 0 - * @return result json object - * @throws AtlasServiceException - */ - public ObjectNode searchByFullText(final String query, final int limit, final int offset) throws AtlasServiceException { - final API api = API_V1.SEARCH_FULL_TEXT; - return callAPIWithRetries(api, null, new ResourceCreator() { - @Override - public WebResource createResource() { - WebResource resource = getResource(api); - resource = resource.queryParam(QUERY, query); - resource = resource.queryParam(LIMIT, String.valueOf(limit)); - resource = resource.queryParam(OFFSET, String.valueOf(offset)); - return resource; - } - }); - } - - public ObjectNode getInputGraph(String datasetName) throws AtlasServiceException { - ObjectNode response = callAPIWithBodyAndParams(API_V1.NAME_LINEAGE_INPUTS_GRAPH, null, datasetName, "/inputs/graph"); - return (ObjectNode)response.get(AtlasClient.RESULTS); - } - - public ObjectNode getOutputGraph(String datasetName) throws AtlasServiceException { - ObjectNode response = callAPIWithBodyAndParams(API_V1.NAME_LINEAGE_OUTPUTS_GRAPH, null, datasetName, "/outputs/graph"); - return (ObjectNode)response.get(AtlasClient.RESULTS); - } - - public ObjectNode getInputGraphForEntity(String entityId) throws AtlasServiceException { - ObjectNode response = callAPIWithBodyAndParams(API_V1.LINEAGE_INPUTS_GRAPH, null, entityId, "/inputs/graph"); - return (ObjectNode)response.get(AtlasClient.RESULTS); - } - - public ObjectNode getOutputGraphForEntity(String datasetId) throws AtlasServiceException { - ObjectNode response = callAPIWithBodyAndParams(API_V1.LINEAGE_OUTPUTS_GRAPH, null, datasetId, "/outputs/graph"); - return (ObjectNode) response.get(AtlasClient.RESULTS); - } - - public ObjectNode getSchemaForEntity(String datasetId) throws AtlasServiceException { - ObjectNode response = callAPIWithBodyAndParams(API_V1.LINEAGE_OUTPUTS_GRAPH, null, datasetId, "/schema"); - return (ObjectNode) response.get(AtlasClient.RESULTS); - } - - private List extractStringList(ObjectNode response) { - List ret = new ArrayList<>(); - JsonNode results = (response != null) ? response.get(AtlasClient.RESULTS) : null; - - if (results != null && results instanceof ArrayNode) { - for (JsonNode node : results) { - ret.add(node.asText()); - } - } - - return ret; - } - - // Wrapper methods for compatibility - @VisibleForTesting - public ObjectNode callAPIWithResource(API api, WebResource resource) throws AtlasServiceException { - return callAPIWithResource(api, resource, null, ObjectNode.class); - } - - @VisibleForTesting - public ObjectNode callAPIWithResource(API_V1 apiV1, WebResource resource) throws AtlasServiceException { - return callAPIWithResource(apiV1, resource, null, ObjectNode.class); - } - - @VisibleForTesting - public WebResource getResource(API api, String... params) { - return getResource(api.getNormalizedPath(), params); - } - - @VisibleForTesting - public WebResource getResource(API_V1 apiV1, String... params) { - return getResource(apiV1.getNormalizedPath(), params); - } - - @VisibleForTesting - public ObjectNode callAPIWithBody(API api, Object requestObject) throws AtlasServiceException { - return callAPI(api, ObjectNode.class, requestObject, (String[]) null); - } - - @VisibleForTesting - public ObjectNode callAPIWithBody(API_V1 apiV1, Object requestObject) throws AtlasServiceException { - return callAPI(apiV1, ObjectNode.class, requestObject, (String[]) null); - } - - @VisibleForTesting - public ObjectNode callAPIWithBodyAndParams(API api, Object requestObject, String... params) throws AtlasServiceException { - return callAPI(api, ObjectNode.class, requestObject, params); - } - - @VisibleForTesting - public ObjectNode callAPIWithBodyAndParams(API_V1 apiV1, Object requestObject, String... params) throws AtlasServiceException { - return callAPI(apiV1, ObjectNode.class, requestObject, params); - } - - @VisibleForTesting - public ObjectNode callAPIWithQueryParams(API api, MultivaluedMap queryParams) throws AtlasServiceException { - return callAPI(api, ObjectNode.class, queryParams); - } - - @VisibleForTesting - public ObjectNode callAPIWithQueryParams(API_V1 apiV1, MultivaluedMap queryParams) throws AtlasServiceException { - return callAPI(apiV1, ObjectNode.class, queryParams); - } - - @VisibleForTesting - ObjectNode callAPIWithRetries(API api, Object requestObject, ResourceCreator resourceCreator) throws AtlasServiceException { - return super.callAPIWithRetries(api, requestObject, resourceCreator); - } - - @VisibleForTesting - ObjectNode callAPIWithRetries(API_V1 apiV1, Object requestObject, ResourceCreator resourceCreator) throws AtlasServiceException { - return super.callAPIWithRetries(apiV1, requestObject, resourceCreator); - } -} diff --git a/client/client-v1/src/main/java/org/apache/atlas/CreateUpdateEntitiesResult.java b/client/client-v1/src/main/java/org/apache/atlas/CreateUpdateEntitiesResult.java deleted file mode 100644 index 5e6d6db3ae7..00000000000 --- a/client/client-v1/src/main/java/org/apache/atlas/CreateUpdateEntitiesResult.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas; - -import org.apache.atlas.model.instance.GuidMapping; -import org.apache.atlas.model.legacy.EntityResult; -import org.apache.atlas.type.AtlasType; - -import java.util.Collections; -import java.util.List; - -/** - * Result from creating or updating entities. - */ -@Deprecated -public class CreateUpdateEntitiesResult { - - /** - * Guid mapping for the entities that were created/updated - */ - private GuidMapping guidMapping; - - /** - * Entity result - */ - private EntityResult entityResult; - - /** - * Gets the guid mapping - */ - public GuidMapping getGuidMapping() { - return guidMapping; - } - - /** - * Sets the guid mapping - */ - public void setGuidMapping(GuidMapping guidMapping) { - this.guidMapping = guidMapping; - } - - /** - * Gets the entity result - */ - public EntityResult getEntityResult() { - return entityResult; - } - - /** - * Sets the entity result - */ - public void setEntityResult(EntityResult entityResult) { - this.entityResult = entityResult; - } - - /** - * Deserializes the given json into an instance of - * CreateUpdateEntitiesResult. - * - * @param json - * the (unmodified) json that comes back from Atlas. - * @return - * @throws AtlasServiceException - */ - public static CreateUpdateEntitiesResult fromJson(String json) throws AtlasServiceException { - - GuidMapping guidMapping = AtlasType.fromJson(json, GuidMapping.class); - EntityResult entityResult = EntityResult.fromString(json); - CreateUpdateEntitiesResult result = new CreateUpdateEntitiesResult(); - result.setEntityResult(entityResult); - result.setGuidMapping(guidMapping); - return result; - } - - /** - * Convenience method to get the guids of the created entities from - * the EntityResult. - */ - public List getCreatedEntities() { - if(entityResult == null) { - return Collections.emptyList(); - } - return getEntityResult().getCreatedEntities(); - } - - /** - * Convenience method to get the guids of the updated entities from - * the EntityResult. - */ - public List getUpdatedEntities() { - if(entityResult == null) { - return Collections.emptyList(); - } - return getEntityResult().getUpdateEntities(); - } - - - /** - * Convenience method to get the guids of the deleted entities - * from the EntityResult. - */ - public List getDeletedEntities() { - if (entityResult == null) { - return Collections.emptyList(); - } - return getEntityResult().getDeletedEntities(); - } - -} diff --git a/client/client-v1/src/test/java/org/apache/atlas/AtlasClientTest.java b/client/client-v1/src/test/java/org/apache/atlas/AtlasClientTest.java deleted file mode 100644 index 067bfdf2874..00000000000 --- a/client/client-v1/src/test/java/org/apache/atlas/AtlasClientTest.java +++ /dev/null @@ -1,478 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 org.apache.atlas; - -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientHandlerException; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.WebResource; -import org.apache.atlas.model.legacy.EntityResult; -import org.apache.atlas.type.AtlasType; -import org.apache.atlas.v1.model.instance.Referenceable; -import org.apache.commons.configuration.Configuration; -import org.apache.hadoop.security.UserGroupInformation; -import org.mockito.Matchers; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import java.net.ConnectException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.List; - -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -public class AtlasClientTest { - - @Mock - private WebResource service; - @Mock - private WebResource.Builder resourceBuilderMock; - - @Mock - private Configuration configuration; - - @Mock - private Client client; - - @BeforeMethod - public void setup() { - MockitoAnnotations.initMocks(this); - } - - @Test - public void shouldVerifyServerIsReady() throws AtlasServiceException { - setupRetryParams(); - - AtlasClient atlasClient = new AtlasClient(service, configuration); - - WebResource.Builder builder = setupBuilder(AtlasClient.API_V1.VERSION, service); - ClientResponse response = mock(ClientResponse.class); - when(response.getStatus()).thenReturn(Response.Status.OK.getStatusCode()); - when(response.getEntity(String.class)).thenReturn("{\"Version\":\"version-rrelease\",\"Name\":\"apache-atlas\"," + - "\"Description\":\"Metadata Management and Data Governance Platform over Hadoop\"}"); - when(builder.method(AtlasClient.API_V1.VERSION.getMethod(), ClientResponse.class, null)).thenReturn(response); - - assertTrue(atlasClient.isServerReady()); - } - - @Test - public void testCreateEntity() throws Exception { - setupRetryParams(); - AtlasClient atlasClient = new AtlasClient(service, configuration); - - WebResource.Builder builder = setupBuilder(AtlasClient.API_V1.CREATE_ENTITY, service); - ClientResponse response = mock(ClientResponse.class); - when(response.getStatus()).thenReturn(Response.Status.CREATED.getStatusCode()); - - String jsonResponse = AtlasType.toV1Json(new EntityResult(Arrays.asList("id"), null, null)); - when(response.getEntity(String.class)).thenReturn(jsonResponse.toString()); - when(response.getLength()).thenReturn(jsonResponse.length()); - - String entityJson = AtlasType.toV1Json(new Referenceable("type")); - when(builder.method(anyString(), Matchers.any(), anyString())).thenReturn(response); - - List ids = atlasClient.createEntity(entityJson); - assertEquals(ids.size(), 1); - assertEquals(ids.get(0), "id"); - } - - private WebResource.Builder setupBuilder(AtlasClient.API_V1 api, WebResource webResource) { - when(webResource.path(api.getPath())).thenReturn(service); - when(webResource.path(api.getNormalizedPath())).thenReturn(service); - return getBuilder(service); - } - - @Test - public void shouldReturnFalseIfServerIsNotReady() throws AtlasServiceException { - setupRetryParams(); - AtlasClient atlasClient = new AtlasClient(service, configuration); - WebResource.Builder builder = setupBuilder(AtlasClient.API_V1.VERSION, service); - when(builder.method(AtlasClient.API_V1.VERSION.getMethod(), ClientResponse.class, null)).thenThrow( - new ClientHandlerException()); - assertFalse(atlasClient.isServerReady()); - } - - @Test - public void shouldReturnFalseIfServiceIsUnavailable() throws AtlasServiceException { - setupRetryParams(); - AtlasClient atlasClient = new AtlasClient(service, configuration); - WebResource.Builder builder = setupBuilder(AtlasClient.API_V1.VERSION, service); - ClientResponse response = mock(ClientResponse.class); - when(response.getStatus()).thenReturn(Response.Status.SERVICE_UNAVAILABLE.getStatusCode()); - when(response.getClientResponseStatus()).thenReturn(ClientResponse.Status.SERVICE_UNAVAILABLE); - - when(builder.method(AtlasClient.API_V1.VERSION.getMethod(), ClientResponse.class, null)).thenReturn(response); - - assertFalse(atlasClient.isServerReady()); - } - - @Test(expectedExceptions = AtlasServiceException.class) - public void shouldThrowErrorIfAnyResponseOtherThanServiceUnavailable() throws AtlasServiceException { - setupRetryParams(); - - AtlasClient atlasClient = new AtlasClient(service, configuration); - WebResource.Builder builder = setupBuilder(AtlasClient.API_V1.VERSION, service); - ClientResponse response = mock(ClientResponse.class); - when(response.getStatus()).thenReturn(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); - when(response.getClientResponseStatus()).thenReturn(ClientResponse.Status.INTERNAL_SERVER_ERROR); - - when(builder.method(AtlasClient.API_V1.VERSION.getMethod(), ClientResponse.class, null)).thenReturn(response); - - atlasClient.isServerReady(); - fail("Should throw exception"); - } - - @Test - public void shouldGetAdminStatus() throws AtlasServiceException { - setupRetryParams(); - - AtlasClient atlasClient = new AtlasClient(service, configuration); - - WebResource.Builder builder = setupBuilder(AtlasClient.API_V1.STATUS, service); - ClientResponse response = mock(ClientResponse.class); - when(response.getStatus()).thenReturn(Response.Status.OK.getStatusCode()); - String activeStatus = "{\"Status\":\"Active\"}"; - when(response.getEntity(String.class)).thenReturn(activeStatus); - when(response.getLength()).thenReturn(activeStatus.length()); - when(builder.method(AtlasClient.API_V1.STATUS.getMethod(), ClientResponse.class, null)).thenReturn(response); - -// Fix after AtlasBaseClient -// atlasClient.setService(); - - - String status = atlasClient.getAdminStatus(); - assertEquals(status, "Active"); - } - - @Test(expectedExceptions = AtlasServiceException.class) - public void shouldReturnStatusAsUnknownOnException() throws AtlasServiceException { - setupRetryParams(); - - AtlasClient atlasClient = new AtlasClient(service, configuration); - - WebResource.Builder builder = setupBuilder(AtlasClient.API_V1.STATUS, service); - ClientResponse response = mock(ClientResponse.class); - when(response.getStatus()).thenReturn(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); - when(response.getClientResponseStatus()).thenReturn(ClientResponse.Status.INTERNAL_SERVER_ERROR); - when(builder.method(AtlasClient.API_V1.STATUS.getMethod(), ClientResponse.class, null)).thenReturn(response); - - String status = atlasClient.getAdminStatus(); - fail("Should fail with AtlasServiceException"); - } - - @Test - public void shouldReturnStatusAsUnknownIfJSONIsInvalid() throws AtlasServiceException { - setupRetryParams(); - AtlasClient atlasClient = new AtlasClient(service, configuration); - - WebResource.Builder builder = setupBuilder(AtlasClient.API_V1.STATUS, service); - ClientResponse response = mock(ClientResponse.class); - when(response.getStatus()).thenReturn(Response.Status.OK.getStatusCode()); - when(response.getEntity(String.class)).thenReturn("{\"status\":\"Active\"}"); - when(builder.method(AtlasClient.API_V1.STATUS.getMethod(), ClientResponse.class, null)).thenReturn(response); - - String status = atlasClient.getAdminStatus(); - assertEquals(status, AtlasClient.UNKNOWN_STATUS); - } - - @Test - public void shouldReturnBaseURLAsPassedInURL() { - AtlasClient atlasClient = new AtlasClient(service, configuration); - - String serviceURL = atlasClient.determineActiveServiceURL(new String[]{"http://localhost:21000"}, client); - assertEquals(serviceURL, "http://localhost:21000"); - } - - @Test - public void shouldSelectActiveAmongMultipleServersIfHAIsEnabled() { - setupRetryParams(); - - when(client.resource(UriBuilder.fromUri("http://localhost:31000").build())).thenReturn(service); - when(client.resource(UriBuilder.fromUri("http://localhost:41000").build())).thenReturn(service); - WebResource.Builder builder = setupBuilder(AtlasClient.API_V1.STATUS, service); - ClientResponse firstResponse = mock(ClientResponse.class); - when(firstResponse.getStatus()).thenReturn(Response.Status.OK.getStatusCode()); - String passiveStatus = "{\"Status\":\"PASSIVE\"}"; - when(firstResponse.getEntity(String.class)).thenReturn(passiveStatus); - when(firstResponse.getLength()).thenReturn(passiveStatus.length()); - ClientResponse secondResponse = mock(ClientResponse.class); - when(secondResponse.getStatus()).thenReturn(Response.Status.OK.getStatusCode()); - String activeStatus = "{\"Status\":\"ACTIVE\"}"; - when(secondResponse.getEntity(String.class)).thenReturn(activeStatus); - when(secondResponse.getLength()).thenReturn(activeStatus.length()); - when(builder.method(AtlasClient.API_V1.STATUS.getMethod(), ClientResponse.class, null)). - thenReturn(firstResponse).thenReturn(firstResponse).thenReturn(firstResponse). - thenReturn(secondResponse); - - AtlasClient atlasClient = new AtlasClient(service, configuration); - - String serviceURL = atlasClient.determineActiveServiceURL( - new String[]{"http://localhost:31000", "http://localhost:41000"}, - client); - assertEquals(serviceURL, "http://localhost:41000"); - } - - @Test - public void shouldRetryUntilServiceBecomesActive() { - setupRetryParams(); - - when(client.resource(UriBuilder.fromUri("http://localhost:31000").build())).thenReturn(service); - WebResource.Builder builder = setupBuilder(AtlasClient.API_V1.STATUS, service); - ClientResponse response = mock(ClientResponse.class); - when(response.getStatus()).thenReturn(Response.Status.OK.getStatusCode()); - when(response.getEntity(String.class)).thenReturn("{\"Status\":\"BECOMING_ACTIVE\"}"); - ClientResponse nextResponse = mock(ClientResponse.class); - when(nextResponse.getStatus()).thenReturn(Response.Status.OK.getStatusCode()); - String activeStatus = "{\"Status\":\"ACTIVE\"}"; - when(response.getEntity(String.class)).thenReturn(activeStatus); - when(response.getLength()).thenReturn(activeStatus.length()); - when(builder.method(AtlasClient.API_V1.STATUS.getMethod(), ClientResponse.class, null)). - thenReturn(response).thenReturn(response).thenReturn(nextResponse); - - AtlasClient atlasClient = new AtlasClient(service, configuration); - - String serviceURL = atlasClient.determineActiveServiceURL( - new String[] {"http://localhost:31000","http://localhost:41000"}, - client); - assertEquals(serviceURL, "http://localhost:31000"); - } - - @Test - public void shouldRetryIfCannotConnectToServiceInitially() { - setupRetryParams(); - - when(client.resource(UriBuilder.fromUri("http://localhost:31000").build())).thenReturn(service); - WebResource.Builder builder = setupBuilder(AtlasClient.API_V1.STATUS, service); - ClientResponse response = mock(ClientResponse.class); - when(response.getStatus()).thenReturn(Response.Status.OK.getStatusCode()); - when(response.getEntity(String.class)).thenReturn("{\"Status\":\"BECOMING_ACTIVE\"}"); - ClientResponse nextResponse = mock(ClientResponse.class); - when(nextResponse.getStatus()).thenReturn(Response.Status.OK.getStatusCode()); - String activeStatus = "{\"Status\":\"ACTIVE\"}"; - when(response.getEntity(String.class)).thenReturn(activeStatus); - when(response.getLength()).thenReturn(activeStatus.length()); - when(builder.method(AtlasClient.API_V1.STATUS.getMethod(), ClientResponse.class, null)). - thenThrow(new ClientHandlerException("Simulating connection exception")). - thenReturn(response). - thenReturn(nextResponse); - - AtlasClient atlasClient = new AtlasClient(service, configuration); - atlasClient.setService(service); - atlasClient.setConfiguration(configuration); - - String serviceURL = atlasClient.determineActiveServiceURL( - new String[] {"http://localhost:31000","http://localhost:41000"}, - client); - assertEquals(serviceURL, "http://localhost:31000"); - } - - @Test(expectedExceptions = IllegalArgumentException.class) - public void shouldThrowExceptionIfActiveServerIsNotFound() { - setupRetryParams(); - - when(client.resource(UriBuilder.fromUri("http://localhost:31000").build())).thenReturn(service); - WebResource.Builder builder = setupBuilder(AtlasClient.API_V1.STATUS, service); - ClientResponse response = mock(ClientResponse.class); - when(response.getStatus()).thenReturn(Response.Status.OK.getStatusCode()); - when(response.getEntity(String.class)).thenReturn("{\"Status\":\"BECOMING_ACTIVE\"}"); - when(builder.method(AtlasClient.API_V1.STATUS.getMethod(), ClientResponse.class, null)). - thenThrow(new ClientHandlerException("Simulating connection exception")). - thenReturn(response). - thenReturn(response); - - AtlasClient atlasClient = new AtlasClient(service, configuration); - - String serviceURL = atlasClient.determineActiveServiceURL( - new String[] {"http://localhost:31000","http://localhost:41000"}, - client); - assertNull(serviceURL); - } - - @Test - public void shouldRetryAPICallsOnClientHandlerException() throws AtlasServiceException, URISyntaxException { - setupRetryParams(); - - ResourceCreator resourceCreator = mock(ResourceCreator.class); - WebResource resourceObject = mock(WebResource.class); - when(resourceObject.getURI()). - thenReturn(new URI("http://localhost:31000/api/atlas/types")). - thenReturn(new URI("http://localhost:41000/api/atlas/types")). - thenReturn(new URI("http://localhost:41000/api/atlas/types")); - - WebResource.Builder builder = getBuilder(resourceObject); - - ClientResponse response = mock(ClientResponse.class); - when(response.getStatus()).thenReturn(Response.Status.OK.getStatusCode()); - String activeStatus = "{\"Status\":\"ACTIVE\"}"; - when(response.getEntity(String.class)).thenReturn(activeStatus); - when(response.getLength()).thenReturn(activeStatus.length()); - - when(builder.method(AtlasClient.API_V1.LIST_TYPES.getMethod(), ClientResponse.class, null)). - thenThrow(new ClientHandlerException("simulating exception in calling API", new ConnectException())). - thenReturn(response); - - when(resourceCreator.createResource()).thenReturn(resourceObject); - - AtlasClient atlasClient = getClientForTest("http://localhost:31000","http://localhost:41000"); - - atlasClient.setService(service); - atlasClient.setConfiguration(configuration); - - atlasClient.callAPIWithRetries(AtlasClient.API_V1.LIST_TYPES, null, resourceCreator); - - verify(client).destroy(); - verify(client).resource(UriBuilder.fromUri("http://localhost:31000").build()); - verify(client).resource(UriBuilder.fromUri("http://localhost:41000").build()); - } - - @Test - public void shouldRetryWithSameClientIfSingleAddressIsUsed() throws URISyntaxException, AtlasServiceException { - setupRetryParams(); - - ResourceCreator resourceCreator = mock(ResourceCreator.class); - WebResource resourceObject = mock(WebResource.class); - when(resourceObject.getURI()). - thenReturn(new URI("http://localhost:31000/api/atlas/types")); - - WebResource.Builder builder = getBuilder(resourceObject); - - ClientResponse response = mock(ClientResponse.class); - when(response.getStatus()).thenReturn(Response.Status.OK.getStatusCode()); - String activeStatus = "{\"Status\":\"ACTIVE\"}"; - when(response.getEntity(String.class)).thenReturn(activeStatus); - when(response.getLength()).thenReturn(activeStatus.length()); - - when(builder.method(AtlasClient.API_V1.LIST_TYPES.getMethod(), ClientResponse.class, null)). - thenThrow(new ClientHandlerException("simulating exception in calling API", new ConnectException())). - thenReturn(response); - - when(resourceCreator.createResource()).thenReturn(resourceObject); - when(configuration.getString("atlas.http.authentication.type", "simple")).thenReturn("simple"); - - AtlasClient atlasClient = getClientForTest("http://localhost:31000"); - - atlasClient.setService(resourceObject); - atlasClient.setConfiguration(configuration); - - atlasClient.callAPIWithRetries(AtlasClient.API_V1.LIST_TYPES, null, resourceCreator); - - verify(client).destroy(); - verify(client, times(2)).resource(UriBuilder.fromUri("http://localhost:31000").build()); - } - - @Test - public void shouldRetryAPICallsOnServiceUnavailable() throws AtlasServiceException, URISyntaxException { - setupRetryParams(); - - ResourceCreator resourceCreator = mock(ResourceCreator.class); - WebResource resourceObject = mock(WebResource.class); - when(resourceObject.getURI()). - thenReturn(new URI("http://localhost:31000/api/atlas/types")). - thenReturn(new URI("http://localhost:41000/api/atlas/types")). - thenReturn(new URI("http://localhost:41000/api/atlas/types")); - - WebResource.Builder builder = getBuilder(resourceObject); - - ClientResponse firstResponse = mock(ClientResponse.class); - when(firstResponse.getStatus()).thenReturn(Response.Status.SERVICE_UNAVAILABLE.getStatusCode()); - when(firstResponse.getClientResponseStatus()).thenReturn(ClientResponse.Status.SERVICE_UNAVAILABLE); - - ClientResponse response = mock(ClientResponse.class); - when(response.getStatus()).thenReturn(Response.Status.OK.getStatusCode()); - String activeStatus = "{\"Status\":\"ACTIVE\"}"; - when(response.getEntity(String.class)).thenReturn(activeStatus); - when(response.getLength()).thenReturn(activeStatus.length()); - - when(builder.method(AtlasClient.API_V1.LIST_TYPES.getMethod(), ClientResponse.class, null)). - thenThrow(new ClientHandlerException("simulating exception in calling API", new ConnectException())). - thenReturn(firstResponse). - thenReturn(response); - - when(resourceCreator.createResource()).thenReturn(resourceObject); - - AtlasClient atlasClient = getClientForTest("http://localhost:31000","http://localhost:41000"); - atlasClient.setService(resourceObject); - atlasClient.setConfiguration(configuration); - - atlasClient.callAPIWithRetries(AtlasClient.API_V1.LIST_TYPES, null, resourceCreator); - - - verify(client).destroy(); - verify(client).resource(UriBuilder.fromUri("http://localhost:31000").build()); - verify(client).resource(UriBuilder.fromUri("http://localhost:41000").build()); - } - - private WebResource.Builder getBuilder(WebResource resourceObject) { - when(resourceObject.getRequestBuilder()).thenReturn(resourceBuilderMock); - when(resourceObject.path(anyString())).thenReturn(resourceObject); - when(resourceBuilderMock.accept(AtlasBaseClient.JSON_MEDIA_TYPE)).thenReturn(resourceBuilderMock); - when(resourceBuilderMock.accept(MediaType.APPLICATION_JSON)).thenReturn(resourceBuilderMock); - when(resourceBuilderMock.type(AtlasBaseClient.JSON_MEDIA_TYPE)).thenReturn(resourceBuilderMock); - when(resourceBuilderMock.type(MediaType.MULTIPART_FORM_DATA)).thenReturn(resourceBuilderMock); - return resourceBuilderMock; - } - - private void setupRetryParams() { - when(configuration.getInt(AtlasClient.ATLAS_CLIENT_HA_RETRIES_KEY, AtlasClient.DEFAULT_NUM_RETRIES)). - thenReturn(3); - when(configuration.getInt(AtlasClient.ATLAS_CLIENT_HA_SLEEP_INTERVAL_MS_KEY, - AtlasClient.DEFAULT_SLEEP_BETWEEN_RETRIES_MS)). - thenReturn(1); - } - - private AtlasClient getClientForTest(final String... baseUrls) { - return new AtlasClient((UserGroupInformation)null, (String)null, baseUrls) { - boolean firstCall = true; - @Override - protected String determineActiveServiceURL(String[] baseUrls, Client client) { - String returnUrl = baseUrls[0]; - if (baseUrls.length > 1 && !firstCall) { - returnUrl = baseUrls[1]; - } - firstCall = false; - return returnUrl; - } - - @Override - protected Configuration getClientProperties() { - return configuration; - } - - @Override - protected Client getClient(Configuration configuration, UserGroupInformation ugi, String doAsUser) { - return client; - } - }; - } -} diff --git a/client/common/src/main/java/org/apache/atlas/AtlasBaseClient.java b/client/common/src/main/java/org/apache/atlas/AtlasBaseClient.java index cb35c944696..017763ac380 100644 --- a/client/common/src/main/java/org/apache/atlas/AtlasBaseClient.java +++ b/client/common/src/main/java/org/apache/atlas/AtlasBaseClient.java @@ -558,26 +558,6 @@ void handleClientHandlerException(ClientHandlerException che) { throw che; } - @VisibleForTesting - ObjectNode callAPIWithRetries(API api, Object requestObject, ResourceCreator resourceCreator) - throws AtlasServiceException { - for (int i = 0; i < getNumberOfRetries(); i++) { - WebResource resource = resourceCreator.createResource(); - try { - LOG.debug("Using resource {} for {} times", resource.getURI(), i + 1); - return callAPIWithResource(api, resource, requestObject, ObjectNode.class); - } catch (ClientHandlerException che) { - if (i == (getNumberOfRetries() - 1)) { - throw che; - } - LOG.warn("Handled exception in calling api {}", api.getNormalizedPath(), che); - LOG.warn("Exception's cause: {}", che.getCause().getClass()); - handleClientHandlerException(che); - } - } - throw new AtlasServiceException(api, new RuntimeException("Could not get response after retries.")); - } - @VisibleForTesting void setConfiguration(Configuration configuration) { this.configuration = configuration; diff --git a/client/common/src/main/java/org/apache/atlas/ResourceCreator.java b/client/common/src/main/java/org/apache/atlas/ResourceCreator.java deleted file mode 100644 index 2017065b39b..00000000000 --- a/client/common/src/main/java/org/apache/atlas/ResourceCreator.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.atlas; - -import com.sun.jersey.api.client.WebResource; - -/** - * An interface to capture the closure of how a WebResource is created. - */ -@Deprecated -public interface ResourceCreator { - WebResource createResource(); -} diff --git a/client/pom.xml b/client/pom.xml index 73eb73a6fd3..2ef6c47ad88 100755 --- a/client/pom.xml +++ b/client/pom.xml @@ -28,7 +28,6 @@ common - client-v1 client-v2 diff --git a/common/pom.xml b/common/pom.xml index 616f66c533c..5d7ba959bbf 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -30,6 +30,7 @@ jar + org.testng testng @@ -104,6 +105,13 @@ compile + + + io.micrometer + micrometer-registry-prometheus + ${micrometer.version} + + com.google.guava guava @@ -128,6 +136,62 @@ ${kafka.version} + + org.redisson + redisson + ${redis.client.version} + + + io.netty + * + + + + + io.netty + netty-all + ${netty4.version} + + + io.netty + netty-handler + ${netty4.version} + + + io.netty + netty-common + ${netty4.version} + + + io.netty + netty-resolver + ${netty4.version} + + + io.netty + netty-codec + ${netty4.version} + + + io.netty + netty-transport + ${netty4.version} + + + io.netty + netty-buffer + ${netty4.version} + + + io.netty + netty-transport-native-epoll + ${netty4.version} + + + io.netty + netty-transport-native-unix-common + ${netty4.version} + diff --git a/common/src/main/java/org/apache/atlas/AtlasConstants.java b/common/src/main/java/org/apache/atlas/AtlasConstants.java index ce0dbd0b4e3..d5e196d15e6 100644 --- a/common/src/main/java/org/apache/atlas/AtlasConstants.java +++ b/common/src/main/java/org/apache/atlas/AtlasConstants.java @@ -38,4 +38,5 @@ private AtlasConstants() { public static final String DEFAULT_ATLAS_REST_ADDRESS = "http://localhost:21000"; public static final String DEFAULT_TYPE_VERSION = "1.0"; public static final int ATLAS_SHUTDOWN_HOOK_PRIORITY = 30; + public static final int TASK_WAIT_TIME_MS = 180_000; } \ No newline at end of file diff --git a/common/src/main/java/org/apache/atlas/ICuratorFactory.java b/common/src/main/java/org/apache/atlas/ICuratorFactory.java new file mode 100644 index 00000000000..32d4e09f8fb --- /dev/null +++ b/common/src/main/java/org/apache/atlas/ICuratorFactory.java @@ -0,0 +1,7 @@ +package org.apache.atlas; + +import org.apache.curator.framework.recipes.locks.InterProcessMutex; + +public interface ICuratorFactory { + InterProcessMutex lockInstance(String zkRoot, String lockName); +} diff --git a/common/src/main/java/org/apache/atlas/annotation/EnableConditional.java b/common/src/main/java/org/apache/atlas/annotation/EnableConditional.java new file mode 100644 index 00000000000..6e1a1adeb76 --- /dev/null +++ b/common/src/main/java/org/apache/atlas/annotation/EnableConditional.java @@ -0,0 +1,19 @@ +package org.apache.atlas.annotation; + +import org.apache.atlas.utils.OnAtlasEnableCondition; +import org.springframework.context.annotation.Conditional; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ ElementType.TYPE, ElementType.METHOD }) +@Retention(RetentionPolicy.RUNTIME) +@Conditional(OnAtlasEnableCondition.class) +public @interface EnableConditional { + // Configured atlas property + String property(); + // The default interface implementation should declare this as true + boolean isDefault() default false; +} \ No newline at end of file diff --git a/common/src/main/java/org/apache/atlas/ha/HAConfiguration.java b/common/src/main/java/org/apache/atlas/ha/HAConfiguration.java index 91fd4e10769..565923db86a 100644 --- a/common/src/main/java/org/apache/atlas/ha/HAConfiguration.java +++ b/common/src/main/java/org/apache/atlas/ha/HAConfiguration.java @@ -74,6 +74,15 @@ public static boolean isHAEnabled(Configuration configuration) { return ret; } + /** + * Return whether HS (Active-Active HA) is enabled or not. + * @param configuration underlying configuration instance + * @return + */ + public static boolean isActiveActiveHAEnabled(Configuration configuration) { + return !isHAEnabled(configuration); + } + /** * Get the web server address that a server instance with the passed ID is bound to. * diff --git a/common/src/main/java/org/apache/atlas/pc/WorkItemManager.java b/common/src/main/java/org/apache/atlas/pc/WorkItemManager.java index 351421e8efb..9fd8a683586 100644 --- a/common/src/main/java/org/apache/atlas/pc/WorkItemManager.java +++ b/common/src/main/java/org/apache/atlas/pc/WorkItemManager.java @@ -115,7 +115,7 @@ public void drain() { } public void shutdown() throws InterruptedException { - int avgCommitTimeSeconds = getAvgCommitTimeSeconds() * 2; + long avgCommitTimeSeconds = getAvgCommitTimeSeconds() * 2; LOG.info("WorkItemManager: Shutdown started. Will wait for: {} minutes...", avgCommitTimeSeconds); @@ -129,8 +129,8 @@ public Queue getResults() { return this.resultsQueue; } - private int getAvgCommitTimeSeconds() { - int commitTimeSeconds = 0; + private long getAvgCommitTimeSeconds() { + long commitTimeSeconds = 0; for (U c : consumers) { commitTimeSeconds += c.getMaxCommitTimeInMs(); diff --git a/common/src/main/java/org/apache/atlas/repository/Constants.java b/common/src/main/java/org/apache/atlas/repository/Constants.java index 7cd67a04c68..e8a87976698 100644 --- a/common/src/main/java/org/apache/atlas/repository/Constants.java +++ b/common/src/main/java/org/apache/atlas/repository/Constants.java @@ -19,16 +19,36 @@ package org.apache.atlas.repository; import org.apache.atlas.ApplicationProperties; +import org.apache.atlas.AtlasConfiguration; import org.apache.atlas.AtlasException; +import org.apache.atlas.service.FeatureFlag; +import org.apache.atlas.service.FeatureFlagStore; import org.apache.commons.configuration.Configuration; - +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import static org.apache.atlas.service.FeatureFlag.USE_TEMP_ES_INDEX; import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.encodePropertyKey; +import static org.apache.atlas.type.AtlasStructType.UNIQUE_ATTRIBUTE_SHADE_PROPERTY_PREFIX; /** * Repository Constants. * */ public final class Constants { + private static final Logger LOG = LoggerFactory.getLogger(Constants.class); /** * Globally Unique identifier property key. @@ -39,8 +59,10 @@ public final class Constants { public static final String GUID_PROPERTY_KEY = encodePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "guid"); public static final String RELATIONSHIP_GUID_PROPERTY_KEY = encodePropertyKey(RELATIONSHIP_PROPERTY_KEY_PREFIX + GUID_PROPERTY_KEY); public static final String HISTORICAL_GUID_PROPERTY_KEY = encodePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "historicalGuids"); + public static final String QUALIFIED_NAME_HIERARCHY_PROPERTY_KEY = encodePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "qualifiedNameHierarchy"); public static final String FREETEXT_REQUEST_HANDLER = "/freetext"; public static final String TERMS_REQUEST_HANDLER = "/terms"; + public static final String ES_API_ALIASES = "/_aliases"; /** * Entity type name property key. @@ -65,7 +87,8 @@ public final class Constants { */ public static final String TYPE_CATEGORY_PROPERTY_KEY = getEncodedTypePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "type.category"); public static final String VERTEX_TYPE_PROPERTY_KEY = getEncodedTypePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "type"); - public static final String TYPENAME_PROPERTY_KEY = getEncodedTypePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "type.name"); + public static final String TYPENAME_PROPERTY_KEY = getEncodedTypePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "type.name"); + public static final String TYPE_DISPLAYNAME_PROPERTY_KEY= getEncodedTypePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "type.displayName"); public static final String TYPEDESCRIPTION_PROPERTY_KEY = getEncodedTypePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "type.description"); public static final String TYPEVERSION_PROPERTY_KEY = getEncodedTypePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "type.version"); public static final String TYPEOPTIONS_PROPERTY_KEY = getEncodedTypePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "type.options"); @@ -105,6 +128,106 @@ public final class Constants { public static final String PATCH_ACTION_PROPERTY_KEY = encodePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "patch.action"); public static final String PATCH_STATE_PROPERTY_KEY = encodePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "patch.state"); + /** + * Glossary property keys. + */ + public static final String ATLAS_GLOSSARY_ENTITY_TYPE = "AtlasGlossary"; + public static final String ATLAS_GLOSSARY_TERM_ENTITY_TYPE = "AtlasGlossaryTerm"; + public static final String ATLAS_GLOSSARY_CATEGORY_ENTITY_TYPE = "AtlasGlossaryCategory"; + public static final String CATEGORY_PARENT_EDGE_LABEL = "r:AtlasGlossaryCategoryHierarchyLink"; + public static final String CATEGORY_TERMS_EDGE_LABEL = "r:AtlasGlossaryTermCategorization"; + public static final String GLOSSARY_TERMS_EDGE_LABEL = "r:AtlasGlossaryTermAnchor"; + public static final String GLOSSARY_CATEGORY_EDGE_LABEL = "r:AtlasGlossaryCategoryAnchor"; + + /** + * MESH property keys. + */ + public static final String DATA_DOMAIN_ENTITY_TYPE = "DataDomain"; + public static final String DATA_PRODUCT_ENTITY_TYPE = "DataProduct"; + + public static final String AI_APPLICATION = "AIApplication"; + public static final String AI_MODEL = "AIModel"; + + public static final String STAKEHOLDER_ENTITY_TYPE = "Stakeholder"; + public static final String STAKEHOLDER_TITLE_ENTITY_TYPE = "StakeholderTitle"; + + public static final String REL_DOMAIN_TO_DOMAINS = "parent_domain_sub_domains"; + public static final String REL_DOMAIN_TO_PRODUCTS = "data_domain_data_products"; + + public static final String REL_DOMAIN_TO_STAKEHOLDERS = "data_domain_stakeholders"; + public static final String REL_STAKEHOLDER_TITLE_TO_STAKEHOLDERS = "stakeholder_title_stakeholders"; + + public static final String REL_DATA_PRODUCT_TO_OUTPUT_PORTS = "data_products_output_ports"; + public static final String REL_DATA_PRODUCT_TO_INPUT_PORTS = "data_products_input_ports"; + + public static final String INPUT_PORT_PRODUCT_EDGE_LABEL = "__Asset.inputPortDataProducts"; + public static final String OUTPUT_PORT_PRODUCT_EDGE_LABEL = "__Asset.outputPortDataProducts"; + + public static final String OUTPUT_PORTS = "outputPorts"; + public static final String INPUT_PORTS = "inputPorts"; + public static final String ADDED_OUTPUT_PORTS = "addedOutputPorts"; + public static final String REMOVED_OUTPUT_PORTS = "removedOutputPorts"; + + public static final String UD_RELATIONSHIP_EDGE_LABEL = "__Referenceable.userDefRelationshipTo"; + public static final String UD_RELATIONSHIP_END_NAME_FROM = "userDefRelationshipFrom"; + public static final String UD_RELATIONSHIP_END_NAME_TO = "userDefRelationshipTo"; + + /** + * SQL property keys. + */ + + public static final String SQL_ENTITY_TYPE = "SQL"; + public static final String CONNECTION_ENTITY_TYPE = "Connection"; + public static final String QUERY_ENTITY_TYPE = "Query"; + public static final String QUERY_FOLDER_ENTITY_TYPE = "Folder"; + public static final String QUERY_COLLECTION_ENTITY_TYPE = "Collection"; + + /* + * Purpose / Persona + */ + public static final String ACCESS_CONTROL_ENTITY_TYPE = "AccessControl"; + public static final String PERSONA_ENTITY_TYPE = "Persona"; + public static final String PURPOSE_ENTITY_TYPE = "Purpose"; + public static final String POLICY_ENTITY_TYPE = "AuthPolicy"; + public static final String SERVICE_ENTITY_TYPE = "AuthService"; + public static final String REL_POLICY_TO_ACCESS_CONTROL = "access_control_policies"; + + /** + * Resource + */ + public static final String LINK_ENTITY_TYPE = "Link"; + public static final String README_ENTITY_TYPE = "Readme"; + + public static final String ASSET_RELATION_ATTR = "asset"; + + public static final String ASSET_README_EDGE_LABEL = "__Asset.readme"; + public static final String ASSET_LINK_EDGE_LABEL = "__Asset.links"; + + public static final String DATA_SET_SUPER_TYPE = "Catalog"; + public static final String PROCESS_SUPER_TYPE = "Process"; + public static final String ERROR = "error"; + public static final String STATUS = "Status"; + + /** + * Contract + */ + public static final String CONTRACT_ENTITY_TYPE = "DataContract"; + public static final String ATTR_CONTRACT_VERSION = "dataContractVersion"; + + + /** + * Lineage relations. + */ + public static final String PROCESS_OUTPUTS = "__Process.outputs"; + public static final String PROCESS_INPUTS = "__Process.inputs"; + + public static String[] PROCESS_EDGE_LABELS = {PROCESS_OUTPUTS, PROCESS_INPUTS}; + + public static final String PROCESS_ENTITY_TYPE = "Process"; + + public static final String CONNECTION_PROCESS_ENTITY_TYPE = "ConnectionProcess"; + public static final String PARENT_CONNECTION_PROCESS_QUALIFIED_NAME = "parentConnectionProcessQualifiedName"; + /** * The homeId field is used when saving into Atlas a copy of an object that is being imported from another * repository. The homeId will be set to a String that identifies the other repository. The specific format @@ -155,16 +278,33 @@ public final class Constants { * search backing index name for edge labels. */ public static final String EDGE_INDEX = "edge_index"; - public static final String FULLTEXT_INDEX = "fulltext_index"; - public static final String QUALIFIED_NAME = "Referenceable.qualifiedName"; + /** + * elasticsearch index prefix. + */ + public static final String INDEX_PREFIX = "janusgraph_"; + + public static final String VERTEX_INDEX_NAME = INDEX_PREFIX + VERTEX_INDEX; + public static final String EDGE_INDEX_NAME = INDEX_PREFIX + EDGE_INDEX; + + public static final String NAME = "name"; + public static final String QUALIFIED_NAME = "qualifiedName"; + public static final String CONNECTION_QUALIFIED_NAME = "connectionQualifiedName"; + public static final String UNIQUE_QUALIFIED_NAME = UNIQUE_ATTRIBUTE_SHADE_PROPERTY_PREFIX + QUALIFIED_NAME; public static final String TYPE_NAME_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "typeName"; + + public static final String LABEL_PROPERTY_KEY = "label"; public static final String INDEX_SEARCH_MAX_RESULT_SET_SIZE = "atlas.graph.index.search.max-result-set-size"; public static final String INDEX_SEARCH_TYPES_MAX_QUERY_STR_LENGTH = "atlas.graph.index.search.types.max-query-str-length"; public static final String INDEX_SEARCH_TAGS_MAX_QUERY_STR_LENGTH = "atlas.graph.index.search.tags.max-query-str-length"; public static final String INDEX_SEARCH_VERTEX_PREFIX_PROPERTY = "atlas.graph.index.search.vertex.prefix"; public static final String INDEX_SEARCH_VERTEX_PREFIX_DEFAULT = "$v$"; + public static final String DOMAIN_GUIDS = "domainGUIDs"; + public static final String PRODUCT_GUIDS = "productGUIDs"; + + public static final String ATTR_TENANT_ID = "tenantId"; + public static final String DEFAULT_TENANT_ID = "default"; public static final String MAX_FULLTEXT_QUERY_STR_LENGTH = "atlas.graph.fulltext-max-query-str-length"; public static final String MAX_DSL_QUERY_STR_LENGTH = "atlas.graph.dsl-max-query-str-length"; @@ -174,6 +314,7 @@ public final class Constants { public static final String ATTRIBUTE_NAME_SUPERTYPENAMES = "superTypeNames"; public static final String ATTRIBUTE_NAME_STATE = "state"; public static final String ATTRIBUTE_NAME_VERSION = "version"; + public static final String ATTRIBUTE_LINK = "link"; public static final String TEMP_STRUCT_NAME_PREFIX = "__tempQueryResultStruct"; public static final String CLASSIFICATION_ENTITY_GUID = encodePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "entityGuid"); @@ -181,6 +322,9 @@ public final class Constants { public static final String CLASSIFICATION_VALIDITY_PERIODS_KEY = encodePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "validityPeriods"); public static final String CLASSIFICATION_VERTEX_PROPAGATE_KEY = encodePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "propagate"); public static final String CLASSIFICATION_VERTEX_REMOVE_PROPAGATIONS_KEY = encodePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "removePropagations"); + public static final String CLASSIFICATION_VERTEX_RESTRICT_PROPAGATE_THROUGH_LINEAGE= encodePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "restrictPropagationThroughLineage"); + + public static final String CLASSIFICATION_VERTEX_RESTRICT_PROPAGATE_THROUGH_HIERARCHY = encodePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "restrictPropagationThroughHierarchy"); public static final String CLASSIFICATION_VERTEX_NAME_KEY = encodePropertyKey(TYPE_NAME_PROPERTY_KEY); public static final String CLASSIFICATION_EDGE_NAME_PROPERTY_KEY = encodePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "name"); public static final String CLASSIFICATION_EDGE_IS_PROPAGATED_PROPERTY_KEY = encodePropertyKey(INTERNAL_PROPERTY_KEY_PREFIX + "isPropagated"); @@ -196,6 +340,19 @@ public final class Constants { public static final String VERTEX_ID_IN_IMPORT_KEY = "__vIdInImport"; public static final String EDGE_ID_IN_IMPORT_KEY = "__eIdInImport"; + /* + * Edge labels for data product relations which are hard deleted + */ + + public static final Set EDGE_LABELS_FOR_HARD_DELETION = new HashSet<>(Arrays.asList( OUTPUT_PORT_PRODUCT_EDGE_LABEL, INPUT_PORT_PRODUCT_EDGE_LABEL, TERM_ASSIGNMENT_LABEL )); + /* + * elasticsearch attributes + */ + + public static final String ELASTICSEARCH_CLUSTER_STATUS_YELLOW = "YELLOW"; + public static final String ELASTICSEARCH_CLUSTER_STATUS_GREEN = "GREEN"; + public static final String ELASTICSEARCH_REST_STATUS_OK = "OK"; + /* * replication attributes */ @@ -225,9 +382,36 @@ public final class Constants { public static final String TASK_ATTEMPT_COUNT = encodePropertyKey(TASK_PREFIX + "attemptCount"); public static final String TASK_PARAMETERS = encodePropertyKey(TASK_PREFIX + "parameters"); public static final String TASK_ERROR_MESSAGE = encodePropertyKey(TASK_PREFIX + "errorMessage"); + public static final String TASK_WARNING_MESSAGE = encodePropertyKey(TASK_PREFIX + "warning"); public static final String TASK_START_TIME = encodePropertyKey(TASK_PREFIX + "startTime"); public static final String TASK_END_TIME = encodePropertyKey(TASK_PREFIX + "endTime"); - + public static final String TASK_TIME_TAKEN_IN_SECONDS = encodePropertyKey(TASK_PREFIX + "timeTakenInSeconds"); + public static final String TASK_CLASSIFICATION_ID = encodePropertyKey(TASK_PREFIX + "classificationId"); + public static final String TASK_ENTITY_GUID = encodePropertyKey(TASK_PREFIX + "entityGuid"); + public static final String TASK_PARENT_ENTITY_GUID = encodePropertyKey(TASK_PREFIX + "parentEntityGuid"); + public static final String TASK_CLASSIFICATION_TYPENAME = encodePropertyKey(TASK_PREFIX + "classificationTypeName"); + public static final String ACTIVE_STATE_VALUE = "ACTIVE"; + + public static final String ATLAN_HEADER_PREFIX_PATTERN = "x-atlan-"; + public static final String TASK_HEADER_ATLAN_AGENT = "x-atlan-agent"; + public static final String TASK_HEADER_ATLAN_AGENT_ID = "x-atlan-agent-id"; + public static final String TASK_HEADER_ATLAN_PKG_NAME = "x-atlan-package-name"; + public static final String TASK_HEADER_ATLAN_AGENT_WORKFLOW_ID = "x-atlan-agent-workflow-id"; + public static final String TASK_HEADER_ATLAN_VIA_UI = "x-atlan-via-ui"; + public static final String TASK_HEADER_ATLAN_REQUEST_ID = "x-atlan-request-id"; + public static final String TASK_HEADER_ATLAN_GOOGLE_SHEETS_ID = "x-atlan-google-sheets-id"; + public static final String TASK_HEADER_ATLAN_MS_EXCEL_ID = "x-atlan-microsoft-excel-id"; + public static final Set TASK_HEADER_SET = new HashSet() {{ + add(TASK_HEADER_ATLAN_AGENT); + add(TASK_HEADER_ATLAN_AGENT_ID); + add(TASK_HEADER_ATLAN_VIA_UI); + add(TASK_HEADER_ATLAN_PKG_NAME); + add(TASK_HEADER_ATLAN_AGENT_WORKFLOW_ID); + add(TASK_HEADER_ATLAN_REQUEST_ID); + add(TASK_HEADER_ATLAN_GOOGLE_SHEETS_ID); + add(TASK_HEADER_ATLAN_MS_EXCEL_ID); + }}; + /** * Index Recovery vertex property keys. */ @@ -244,12 +428,116 @@ public final class Constants { public static final String IMPALA_SOURCE = "impala"; public static final String STORM_SOURCE = "storm"; public static final String FILE_SPOOL_SOURCE = "file_spool"; + public static final String DOMAIN_GUIDS_ATTR = "domainGUIDs"; + public static final String ASSET_POLICY_GUIDS = "assetPolicyGUIDs"; + public static final String PRODUCT_GUIDS_ATTR = "productGUIDs"; + + public static final String NON_COMPLIANT_ASSET_POLICY_GUIDS = "nonCompliantAssetPolicyGUIDs"; + public static final String ASSET_POLICIES_COUNT = "assetPoliciesCount"; /* * All supported file-format extensions for Bulk Imports through file upload */ public enum SupportedFileExtensions { XLSX, XLS, CSV } + /* + * All statsd metric names + */ + public static final String ENTITIES_ADDED_METRIC = "entities.added"; + public static final String ENTITIES_UPDATED_METRIC = "entities.updated"; + public static final String ENTITIES_DELETED_METRIC = "entities.deleted"; + public static final String ENTITIES_PURGED_METRIC = "entities.purged"; + public static final String CLASSIFICATIONS_ADDED_METRIC = "classifications.added"; + public static final String CLASSIFICATIONS_UPDATED_METRIC = "classifications.updated"; + public static final String CLASSIFICATIONS_DELETED_METRIC = "classifications.deleted"; + public static final String TERMS_ADDED_METRIC = "terms.added"; + public static final String TERMS_DELETED_METRIC = "terms.deleted"; + public static final String RELATIONSHIPS_ADDED_METRIC = "relationships.added"; + public static final String RELATIONSHIPS_UPDATED_METRIC = "relationships.updated"; + public static final String RELATIONSHIPS_DELETED_METRIC = "relationships.deleted"; + public static final String RELATIONSHIPS_PURGED_METRIC = "relationships.purged"; + public static final String LABELS_ADDED_METRIC = "labels.added"; + public static final String LABELS_DELETED_METRIC = "labels.deleted"; + public static final String BA_UPDATED_METRIC = "ba.deleted"; + + public static final String BASIC_SEARCH_COUNT_METRIC = "search.basic.count"; + public static final String BASIC_SEARCH_EXECUTION_TIME_METRIC = "search.basic.execution.time"; + public static final String CLASSIFICATION_PROPAGATION_TIME_METRIC = "classification.propagation.time"; + public static final String CLASSIFICATION_PROPAGATION_JOB_COUNT_METRIC = "classification.propagation.job.count"; + + public static final int ELASTICSEARCH_PAGINATION_SIZE = 50; + + public static final String CATALOG_PROCESS_INPUT_RELATIONSHIP_LABEL = "__Process.inputs"; + public static final String CATALOG_PROCESS_OUTPUT_RELATIONSHIP_LABEL = "__Process.outputs"; + public static final String CATALOG_AIRFLOW_INPUT_RELATIONSHIP_LABEL = "__AirflowTask.inputs"; + public static final String CATALOG_AIRFLOW_OUTPUT_RELATIONSHIP_LABEL = "__AirflowTask.outputs"; + public static final String CATALOG_CONNECTION_PROCESS_INPUT_RELATIONSHIP_LABEL = "__ConnectionProcess.inputs"; + public static final String CATALOG_CONNECTION_PROCESS_OUTPUT_RELATIONSHIP_LABEL = "__ConnectionProcess.outputs"; + public static final String CATALOG_SPARK_JOB_INPUT_RELATIONSHIP_LABEL = "__SparkJob.inputs"; + public static final String CATALOG_SPARK_JOB_OUTPUT_RELATIONSHIP_LABEL = "__SparkJob.outputs"; + public static final String CLASSIFICATION_PROPAGATION_MODE_DEFAULT ="DEFAULT"; + public static final String CLASSIFICATION_PROPAGATION_MODE_RESTRICT_LINEAGE ="RESTRICT_LINEAGE"; + + public static final String CLASSIFICATION_PROPAGATION_MODE_RESTRICT_HIERARCHY ="RESTRICT_HIERARCHY"; + + + public static final HashMap> CLASSIFICATION_PROPAGATION_MODE_LABELS_MAP = new HashMap>(){{ + put(CLASSIFICATION_PROPAGATION_MODE_RESTRICT_LINEAGE, new ArrayList<>( + Arrays.asList(CATALOG_PROCESS_INPUT_RELATIONSHIP_LABEL, + CATALOG_PROCESS_OUTPUT_RELATIONSHIP_LABEL, + CATALOG_AIRFLOW_INPUT_RELATIONSHIP_LABEL, + CATALOG_AIRFLOW_OUTPUT_RELATIONSHIP_LABEL, + CATALOG_CONNECTION_PROCESS_INPUT_RELATIONSHIP_LABEL, + CATALOG_CONNECTION_PROCESS_OUTPUT_RELATIONSHIP_LABEL, + CATALOG_SPARK_JOB_INPUT_RELATIONSHIP_LABEL, + CATALOG_SPARK_JOB_OUTPUT_RELATIONSHIP_LABEL + ))); + put(CLASSIFICATION_PROPAGATION_MODE_DEFAULT, null); + put(CLASSIFICATION_PROPAGATION_MODE_RESTRICT_HIERARCHY, new ArrayList<>( + Arrays.asList(CATALOG_PROCESS_INPUT_RELATIONSHIP_LABEL, + CATALOG_PROCESS_OUTPUT_RELATIONSHIP_LABEL + ))); + }}; + + public static final String ATTR_ADMIN_USERS = "adminUsers"; + public static final String ATTR_ADMIN_GROUPS = "adminGroups"; + public static final String ATTR_ADMIN_ROLES = "adminRoles"; + public static final String ATTR_VIEWER_USERS = "viewerUsers"; + public static final String ATTR_VIEWER_GROUPS = "viewerGroups"; + + public static final String ATTR_STARRED_BY = "starredBy"; + public static final String ATTR_STARRED_COUNT = "starredCount"; + public static final String ATTR_STARRED_DETAILS_LIST = "starredDetailsList"; + public static final String ATTR_ASSET_STARRED_BY = "assetStarredBy"; + public static final String ATTR_ASSET_STARRED_AT = "assetStarredAt"; + public static final String ATTR_CERTIFICATE_STATUS = "certificateStatus"; + public static final String ATTR_CONTRACT = "dataContractSpec"; + public static final String ATTR_CONTRACT_JSON = "dataContractJson"; + public static final String STRUCT_STARRED_DETAILS = "StarredDetails"; + + public static final String KEYCLOAK_ROLE_ADMIN = "$admin"; + public static final String KEYCLOAK_ROLE_MEMBER = "$member"; + public static final String KEYCLOAK_ROLE_GUEST = "$guest"; + public static final String KEYCLOAK_ROLE_DEFAULT = "default-roles-default"; + public static final String KEYCLOAK_ROLE_API_TOKEN = "$api-token-default-access"; + + public static final String REQUEST_HEADER_USER_AGENT = "User-Agent"; + public static final String REQUEST_HEADER_HOST = "Host"; + + public static final Set SKIP_UPDATE_AUTH_CHECK_TYPES = new HashSet() {{ + add(README_ENTITY_TYPE); + add(LINK_ENTITY_TYPE); + add(STAKEHOLDER_ENTITY_TYPE); + add(STAKEHOLDER_TITLE_ENTITY_TYPE); + }}; + + public static final Set SKIP_DELETE_AUTH_CHECK_TYPES = new HashSet() {{ + add(README_ENTITY_TYPE); + add(LINK_ENTITY_TYPE); + add(POLICY_ENTITY_TYPE); + add(STAKEHOLDER_TITLE_ENTITY_TYPE); + }}; + private Constants() { } @@ -268,4 +556,34 @@ private static String getEncodedTypePropertyKey(String defaultKey) { return encodePropertyKey(defaultKey); } } + + public static String getESIndex() { + String indexSuffix = null; + if(AtlasConfiguration.ATLAS_MAINTENANCE_MODE.getBoolean()) { + try { + if (FeatureFlagStore.evaluate( USE_TEMP_ES_INDEX.getKey(), "true")) { + indexSuffix = "_temp"; + } + } catch (Exception e) { + LOG.error("Failed to evaluate feature flag with error", e); + } + } + return indexSuffix == null ? VERTEX_INDEX_NAME : VERTEX_INDEX_NAME + indexSuffix; + } + + public static String getStaticFileAsString(String fileName) throws IOException { + String atlasHomeDir = System.getProperty("atlas.home"); + atlasHomeDir = StringUtils.isEmpty(atlasHomeDir) ? "." : atlasHomeDir; + + Path path = Paths.get(atlasHomeDir, "static", fileName); + String resourceAsString = null; + try { + resourceAsString = new String(Files.readAllBytes(path), StandardCharsets.UTF_8); + } catch (IOException e) { + LOG.error("Failed to get static file as string: {}", fileName); + throw e; + } + + return resourceAsString; + } } diff --git a/common/src/main/java/org/apache/atlas/service/CacheEntry.java b/common/src/main/java/org/apache/atlas/service/CacheEntry.java new file mode 100644 index 00000000000..7af28d2f3a6 --- /dev/null +++ b/common/src/main/java/org/apache/atlas/service/CacheEntry.java @@ -0,0 +1,38 @@ +package org.apache.atlas.service; + +/** + * A simple wrapper for cache entries that includes the value and its expiration timestamp. + * Used for TTL-based expiration with jitter in the custom cache implementation. + */ +class CacheEntry { + private final V value; + private final long expirationTime; // CHANGED: Store expiration time directly + + /** + * Creates a new cache entry. + * + * @param value The value to be stored. + * @param expirationTime The pre-calculated timestamp (in milliseconds) when this entry should expire. + * A value of Long.MAX_VALUE means it never expires. + */ + public CacheEntry(V value, long expirationTime) { + this.value = value; + this.expirationTime = expirationTime; + } + + public V getValue() { + return value; + } + + /** + * Check if this cache entry has expired. + * * @return true if the entry has expired, false otherwise + */ + public boolean isExpired() { + // No expiration for entries with max value timestamp + if (expirationTime == Long.MAX_VALUE) { + return false; + } + return System.currentTimeMillis() > expirationTime; + } +} \ No newline at end of file diff --git a/common/src/main/java/org/apache/atlas/service/FeatureFlag.java b/common/src/main/java/org/apache/atlas/service/FeatureFlag.java new file mode 100644 index 00000000000..e5d0aa812bf --- /dev/null +++ b/common/src/main/java/org/apache/atlas/service/FeatureFlag.java @@ -0,0 +1,47 @@ +package org.apache.atlas.service; + +import java.util.Arrays; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +public enum FeatureFlag { + ENABLE_JANUS_OPTIMISATION("ENABLE_JANUS_OPTIMISATION", false), + ENABLE_PERSONA_HIERARCHY_FILTER("enable_persona_hierarchy_filter", false), + DISABLE_WRITE_FLAG("disable_writes", false), + USE_TEMP_ES_INDEX("use_temp_es_index", false); + + private final String key; + private final boolean defaultValue; + + private static final Map KEY_TO_FLAG_MAP = + Arrays.stream(values()) + .collect(Collectors.toMap(FeatureFlag::getKey, Function.identity())); + + FeatureFlag(String key, boolean defaultValue) { + this.key = key; + this.defaultValue = defaultValue; + } + + public String getKey() { + return key; + } + + public boolean getDefaultValue() { + return defaultValue; + } + + public static FeatureFlag fromKey(String key) { + return KEY_TO_FLAG_MAP.get(key); + } + + public static boolean isValidFlag(String key) { + return KEY_TO_FLAG_MAP.containsKey(key); + } + + public static String[] getAllKeys() { + return Arrays.stream(values()) + .map(FeatureFlag::getKey) + .toArray(String[]::new); + } +} diff --git a/common/src/main/java/org/apache/atlas/service/FeatureFlagCacheStore.java b/common/src/main/java/org/apache/atlas/service/FeatureFlagCacheStore.java new file mode 100644 index 00000000000..7012367ca62 --- /dev/null +++ b/common/src/main/java/org/apache/atlas/service/FeatureFlagCacheStore.java @@ -0,0 +1,59 @@ +package org.apache.atlas.service; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.time.Duration; + +@Component +@DependsOn({"redisServiceImpl"}) +public class FeatureFlagCacheStore { + private static final Logger LOG = LoggerFactory.getLogger(FeatureFlagCacheStore.class); + + private final SimpleCache primaryCache; + private final SimpleCache fallbackCache; + + @Inject + public FeatureFlagCacheStore(FeatureFlagConfig config) { + this.primaryCache = new SimpleCache<>(Duration.ofMinutes(config.getPrimaryCacheTtlMinutes()).toMillis()); + this.fallbackCache = new SimpleCache<>(null); // No TTL for fallback cache + + LOG.info("Initialized FeatureFlagCacheStore - Primary cache TTL: {}min, Fallback cache: no expiration", + config.getPrimaryCacheTtlMinutes()); + } + + public String getFromPrimaryCache(String key) { + String value = primaryCache.getIfPresent(key); + LOG.debug("Primary cache {} for key: {}", value != null ? "hit" : "miss", key); + return value; + } + + public String getFromFallbackCache(String key) { + String value = fallbackCache.getIfPresent(key); + if (value == null) { + LOG.warn("Fallback cache miss for key: {}", key); + } + return value; + } + + public void putInBothCaches(String key, String value) { + primaryCache.put(key, value); + fallbackCache.put(key, value); + LOG.debug("Cached value for key: {} in both primary and fallback caches", key); + } + + public void putInFallbackCache(String key, String value) { + fallbackCache.put(key, value); + LOG.debug("Cached value for key: {} in fallback cache only", key); + } + + public void removeFromBothCaches(String key) { + primaryCache.invalidate(key); + fallbackCache.invalidate(key); + LOG.debug("Removed key: {} from both caches", key); + } + +} diff --git a/common/src/main/java/org/apache/atlas/service/FeatureFlagConfig.java b/common/src/main/java/org/apache/atlas/service/FeatureFlagConfig.java new file mode 100644 index 00000000000..b603a316301 --- /dev/null +++ b/common/src/main/java/org/apache/atlas/service/FeatureFlagConfig.java @@ -0,0 +1,41 @@ +package org.apache.atlas.service; + +import org.apache.atlas.ApplicationProperties; +import org.apache.atlas.AtlasException; +import org.apache.commons.configuration.Configuration; +import org.springframework.stereotype.Component; + +@Component +public class FeatureFlagConfig { + + private final int primaryCacheTtlMinutes; + private final int redisRetryAttempts; + private final long redisRetryDelayMs; + private final double redisRetryBackoffMultiplier; + + public FeatureFlagConfig() throws AtlasException { + Configuration props = ApplicationProperties.get(); + + this.primaryCacheTtlMinutes = props.getInt("atlas.feature.flag.cache.primary.ttl.minutes", 30); + this.redisRetryAttempts = props.getInt("atlas.feature.flag.redis.retry.attempts", 5); + this.redisRetryDelayMs = props.getLong("atlas.feature.flag.redis.retry.delay.ms", 1000L); + this.redisRetryBackoffMultiplier = props.getDouble("atlas.feature.flag.redis.retry.backoff.multiplier", 2.0); + } + + public int getPrimaryCacheTtlMinutes() { + return primaryCacheTtlMinutes; + } + + public int getRedisRetryAttempts() { + return redisRetryAttempts; + } + + public long getRedisRetryDelayMs() { + return redisRetryDelayMs; + } + + public double getRedisRetryBackoffMultiplier() { + return redisRetryBackoffMultiplier; + } + +} diff --git a/common/src/main/java/org/apache/atlas/service/FeatureFlagStore.java b/common/src/main/java/org/apache/atlas/service/FeatureFlagStore.java new file mode 100644 index 00000000000..599b570473a --- /dev/null +++ b/common/src/main/java/org/apache/atlas/service/FeatureFlagStore.java @@ -0,0 +1,397 @@ +package org.apache.atlas.service; + +import org.apache.atlas.service.redis.RedisService; +import org.apache.commons.lang.StringUtils; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.annotation.DependsOn; +import org.springframework.stereotype.Component; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import io.micrometer.core.instrument.Gauge; +import io.micrometer.core.instrument.MeterRegistry; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + + +@Component +@DependsOn("redisServiceImpl") +public class FeatureFlagStore implements ApplicationContextAware { + private static final Logger LOG = LoggerFactory.getLogger(FeatureFlagStore.class); + + private static final String FF_NAMESPACE = "ff:"; + private static final List KNOWN_FLAGS = List.of(FeatureFlag.getAllKeys()); + + // Thundering herd prevention: result sharing pattern + private static final int LOCK_TIMEOUT_SECONDS = 10; + private static final long INIT_RETRY_DELAY_MS = 20000L; // 2 seconds + + private final ConcurrentHashMap> inFlightRedisFetches = new ConcurrentHashMap<>(); + + private final RedisService redisService; + private final FeatureFlagConfig config; + private final FeatureFlagCacheStore cacheStore; + private static ApplicationContext context; + + private volatile boolean initialized = false; + private static final String METRIC_COMPONENT = "atlas_classification"; + + @Inject + public FeatureFlagStore(RedisService redisService, FeatureFlagConfig config, + FeatureFlagCacheStore cacheStore) { + this.redisService = Objects.requireNonNull(redisService, "RedisService cannot be null - critical dependency missing!"); + this.config = Objects.requireNonNull(config, "FeatureFlagConfig cannot be null"); + this.cacheStore = Objects.requireNonNull(cacheStore, "FeatureFlagCacheStore cannot be null"); + + LOG.info("FeatureFlagStore dependencies injected successfully - RedisService: {}", + redisService.getClass().getSimpleName()); + } + + private static FeatureFlagStore getStore() { + try { + if (context == null) { + LOG.error("ApplicationContext not initialized yet"); + return null; + } + return context.getBean(FeatureFlagStore.class); + } catch (Exception e) { + LOG.error("Failed to get FeatureFlagStore from Spring context", e); + return null; + } + } + + @PostConstruct + public void initialize() throws InterruptedException { + LOG.info("Starting FeatureFlagStore initialization..."); + long startTime = System.currentTimeMillis(); + + // A single, consolidated retry loop for the entire initialization process. Doesn't let Atlas start until Redis FF store is set up correctly. + while (true) { + try { + validateDependencies(); + preloadAllFlags(); + initialized = true; + + // Add version tracking metric + MeterRegistry meterRegistry = org.apache.atlas.service.metrics.MetricUtils.getMeterRegistry(); + Gauge.builder(METRIC_COMPONENT + "_atlas_version_enabled", + this, + ref -> isTagV2Enabled() ? 2.0 : 1.0) + .description("Indicates which Tag propagation version is enabled (2.0 = v2, 1.0 = v1)") + .tag("component", "version") + .register(meterRegistry); + + long duration = System.currentTimeMillis() - startTime; + LOG.info("FeatureFlagStore initialization completed successfully in {}ms", duration); + break; // Success! Exit the loop. + + } catch (Exception e) { + // Catches any failure from validation or preloading and retries the whole process. + long duration = System.currentTimeMillis() - startTime; + LOG.warn("FeatureFlagStore initialization failed after {}ms, retrying in {} seconds... Error: {}", + duration, INIT_RETRY_DELAY_MS / 1000, e.getMessage()); + Thread.sleep(INIT_RETRY_DELAY_MS); + } + } + } + + private void validateDependencies() { + LOG.info("Validating FeatureFlagStore dependencies..."); + try { + // Test Redis connectivity with a simple operation + String testKey = "ff:_health_check"; + redisService.putValue(testKey, "test"); + String testValue = redisService.getValue(testKey); + redisService.removeValue(testKey); + + if (!"test".equals(testValue)) { + throw new RuntimeException("Redis connectivity test failed - value mismatch"); + } + + LOG.info("Redis connectivity validated successfully"); + } catch (Exception e) { + // Re-throw the exception to be caught by the central loop in initialize() + throw new RuntimeException("Redis dependency validation failed", e); + } + } + + private void preloadAllFlags() { + LOG.info("Preloading all known feature flags from Redis..."); + for (String flagKey : KNOWN_FLAGS) { + FeatureFlag flag = FeatureFlag.fromKey(flagKey); + String namespacedKey = addFeatureFlagNamespace(flagKey); + // loadFlagFromRedisWithRetry will throw an exception on failure, which is caught by initialize() + String value = loadFlagFromRedisWithRetry(namespacedKey, flagKey); + + if (!StringUtils.isEmpty(value)) { + cacheStore.putInBothCaches(namespacedKey, value); + LOG.debug("Preloaded flag '{}' with Redis value: {}", flagKey, value); + } else { + String defaultValue = String.valueOf(flag.getDefaultValue()); + cacheStore.putInBothCaches(namespacedKey, defaultValue); + LOG.debug("Preloaded flag '{}' with default value: {} (not found in Redis)", flagKey, defaultValue); + } + } + LOG.info("All feature flags preloaded."); + } + + private String loadFlagFromRedisWithRetry(String namespacedKey, String flagKey) { + for (int attempt = 1; attempt <= config.getRedisRetryAttempts(); attempt++) { + try { + return redisService.getValue(namespacedKey); + + } catch (Exception e) { + boolean isLastAttempt = (attempt == config.getRedisRetryAttempts()); + + if (isLastAttempt) { + LOG.error("Redis operation failed for flag '{}' after {} attempts", flagKey, attempt, e); + throw new RuntimeException("Failed to load flag " + flagKey + " after " + attempt + " attempts", e); + } + + // Calculate exponential backoff delay + long backoffDelay = calculateBackoffDelay(attempt); + LOG.warn("Redis operation failed for flag '{}' (attempt {}/{}), retrying in {}ms...", + flagKey, attempt, config.getRedisRetryAttempts(), backoffDelay, e); + + try { + Thread.sleep(backoffDelay); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Interrupted while retrying flag " + flagKey, ie); + } + } + } + + return null; // This line should never be reached + } + + private long calculateBackoffDelay(int attempt) { + double exponentialFactor = Math.pow(config.getRedisRetryBackoffMultiplier(), attempt - 1); + long backoffDelay = Math.round(config.getRedisRetryDelayMs() * exponentialFactor); + + // Cap the maximum delay to prevent extremely long waits (e.g., 30 seconds max) + long maxDelayMs = 30000L; + return Math.min(backoffDelay, maxDelayMs); + } + + public static boolean isTagV2Enabled() { + return !evaluate(FeatureFlag.ENABLE_JANUS_OPTIMISATION.getKey(), "false"); // Default value is false, if the flag is present or has value true it's treated as enabled + } + + public static boolean evaluate(String key, String expectedValue) { + return StringUtils.equals(getFlag(key), expectedValue); + } + + public static String getFlag(String key){ + try { + if (!isValidFlag(key)) { + LOG.warn("Invalid feature flag requested: '{}'. Only predefined flags are allowed", key); + throw new IllegalStateException("Invalid feature flag requested: " + key); + } + + FeatureFlagStore instance = getInstance(); + if (instance == null) { + LOG.warn("FeatureFlagStore not initialized, cannot get flag: {}", key); + return getDefaultValue(key); + } + + return instance.getFlagInternal(key); + } catch (Exception e) { + if (FeatureFlag.ENABLE_JANUS_OPTIMISATION.getKey().equals(key)) + throw e; + LOG.error("Error getting feature flag '{}'", key, e); + return getDefaultValue(key); // Always return something + } + } + + private static String getDefaultValue(String key) { + if (FeatureFlag.ENABLE_JANUS_OPTIMISATION.getKey().equals(key)) + throw new RuntimeException("Cannot return default value for critical Tags FF: " + key); + FeatureFlag flag = FeatureFlag.fromKey(key); + return flag != null ? String.valueOf(flag.getDefaultValue()) : "false"; + } + + private static boolean isValidFlag(String key) { + return FeatureFlag.isValidFlag(key); + } + + String getFlagInternal(String key) { + if (!initialized) { + LOG.warn("FeatureFlagStore not fully initialized yet, attempting to get flag: {}", key); + throw new IllegalStateException("FeatureFlagStore not initialized"); + } + + if (redisService == null) { + LOG.error("RedisService is null - this should never happen after proper initialization"); + throw new IllegalStateException("RedisService is not available"); + } + + if (StringUtils.isEmpty(key)) { + LOG.error("Invalid key: cannot be null or empty"); + throw new IllegalStateException("Null or empty redis key"); + } + + String namespacedKey = addFeatureFlagNamespace(key); + + // 1. First check: primary cache + String value = cacheStore.getFromPrimaryCache(namespacedKey); + if (value != null) { + return value; + } + + // 2. Second check: see if another thread is already fetching this key + CompletableFuture future = inFlightRedisFetches.get(key); + + if (future == null) { + // This thread is the first; it will do the fetching + CompletableFuture newFuture = new CompletableFuture<>(); + + // Atomically put the new future into the map. + // If another thread beats us, `putIfAbsent` will return its future. + future = inFlightRedisFetches.putIfAbsent(key, newFuture); + + if (future == null) { // We successfully put our new future in the map; we are the leader. + future = newFuture; // Use the future we created + try { + LOG.debug("Fetching from Redis for key: {}", key); + String redisValue = fetchFromRedisAndCache(namespacedKey, key); + + // Complete the future successfully with the result + future.complete(redisValue); + + } catch (Exception e) { + // Complete the future exceptionally to notify other waiting threads of the failure + LOG.error("Exception while fetching flag '{}' for the first time.", key, e); + future.completeExceptionally(e); + } finally { + // CRUCIAL: Clean up the map so subsequent requests re-trigger a fetch + inFlightRedisFetches.remove(key, future); + } + } + } + + // 3. Wait for the result from the leader thread (or this thread if it was the leader) + try { + value = future.get(LOCK_TIMEOUT_SECONDS, TimeUnit.SECONDS); + } catch (Exception e) { + LOG.warn("Failed to get feature flag '{}' from in-flight future (timeout or exception)", key, e); + } + + if (value != null) { + return value; + } + + // 4. Final check: fallback cache + value = cacheStore.getFromFallbackCache(namespacedKey); + if (value != null) { + LOG.debug("Using fallback cache value for key: {}", key); + return value; + } + + LOG.warn("No value found for flag '{}' in any cache or Redis", key); + return null; + } + + private String fetchFromRedisAndCache(String namespacedKey, String key) { + try { + String value = loadFlagFromRedisWithRetry(namespacedKey, key); + if (value != null) + updateBothCaches(namespacedKey, value); + return value; + } catch (Exception e) { + LOG.error("Failed to fetch flag '{}' from Redis", key, e); + return null; + } + } + + private synchronized void updateBothCaches(String namespacedKey, String value) { + cacheStore.putInBothCaches(namespacedKey, value); + } + + public static void setFlag(String key, String value) { + if (!isValidFlag(key)) { + LOG.error("Cannot set invalid feature flag: '{}'. Only predefined flags are allowed: {}", + key, String.join(", ", FeatureFlag.getAllKeys())); + return; + } + + FeatureFlagStore instance = getInstance(); + if (instance == null) { + LOG.warn("FeatureFlagStore not initialized, cannot set flag: {}", key); + return; + } + instance.setFlagInternal(key, value); + } + + synchronized void setFlagInternal(String key, String value) { + if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) { + return; + } + + String namespacedKey = addFeatureFlagNamespace(key); + try { + redisService.putValue(namespacedKey, value); + cacheStore.putInBothCaches(namespacedKey, value); + LOG.info("Set feature flag '{}' to value: {}", key, value); + + } catch (Exception e) { + LOG.error("Failed to set feature flag '{}'", key, e); + } + } + + public static void deleteFlag(String key) { + if (!isValidFlag(key)) { + LOG.error("Cannot delete invalid feature flag: '{}'. Only predefined flags are allowed: {}", + key, String.join(", ", FeatureFlag.getAllKeys())); + return; + } + + FeatureFlagStore instance = getInstance(); + if (instance == null) { + LOG.warn("FeatureFlagStore not initialized, cannot delete flag: {}", key); + return; + } + instance.deleteFlagInternal(key); + } + + synchronized void deleteFlagInternal(String key) { + if (StringUtils.isEmpty(key)) { + return; + } + + String namespacedKey = addFeatureFlagNamespace(key); + try { + redisService.removeValue(namespacedKey); + cacheStore.removeFromBothCaches(namespacedKey); + LOG.info("Deleted feature flag: {}", key); + + } catch (Exception e) { + LOG.error("Failed to delete feature flag '{}'", key, e); + } + } + + private static FeatureFlagStore getInstance() { + return getStore(); + } + + private static String addFeatureFlagNamespace(String key) { + return FF_NAMESPACE + key; + } + + public boolean isInitialized() { + return initialized; + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + context = applicationContext; + } + +} diff --git a/common/src/main/java/org/apache/atlas/service/Services.java b/common/src/main/java/org/apache/atlas/service/Services.java index 2d548467fe8..5beab354216 100644 --- a/common/src/main/java/org/apache/atlas/service/Services.java +++ b/common/src/main/java/org/apache/atlas/service/Services.java @@ -18,6 +18,7 @@ package org.apache.atlas.service; import org.apache.atlas.annotation.AtlasService; +import org.apache.atlas.type.AtlasType; import org.apache.commons.configuration.Configuration; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; @@ -27,6 +28,7 @@ import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.inject.Inject; + import java.util.List; import static org.apache.atlas.AtlasConstants.ATLAS_MIGRATION_MODE_FILENAME; @@ -65,8 +67,8 @@ public void start() { continue; } - LOG.info("Starting service {}", svc.getClass().getName()); + LOG.info("Starting service {}", svc.getClass().getName()); svc.start(); } } catch (Exception e) { diff --git a/common/src/main/java/org/apache/atlas/service/SimpleCache.java b/common/src/main/java/org/apache/atlas/service/SimpleCache.java new file mode 100644 index 00000000000..acec2f5a443 --- /dev/null +++ b/common/src/main/java/org/apache/atlas/service/SimpleCache.java @@ -0,0 +1,84 @@ +package org.apache.atlas.service; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ThreadLocalRandom; + +/** + * A simple, thread-safe cache implementation with TTL-based expiration and jitter. + * Jitter is added to the TTL to prevent the "thundering herd" problem by spreading out expirations. + * Uses ConcurrentHashMap for thread safety without explicit locking. + */ +public class SimpleCache { + private final ConcurrentHashMap> cache = new ConcurrentHashMap<>(); + private final long ttlMs; + private final boolean hasTtl; + + // NEW: Jitter factor (e.g., 0.2 means +/- 20% of the TTL) + private static final double JITTER_FACTOR = 0.2; + + /** + * Creates a new SimpleCache instance. + * * @param ttlMs TTL in milliseconds. If null or <= 0, entries never expire. + */ + public SimpleCache(Long ttlMs) { + this.ttlMs = ttlMs != null ? ttlMs : 0; + this.hasTtl = ttlMs != null && ttlMs > 0; + } + + /** + * Gets a value from the cache if present and not expired. + * * @param key the cache key + * @return the cached value, or null if not present or expired + */ + public V getIfPresent(K key) { + CacheEntry entry = cache.get(key); + if (entry == null) { + return null; + } + + if (entry.isExpired()) { + // Lazy expiration - remove expired entry + cache.remove(key, entry); + return null; + } + + return entry.getValue(); + } + + /** + * Puts a value into the cache, calculating its expiration time with jitter. + * * @param key the cache key + * @param value the value to cache + */ + public void put(K key, V value) { + long expirationTime = calculateExpirationTime(); + cache.put(key, new CacheEntry<>(value, expirationTime)); + } + + /** + * NEW: Helper method to calculate the expiration timestamp with jitter. + * @return The calculated expiration timestamp in milliseconds. + */ + private long calculateExpirationTime() { + if (!hasTtl) { + return Long.MAX_VALUE; // Never expires + } + + // Calculate the jitter range (e.g., for 1000ms TTL and 0.2 factor, range is +/- 200ms) + long jitterRange = (long) (this.ttlMs * JITTER_FACTOR); + + // Generate a random jitter value within [-jitterRange, +jitterRange] + long jitter = ThreadLocalRandom.current().nextLong(-jitterRange, jitterRange + 1); + + return System.currentTimeMillis() + this.ttlMs + jitter; + } + + /** + * Removes a value from the cache. + * * @param key the cache key to remove + */ + public void invalidate(K key) { + cache.remove(key); + } + +} \ No newline at end of file diff --git a/common/src/main/java/org/apache/atlas/service/metrics/MetricUtils.java b/common/src/main/java/org/apache/atlas/service/metrics/MetricUtils.java new file mode 100644 index 00000000000..d74e72c10e2 --- /dev/null +++ b/common/src/main/java/org/apache/atlas/service/metrics/MetricUtils.java @@ -0,0 +1,122 @@ +package org.apache.atlas.service.metrics; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.Metrics; +import io.micrometer.core.instrument.Tags; +import io.micrometer.core.instrument.Timer; +import io.micrometer.prometheus.PrometheusConfig; +import io.micrometer.prometheus.PrometheusMeterRegistry; +import org.apache.atlas.ApplicationProperties; +import org.apache.atlas.AtlasException; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.stream.Collectors; + +import static org.apache.commons.lang.StringUtils.EMPTY; + +@Component +public class MetricUtils { + private final static Logger LOG = LoggerFactory.getLogger(MetricUtils.class); + + private static final String URI = "uri"; + private static final String LOCAL = "local"; + private static final String STATUS = "status"; + private static final String METHOD = "method"; + private static final String SERVICE = "service"; + private static final String INTEGRATION = "integration"; + private static final String ATLAS_METASTORE = "atlas-metastore"; + private static final String REGEX_URI_PLACEHOLDER = "\\[\\^/\\]\\+"; + private static final String HTTP_SERVER_REQUESTS = "http.server.requests"; + private static final String ATLAS_METRICS_URI_PATTERNS = "atlas.metrics.uri_patterns"; + private static final double[] PERCENTILES = {0.5, 0.90, 0.99}; + + // Redis metrics constants + private static final String REDIS_CONNECTION_FAILURES = "redis.connection.failures"; + + private static Map METRIC_URI_PATTERNS_MAP; + private static final PrometheusMeterRegistry METER_REGISTRY; + + static { + try { + METRIC_URI_PATTERNS_MAP = Arrays.stream(ApplicationProperties.get().getStringArray(ATLAS_METRICS_URI_PATTERNS)) + .distinct().collect(Collectors.toMap(uri->uri, uri->uri.replaceAll(REGEX_URI_PLACEHOLDER, "*"))); + } catch (Exception e) { + LOG.error("Failed to load 'atlas.metrics.uri_patterns from properties"); + } + METER_REGISTRY = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT); + METER_REGISTRY.config().withHighCardinalityTagsDetector().commonTags(SERVICE, ATLAS_METASTORE, INTEGRATION, LOCAL); + Metrics.globalRegistry.add(METER_REGISTRY); + } + + public Timer.Sample start(String uri) { + return matchCanonicalPattern(uri).isPresent() ? Timer.start(getMeterRegistry()) : null; + } + + public void recordHttpTimer(Timer.Sample sample, String method, String rawPath, int code, String... additionalTags) { + if (Objects.isNull(sample)) { + return; + } + sample.stop(getTimer(HTTP_SERVER_REQUESTS, method, code, rawPath, additionalTags)); + } + + private Timer getTimer(String timerName, String method, int code, String rawPath, String... additionalTags) { + Tags tags = getTags(method, code, rawPath); + if (Objects.nonNull(additionalTags) && additionalTags.length > 0) { + tags = tags.and(additionalTags); + } + return Timer.builder(timerName) + .publishPercentiles(PERCENTILES) + .tags(tags) + .register(getMeterRegistry()); + } + + private Tags getTags(String httpMethod, int httpResponseStatus, String uri) { + return Tags.of(METHOD, httpMethod, + STATUS, String.valueOf(httpResponseStatus), + URI, matchCanonicalPattern(uri).get()); + } + + public static Optional matchCanonicalPattern(String uri) { + if (Objects.isNull(uri) || uri.isEmpty()) { + return Optional.empty(); + } + if (uri.endsWith("/")) { + uri = uri.substring(0, uri.lastIndexOf("/")); + } + String updatedUrl = uri; + Optional patternOp = METRIC_URI_PATTERNS_MAP.keySet().stream() + .filter(pattern -> updatedUrl.matches(pattern + "$")) + .findFirst(); + return Optional.ofNullable(METRIC_URI_PATTERNS_MAP.get(patternOp.orElse(EMPTY))); + } + + public static PrometheusMeterRegistry getMeterRegistry() { + return METER_REGISTRY; + } + + // ================================= + // Redis Metrics Integration + // ================================= + + /** + * Record Redis connection failure + */ + public static void recordRedisConnectionFailure() { + try { + Counter.builder(REDIS_CONNECTION_FAILURES) + .description("Total count of Redis connection failures") + .tags(Tags.of(SERVICE, ATLAS_METASTORE, INTEGRATION, LOCAL)) + .register(METER_REGISTRY) + .increment(); + } catch (Exception e) { + LOG.warn("Failed to record Redis connection failure metric", e); + } + } + + + +} diff --git a/common/src/main/java/org/apache/atlas/service/metrics/MetricsRegistry.java b/common/src/main/java/org/apache/atlas/service/metrics/MetricsRegistry.java new file mode 100644 index 00000000000..60c1553f9c5 --- /dev/null +++ b/common/src/main/java/org/apache/atlas/service/metrics/MetricsRegistry.java @@ -0,0 +1,17 @@ +package org.apache.atlas.service.metrics; + +import org.apache.atlas.utils.AtlasPerfMetrics; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.List; + +public interface MetricsRegistry { + + void collect(String requestId, String requestUri, AtlasPerfMetrics metrics, String clientOrigin); + + void collectApplicationMetrics(String requestId, String requestUri, List applicationMetrics); + + void scrape(PrintWriter writer) throws IOException; + +} diff --git a/common/src/main/java/org/apache/atlas/service/metrics/MetricsRegistryServiceImpl.java b/common/src/main/java/org/apache/atlas/service/metrics/MetricsRegistryServiceImpl.java new file mode 100644 index 00000000000..e11fc5725fa --- /dev/null +++ b/common/src/main/java/org/apache/atlas/service/metrics/MetricsRegistryServiceImpl.java @@ -0,0 +1,129 @@ +package org.apache.atlas.service.metrics; + +import io.micrometer.core.instrument.*; +import io.micrometer.prometheus.PrometheusMeterRegistry; +import org.apache.atlas.ApplicationProperties; +import org.apache.atlas.AtlasException; +import org.apache.atlas.utils.AtlasMetricType; +import org.apache.atlas.utils.AtlasPerfMetrics; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import java.io.IOException; +import java.io.PrintWriter; +import java.time.Duration; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import static org.apache.atlas.service.metrics.MetricUtils.getMeterRegistry; + + +@Component +public class MetricsRegistryServiceImpl implements MetricsRegistry { + + private static final Logger LOG = LoggerFactory.getLogger(MetricsRegistryServiceImpl.class); + + private static final String NAME = "name"; + private static final String URI = "uri"; + private static final String ORIGIN = "origin"; + private static final String METHOD_DIST_SUMMARY = "method_dist_summary"; + private static final String APPLICATION_LEVEL_METRICS_SUMMARY = "application_level_metrics_summary"; + private static final double[] PERCENTILES = {0.99}; + private static final String METHOD_LEVEL_METRICS_ENABLE = "atlas.metrics.method_level.enable"; + private static final String ATLAS_METRICS_METHOD_PATTERNS = "atlas.metrics.method_patterns"; + private final List filteredMethods; + + @Inject + public MetricsRegistryServiceImpl() throws AtlasException { + this.filteredMethods = Arrays.stream(ApplicationProperties.get().getStringArray(ATLAS_METRICS_METHOD_PATTERNS)).collect(Collectors.toList()); + } + + @Override + public void collect(String requestId, String requestUri, AtlasPerfMetrics metrics, String clientOrigin) { + try { + if (!ApplicationProperties.get().getBoolean(METHOD_LEVEL_METRICS_ENABLE, false)) { + return; + } + + for (String name : this.filteredMethods) { + if(metrics.hasMetric(name)) { + AtlasPerfMetrics.Metric metric = metrics.getMetric(name); + Timer.builder(METHOD_DIST_SUMMARY).tags(Tags.of(NAME, metric.getName(), URI, requestUri, ORIGIN, clientOrigin)).publishPercentiles(PERCENTILES) + .register(getMeterRegistry()).record(metric.getTotalTimeMSecs(), TimeUnit.MILLISECONDS); + } + } + } catch (Exception e) { + LOG.error("Failed to collect metrics", e); + return; + } + } + //Use this if you want to publish Histograms + public void collectApplicationMetrics(String requestId, String requestUri, List applicationMetrics){ + try { + for(AtlasPerfMetrics.Metric metric : applicationMetrics){ + if (metric.getMetricType() == AtlasMetricType.COUNTER) { + Counter.builder(metric.getName()) + .tags(convertToMicrometerTags(metric.getTags())) + .register(getMeterRegistry()) + .increment(metric.getInvocations()); + } else { + Timer.builder(APPLICATION_LEVEL_METRICS_SUMMARY) + .serviceLevelObjectives( + Duration.ofMillis(500), + Duration.ofMillis(750), + Duration.ofMillis(1000), + Duration.ofMillis(1200), + Duration.ofMillis(1500), + Duration.ofSeconds(2), + Duration.ofSeconds(3), + Duration.ofSeconds(4), + Duration.ofSeconds(5), + Duration.ofSeconds(7), + Duration.ofSeconds(10), + Duration.ofSeconds(15), + Duration.ofSeconds(20), + Duration.ofSeconds(25), + Duration.ofSeconds(30), + Duration.ofSeconds(40), + Duration.ofSeconds(60), + Duration.ofSeconds(90), + Duration.ofSeconds(120), + Duration.ofSeconds(180) + ) + .publishPercentiles(PERCENTILES) + .tags(convertToMicrometerTags(metric.getTags())) + .register(getMeterRegistry()).record(metric.getTotalTimeMSecs(), TimeUnit.MILLISECONDS); + } + } + } catch (Exception e) { + LOG.error("Failed to collect metrics", e); + return; + } + } + + private static Iterable convertToMicrometerTags(Map tagsMap) { + return tagsMap.entrySet().stream() + .map(entry -> Tag.of(entry.getKey(), entry.getValue())) + .collect(Collectors.toList()); + } + + @Override + public void scrape(PrintWriter writer) { + Metrics.globalRegistry.getRegistries().forEach(r -> { + try { + ((PrometheusMeterRegistry) r).scrape(writer); + writer.flush(); + } catch (IOException e) { + LOG.warn("Failed to write metrics while scraping", e); + } finally { + writer.close(); + } + }); + } + +} diff --git a/common/src/main/java/org/apache/atlas/service/redis/AbstractRedisService.java b/common/src/main/java/org/apache/atlas/service/redis/AbstractRedisService.java new file mode 100644 index 00000000000..e729643d7e7 --- /dev/null +++ b/common/src/main/java/org/apache/atlas/service/redis/AbstractRedisService.java @@ -0,0 +1,352 @@ +package org.apache.atlas.service.redis; + +import org.apache.atlas.ApplicationProperties; +import org.apache.atlas.AtlasException; +import org.apache.atlas.service.metrics.MetricUtils; +import org.apache.commons.configuration.Configuration; +import org.apache.commons.lang.ArrayUtils; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.redisson.config.Config; +import org.redisson.config.ReadMode; + +import javax.annotation.PreDestroy; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; + +public abstract class AbstractRedisService implements RedisService { + + private static final String REDIS_URL_PREFIX = "redis://"; + private static final String ATLAS_REDIS_URL = "atlas.redis.url"; + private static final String ATLAS_REDIS_SENTINEL_URLS = "atlas.redis.sentinel.urls"; + private static final String ATLAS_REDIS_USERNAME = "atlas.redis.username"; + private static final String ATLAS_REDIS_PASSWORD = "atlas.redis.password"; + private static final String ATLAS_REDIS_MASTER_NAME = "atlas.redis.master_name"; + private static final String ATLAS_REDIS_LOCK_WAIT_TIME_MS = "atlas.redis.lock.wait_time.ms"; + private static final String ATLAS_REDIS_LOCK_WATCHDOG_TIMEOUT_MS = "atlas.redis.lock.watchdog_timeout.ms"; + private static final String ATLAS_REDIS_LEASE_TIME_MS = "atlas.redis.lease_time.ms"; + private static final String CHECK_SENTINELS_LIST = "atlas.redis.sentinel.check_list.enabled"; + private static final int DEFAULT_REDIS_WAIT_TIME_MS = 15_000; + private static final int DEFAULT_REDIS_LOCK_WATCHDOG_TIMEOUT_MS = 600_000; + private static final int DEFAULT_REDIS_LEASE_TIME_MS = 60_000; + private static final String ATLAS_METASTORE_SERVICE = "atlas-metastore-service"; + // Heartbeat monitoring for lock health checking (not for renewal) + private final ScheduledExecutorService heartbeatExecutor = Executors.newScheduledThreadPool(1); + private final long HEARTBEAT_INTERVAL_MS = 30000; // 30 seconds - only for health monitoring + private final Map activeLocks = new ConcurrentHashMap<>(); + + RedissonClient redisClient; + RedissonClient redisCacheClient; + Map keyLockMap; + Configuration atlasConfig; + long waitTimeInMS; + long leaseTimeInMS; + long watchdogTimeoutInMS; + boolean checkSentinelsList; + + // Inner class to track lock information + private static class LockInfo { + final RLock lock; + final long lockAcquiredTime; + final String ownerThreadName; + volatile ScheduledFuture healthCheckTask; + + LockInfo(RLock lock, String ownerThreadName) { + this.lock = lock; + this.lockAcquiredTime = System.currentTimeMillis(); + this.ownerThreadName = ownerThreadName; + } + } + + @Override + public boolean acquireDistributedLock(String key) throws Exception { + getLogger().info("Attempting to acquire distributed lock for {}, host:{}", key, getHostAddress()); + RLock lock = redisClient.getFairLock(key); + String currentThreadName = Thread.currentThread().getName(); + try { + // Redisson automatically handles lock renewal via its watchdog mechanism + // when leaseTime is -1 (which is the default for tryLock without leaseTime) + boolean isLockAcquired = lock.tryLock(waitTimeInMS, TimeUnit.MILLISECONDS); + if (isLockAcquired) { + getLogger().info("Lock with key {} is acquired, host: {}, thread: {}", key, getHostAddress(), currentThreadName); + + // Store lock information + keyLockMap.put(key, lock); + LockInfo lockInfo = new LockInfo(lock, currentThreadName); + activeLocks.put(key, lockInfo); + + // Start health monitoring (not renewal - Redisson handles that automatically) + ScheduledFuture healthCheckTask = heartbeatExecutor.scheduleAtFixedRate(() -> { + monitorLockHealth(key, lockInfo); + }, HEARTBEAT_INTERVAL_MS, HEARTBEAT_INTERVAL_MS, TimeUnit.MILLISECONDS); + lockInfo.healthCheckTask = healthCheckTask; + } else { + getLogger().info("Attempt failed as fair lock {} is already acquired, host: {}", key, getHostAddress()); + } + return isLockAcquired; + } catch (InterruptedException e) { + getLogger().error("Failed to acquire distributed lock for {}, host: {}", key, getHostAddress(), e); + throw new AtlasException(e); + } + } + // Health monitoring method - does not attempt to renew locks + private void monitorLockHealth(String key, LockInfo lockInfo) { + try { + RLock lock = lockInfo.lock; + if (lock != null && lock.isLocked()) { + long lockDuration = System.currentTimeMillis() - lockInfo.lockAcquiredTime; + getLogger().debug("Lock health check for {}: locked for {} ms, owner: {}", + key, lockDuration, lockInfo.ownerThreadName); + } else { + // Lock is no longer held, cleanup monitoring + getLogger().debug("Lock {} is no longer held, stopping health monitoring", key); + cleanupLockMonitoring(key); + } + } catch (Exception e) { + getLogger().warn("Health check failed for lock {}", key, e); + } + } + + @Override + public Lock acquireDistributedLockV2(String key) throws Exception { + getLogger().info("Attempting to acquire distributed lock for {}, host:{}", key, getHostAddress()); + RLock lock = null; + try { + lock = redisClient.getFairLock(key); + // Use Redisson's automatic renewal by not specifying leaseTime + boolean isLockAcquired = lock.tryLock(waitTimeInMS, TimeUnit.MILLISECONDS); + if (isLockAcquired) { + getLogger().info("Lock with key {} is acquired, host: {}.", key, getHostAddress()); + return lock; + } else { + getLogger().info("Attempt failed as fair lock {} is already acquired, host: {}.", key, getHostAddress()); + return null; + } + + } catch (InterruptedException e) { + getLogger().error("Failed to acquire distributed lock for {}, host: {}", key, getHostAddress(), e); + if (lock != null && lock.isHeldByCurrentThread()) { + lock.unlock(); + } + throw new AtlasException(e); + } + } + + + @Override + public void releaseDistributedLock(String key) { + if (!keyLockMap.containsKey(key)) { + return; + } + try { + RLock lock = keyLockMap.get(key); + if (lock != null && lock.isHeldByCurrentThread()) { + lock.unlock(); + getLogger().info("Released distributed lock for {}", key); + } + // Cleanup monitoring and tracking + cleanupLockMonitoring(key); + keyLockMap.remove(key); + + } catch (Exception e) { + getLogger().error("Failed to release distributed lock for {}", key, e); + } + } + + // Thread-safe cleanup of lock monitoring + private void cleanupLockMonitoring(String key) { + LockInfo lockInfo = activeLocks.remove(key); + if (lockInfo != null && lockInfo.healthCheckTask != null) { + lockInfo.healthCheckTask.cancel(false); + } + } + + @Override + public void releaseDistributedLockV2(Lock lock, String key) { + try { + if (lock != null) { + lock.unlock(); + } + } catch (Exception e) { + getLogger().error("Failed to release distributed lock for {}", key, e); + } + } + + @Override + public String getValue(String key) { + try { + return (String) redisCacheClient.getBucket(convertToNamespace(key)).get(); + } catch (Exception e) { + MetricUtils.recordRedisConnectionFailure(); + getLogger().error("Redis getValue operation failed for key: {}", key, e); + throw e; + } + } + + @Override + public String putValue(String key, String value) { + try { + // Put the value in the redis cache with TTL + redisCacheClient.getBucket(convertToNamespace(key)).set(value); + return value; + } catch (Exception e) { + MetricUtils.recordRedisConnectionFailure(); + getLogger().warn("Redis putValue operation failed for key: {}", key, e); + throw e; + } + } + + @Override + public String putValue(String key, String value, int timeout) { + try { + // Put the value in the redis cache with TTL + redisCacheClient.getBucket(convertToNamespace(key)).set(value, timeout, TimeUnit.SECONDS); + return value; + } catch (Exception e) { + MetricUtils.recordRedisConnectionFailure(); + getLogger().warn("Redis putValue with TTL operation failed for key: {}", key, e); + throw e; + } + } + + @Override + public void removeValue(String key) { + try { + // Remove the value from the redis cache + redisCacheClient.getBucket(convertToNamespace(key)).delete(); + } catch (Exception e) { + MetricUtils.recordRedisConnectionFailure(); + getLogger().warn("Redis removeValue operation failed for key: {}", key, e); + throw e; + } + } + + private String getHostAddress() throws UnknownHostException { + return InetAddress.getLocalHost().getHostAddress(); + } + + private Config initAtlasConfig() throws AtlasException { + keyLockMap = new ConcurrentHashMap<>(); + atlasConfig = ApplicationProperties.get(); + waitTimeInMS = atlasConfig.getLong(ATLAS_REDIS_LOCK_WAIT_TIME_MS, DEFAULT_REDIS_WAIT_TIME_MS); + leaseTimeInMS = atlasConfig.getLong(ATLAS_REDIS_LEASE_TIME_MS, DEFAULT_REDIS_LEASE_TIME_MS); + watchdogTimeoutInMS = atlasConfig.getLong(ATLAS_REDIS_LOCK_WATCHDOG_TIMEOUT_MS, DEFAULT_REDIS_LOCK_WATCHDOG_TIMEOUT_MS); + checkSentinelsList = atlasConfig.getBoolean(CHECK_SENTINELS_LIST, true); + Config redisConfig = new Config(); + redisConfig.setLockWatchdogTimeout(watchdogTimeoutInMS); + return redisConfig; + } + + private String convertToNamespace(String key){ + // Append key with namespace :atlas + return "atlas:"+key; + } + + Config getLocalConfig() throws AtlasException { + Config config = initAtlasConfig(); + config.useSingleServer() + .setAddress(formatUrls(atlasConfig.getStringArray(ATLAS_REDIS_URL))[0]) + .setUsername(atlasConfig.getString(ATLAS_REDIS_USERNAME)) + .setPassword(atlasConfig.getString(ATLAS_REDIS_PASSWORD)); + return config; + } + + Config getProdConfig() throws AtlasException { + Config config = initAtlasConfig(); + config.useSentinelServers() + .setClientName(ATLAS_METASTORE_SERVICE) + .setReadMode(ReadMode.MASTER_SLAVE) + .setCheckSentinelsList(false) + .setKeepAlive(true) + .setMasterConnectionMinimumIdleSize(10) + .setMasterConnectionPoolSize(20) + .setSlaveConnectionMinimumIdleSize(10) + .setSlaveConnectionPoolSize(20) + .setMasterName(atlasConfig.getString(ATLAS_REDIS_MASTER_NAME)) + .addSentinelAddress(formatUrls(atlasConfig.getStringArray(ATLAS_REDIS_SENTINEL_URLS))) + .setUsername(atlasConfig.getString(ATLAS_REDIS_USERNAME)) + .setPassword(atlasConfig.getString(ATLAS_REDIS_PASSWORD)); + return config; + } + + Config getCacheImplConfig() { + Config config = new Config(); + config.useSentinelServers() + .setClientName(ATLAS_METASTORE_SERVICE+"-redisCache") + .setReadMode(ReadMode.MASTER_SLAVE) + .setCheckSentinelsList(checkSentinelsList) + .setKeepAlive(true) + .setMasterConnectionMinimumIdleSize(5) + .setMasterConnectionPoolSize(5) + .setSlaveConnectionMinimumIdleSize(5) + .setSlaveConnectionPoolSize(5) + .setMasterName(atlasConfig.getString(ATLAS_REDIS_MASTER_NAME)) + .addSentinelAddress(formatUrls(atlasConfig.getStringArray(ATLAS_REDIS_SENTINEL_URLS))) + .setUsername(atlasConfig.getString(ATLAS_REDIS_USERNAME)) + .setPassword(atlasConfig.getString(ATLAS_REDIS_PASSWORD)) + .setTimeout(50) //Setting UP timeout to 50ms + .setRetryAttempts(10); //Retry 10 times; + return config; + } + + private String[] formatUrls(String[] urls) throws IllegalArgumentException { + if (ArrayUtils.isEmpty(urls)) { + getLogger().error("Invalid redis cluster urls"); + throw new IllegalArgumentException("Invalid redis cluster urls"); + } + return Arrays.stream(urls).map(url -> { + if (url.startsWith(REDIS_URL_PREFIX)) { + return url; + } + return REDIS_URL_PREFIX + url; + }).toArray(String[]::new); + } + + @PreDestroy + public void flushLocks(){ + // Cancel all health check tasks + activeLocks.values().forEach(lockInfo -> { + if (lockInfo.healthCheckTask != null) { + lockInfo.healthCheckTask.cancel(false); + } + }); + activeLocks.clear(); + + // Release all locks held by current thread + keyLockMap.entrySet().removeIf(entry -> { + String key = entry.getKey(); + RLock lock = entry.getValue(); + try { + if (lock != null && lock.isHeldByCurrentThread()) { + lock.unlock(); + getLogger().info("Released lock {} during shutdown", key); + return true; + } + } catch (Exception e) { + getLogger().warn("Failed to release lock {} during shutdown", key, e); + } + return false; + }); + + // Shutdown the health monitoring executor + heartbeatExecutor.shutdown(); + try { + if (!heartbeatExecutor.awaitTermination(5, TimeUnit.SECONDS)) { + getLogger().warn("Health monitoring executor did not terminate gracefully, forcing shutdown"); + heartbeatExecutor.shutdownNow(); + } + } catch (InterruptedException e) { + getLogger().warn("Interrupted while waiting for health monitoring executor shutdown"); + heartbeatExecutor.shutdownNow(); + Thread.currentThread().interrupt(); + } + } +} \ No newline at end of file diff --git a/common/src/main/java/org/apache/atlas/service/redis/RedisService.java b/common/src/main/java/org/apache/atlas/service/redis/RedisService.java new file mode 100644 index 00000000000..083793ea71e --- /dev/null +++ b/common/src/main/java/org/apache/atlas/service/redis/RedisService.java @@ -0,0 +1,27 @@ +package org.apache.atlas.service.redis; + +import org.slf4j.Logger; + +import java.util.concurrent.locks.Lock; + +public interface RedisService { + + boolean acquireDistributedLock(String key) throws Exception; + + Lock acquireDistributedLockV2(String key) throws Exception; + + void releaseDistributedLock(String key); + + void releaseDistributedLockV2(Lock lock, String key); + + String getValue(String key); + + String putValue(String key, String value); + + String putValue(String key, String value, int timeout); + + void removeValue(String key); + + Logger getLogger(); + +} diff --git a/common/src/main/java/org/apache/atlas/service/redis/RedisServiceImpl.java b/common/src/main/java/org/apache/atlas/service/redis/RedisServiceImpl.java new file mode 100644 index 00000000000..67b33c9f565 --- /dev/null +++ b/common/src/main/java/org/apache/atlas/service/redis/RedisServiceImpl.java @@ -0,0 +1,94 @@ +package org.apache.atlas.service.redis; + +import org.apache.atlas.AtlasException; +import org.apache.atlas.service.metrics.MetricUtils; +import org.redisson.Redisson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; + +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class RedisServiceImpl extends AbstractRedisService { + + private static final Logger LOG = LoggerFactory.getLogger(RedisServiceImpl.class); + private static final long RETRY_DELAY_MS = 1000L; + + @PostConstruct + public void init() throws InterruptedException { + LOG.info("==> RedisServiceImpl.init() - Starting Redis service initialization."); + + // This loop will block the main application thread until a connection is successful. + while (true) { + try { + LOG.info("Attempting to connect to Redis..."); + + redisClient = Redisson.create(getProdConfig()); + redisCacheClient = Redisson.create(getCacheImplConfig()); + + if (redisClient == null || redisCacheClient == null) { + throw new AtlasException("Failed to create Sentinel redis client."); + } + + // Test basic connectivity to ensure clients are working. + testRedisConnectivity(); + + LOG.info("RedisServiceImpl initialization completed successfully!"); + break; + } catch (Exception e) { + LOG.warn("Redis connection failed: {}. Application startup is BLOCKED. Retrying in {} seconds...", e.getMessage(), RETRY_DELAY_MS / 1000); + MetricUtils.recordRedisConnectionFailure(); + // Clean up any partially created clients before retrying. + shutdownClients(); + Thread.sleep(RETRY_DELAY_MS); + } + } + } + + /** + * Test Redis connectivity with basic operations + */ + private void testRedisConnectivity() throws Exception { + String testKey = "atlas:startup:connectivity:test:" + System.currentTimeMillis(); + String testValue = "connectivity-test"; + + try { + // Test cache client + LOG.debug("Testing Redis cache client connectivity"); + redisCacheClient.getBucket(testKey).set(testValue); + String retrievedValue = (String) redisCacheClient.getBucket(testKey).get(); + + if (!testValue.equals(retrievedValue)) { + throw new RuntimeException("Redis cache client connectivity test failed - value mismatch"); + } + + redisCacheClient.getBucket(testKey).delete(); + LOG.debug("Redis connectivity test completed successfully"); + + } catch (Exception e) { + MetricUtils.recordRedisConnectionFailure(); + throw new Exception("Redis connectivity test failed", e); + } + } + + private void shutdownClients() { + if (redisClient != null && !redisClient.isShutdown()) { + redisClient.shutdown(); + } + if (redisCacheClient != null && !redisCacheClient.isShutdown()) { + redisCacheClient.shutdown(); + } + redisClient = null; + redisCacheClient = null; + } + + @Override + public Logger getLogger() { + return LOG; + } + +} diff --git a/common/src/main/java/org/apache/atlas/utils/AtlasMetricType.java b/common/src/main/java/org/apache/atlas/utils/AtlasMetricType.java new file mode 100644 index 00000000000..6752b7fbd4d --- /dev/null +++ b/common/src/main/java/org/apache/atlas/utils/AtlasMetricType.java @@ -0,0 +1,9 @@ +package org.apache.atlas.utils; + +public enum AtlasMetricType { + COUNTER, + GAUGE, + HISTOGRAM, + METER, + TIMER +} diff --git a/common/src/main/java/org/apache/atlas/utils/AtlasPerfMetrics.java b/common/src/main/java/org/apache/atlas/utils/AtlasPerfMetrics.java index c72b2c3e25a..46933f09a28 100644 --- a/common/src/main/java/org/apache/atlas/utils/AtlasPerfMetrics.java +++ b/common/src/main/java/org/apache/atlas/utils/AtlasPerfMetrics.java @@ -19,6 +19,7 @@ package org.apache.atlas.utils; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; @@ -33,8 +34,8 @@ public MetricRecorder getMetricRecorder(String name) { public void recordMetric(MetricRecorder recorder) { if (recorder != null) { - final String name = recorder.name; - final long timeTaken = recorder.getElapsedTime(); + final String name = recorder.name; + final long timeTaken = recorder.getElapsedTime(); Metric metric = metrics.get(name); @@ -49,6 +50,23 @@ public void recordMetric(MetricRecorder recorder) { } } + public void recordMetric(MetricRecorder recorder, long invocations) { + if (recorder != null) { + final String name = recorder.name; + final long timeTaken = recorder.getElapsedTime(); + Metric metric = metrics.get(name); + + if (metric == null) { + metric = new Metric(name); + + metrics.put(name, metric); + } + + metric.invocations += invocations; + metric.totalTimeMSecs += timeTaken; + } + } + public void clear() { metrics.clear(); } @@ -65,6 +83,10 @@ public Metric getMetric(String name) { return metrics.get(name); } + public boolean hasMetric(String name) { + return metrics.containsKey(name); + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -86,7 +108,7 @@ public String toString() { public class MetricRecorder { private final String name; - private final long startTimeMs = System.currentTimeMillis(); + private final long startTimeMs = System.currentTimeMillis(); MetricRecorder(String name) { this.name = name; @@ -99,23 +121,53 @@ long getElapsedTime() { public static class Metric { private final String name; - private short invocations = 0; - private long totalTimeMSecs = 0; + + private AtlasMetricType metricType; + private long invocations = 0; + private long totalTimeMSecs = 0; + HashMap tags = new HashMap<>(); public Metric(String name) { this.name = name; } + public void setMetricType(AtlasMetricType metricType) { + this.metricType = metricType; + } + + public AtlasMetricType getMetricType() { + return metricType; + } + public String getName() { return name; } - public short getInvocations() { + public long getInvocations() { return invocations; } + public void setTotalTimeMSecs(long totalTimeMSecs) { + this.totalTimeMSecs = totalTimeMSecs; + } + public long getTotalTimeMSecs() { return totalTimeMSecs; } + + public void addTag(String key, String value) { + tags.put(key, value); + } + public HashMap getTags() { + return tags; + } + + public void incrementInvocations() { + invocations++; + } + + public void setInvocations(long invocations) { + this.invocations = invocations; + } } } diff --git a/common/src/main/java/org/apache/atlas/utils/AtlasPerfTracer.java b/common/src/main/java/org/apache/atlas/utils/AtlasPerfTracer.java index a2baa65b03b..45bd63cc42c 100644 --- a/common/src/main/java/org/apache/atlas/utils/AtlasPerfTracer.java +++ b/common/src/main/java/org/apache/atlas/utils/AtlasPerfTracer.java @@ -19,6 +19,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.slf4j.MDC; /** @@ -74,7 +75,9 @@ public long getElapsedTime() { public void log() { long elapsedTime = getElapsedTime(); if (elapsedTime > reportingThresholdMs) { - logger.debug("PERF|{}|{}", tag, elapsedTime); + MDC.put("timeTaken", String.valueOf(elapsedTime)); + logger.debug("PERF|{}", tag); + MDC.remove("timeTaken"); } } } diff --git a/common/src/main/java/org/apache/atlas/utils/OnAtlasEnableCondition.java b/common/src/main/java/org/apache/atlas/utils/OnAtlasEnableCondition.java new file mode 100644 index 00000000000..e97db4ce40c --- /dev/null +++ b/common/src/main/java/org/apache/atlas/utils/OnAtlasEnableCondition.java @@ -0,0 +1,52 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.atlas.utils; + +import org.apache.atlas.ApplicationProperties; +import org.apache.atlas.AtlasException; +import org.apache.atlas.annotation.EnableConditional; +import org.apache.commons.configuration.Configuration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +import java.util.Map; + +public class OnAtlasEnableCondition implements Condition { + private final Logger LOG = LoggerFactory.getLogger(OnAtlasEnableCondition.class); + + @Override + public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + boolean matches = false; + Map attributes = metadata.getAnnotationAttributes(EnableConditional.class.getName()); + String propertyName = (String) attributes.get("property"); + if (metadata instanceof AnnotatedTypeMetadata) { + + try { + Configuration configuration = ApplicationProperties.get(); + boolean enabled = configuration.getBoolean(propertyName, (boolean) attributes.get("isDefault")); + return enabled; + } catch (AtlasException e) { + LOG.error("Unable to load atlas properties. Dependent bean configuration may fail"); + } + } + return false; + } +} \ No newline at end of file diff --git a/common/src/test/resources/atlas-log4j.xml b/common/src/test/resources/atlas-log4j.xml deleted file mode 100644 index 4f1551857fd..00000000000 --- a/common/src/test/resources/atlas-log4j.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/common/src/test/resources/atlas-logback.xml b/common/src/test/resources/atlas-logback.xml new file mode 100644 index 00000000000..d82bfa8c308 --- /dev/null +++ b/common/src/test/resources/atlas-logback.xml @@ -0,0 +1,54 @@ + + + + + + + + %date [%thread] %level{5} [%file:%line] %msg%n + + + INFO + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/common/src/test/resources/log4j.properties b/common/src/test/resources/log4j.properties deleted file mode 100644 index d62cf804502..00000000000 --- a/common/src/test/resources/log4j.properties +++ /dev/null @@ -1,34 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You 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. - -# A1 is set to be a FileAppender. -log4j.appender.A1=org.apache.log4j.FileAppender -log4j.appender.A1.File=target/test.log -log4j.appender.A1.Threshold=ALL -# A1 uses PatternLayout. -log4j.appender.A1.layout=org.apache.log4j.PatternLayout -log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5p %c{2}: %m%n - -# A2 is a ConsoleAppender. -log4j.appender.A2=org.apache.log4j.ConsoleAppender -log4j.appender.A2.Threshold=ALL -# A2 uses PatternLayout. -log4j.appender.A2.layout=org.apache.log4j.PatternLayout -log4j.appender.A2.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5p %c{2}: %m%n - -# Set both appenders (A1 and A2) on the root logger. -#log4j.rootLogger=INFO, A1, A2 -log4j.rootLogger=ERROR, A1 diff --git a/common/src/test/resources/logback.xml b/common/src/test/resources/logback.xml new file mode 100644 index 00000000000..bcd075b660a --- /dev/null +++ b/common/src/test/resources/logback.xml @@ -0,0 +1,43 @@ + + + + + + + + %date [%thread] %level{5} [%file:%line] %msg%n + + + INFO + + + + + target/test.log + true + + %date [%thread] %level{5} [%file:%line] %msg%n + + + + + + + + diff --git a/dashboardv2/.gitignore b/dashboardv2/.gitignore deleted file mode 100644 index f75b10dfa1b..00000000000 --- a/dashboardv2/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -.DS_Store -.bower-*/ -.idea/ -node_modules/ -public/js/libs/ -dist -target/ -*.log -*.tgz -node/ -.npmrc -dist/ -!public/js/external_lib/atlas-lineage/dist \ No newline at end of file diff --git a/dashboardv2/gruntfile.js b/dashboardv2/gruntfile.js deleted file mode 100644 index fa79a157242..00000000000 --- a/dashboardv2/gruntfile.js +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -'use strict'; -var sass = require('node-sass'); -module.exports = function(grunt) { - var buildTime = new Date().getTime(), - distPath = './dist', - libPath = distPath + '/js/libs/', - isDashboardDirectory = grunt.file.isDir('public'), - nodeModulePath = './node_modules/', - modulesPath = 'public/'; - if (!isDashboardDirectory) { - modulesPath = '../public/' - } - - grunt.initConfig({ - watch: { - js: { - files: ['public/**/*.js'], - tasks: ['copy:build'] - }, - html: { - files: ['public/**/*.html'], - tasks: ['copy:build'] - }, - css: { - files: ['public/**/*.scss', 'public/**/*.css'], - tasks: ['copy:build', 'sass'] - }, - image: { - files: ['public/**/*.{ico,gif,png}'], - tasks: ['copy:build'] - } - }, - connect: { - server: { - options: { - port: 9999, - base: distPath, - // change this to '0.0.0.0' to access the server from outside - hostname: '0.0.0.0', - middleware: function(connect, options, middlewares) { - middlewares.unshift(require('grunt-middleware-proxy/lib/Utils').getProxyMiddleware()); - return middlewares; - } - }, - proxies: [{ - context: '/api', // the context of the data service - host: '127.0.0.1', - auth: "admin:admin", - port: 21000, // the port that the data service is running on - https: false - }], - }, - }, - npmcopy: { - js: { - options: { - destPrefix: libPath, - srcPrefix: nodeModulePath - }, - files: { - // FileName : {"src":"dest"} - 'jquery.min.js': { 'jquery/dist': 'jquery/js' }, - 'require.js': { 'requirejs': 'requirejs' }, - 'text.js': { 'requirejs-text': 'requirejs-text' }, - 'underscore-min.js': { 'underscore': 'underscore' }, - 'bootstrap.min.js': { 'bootstrap/dist/js': 'bootstrap/js' }, - 'backbone-min.js': { 'backbone': 'backbone' }, - 'backbone.babysitter.min.js': { 'backbone.babysitter/lib': 'backbone-babysitter' }, - 'backbone.marionette.min.js': { 'backbone.marionette/lib': 'backbone-marionette' }, - 'backbone.paginator.min.js': { 'backbone.paginator/lib': 'backbone-paginator' }, - 'backbone.wreqr.min.js': { 'backbone.wreqr/lib': 'backbone-wreqr' }, - 'backgrid.js': { 'backgrid/lib': 'backgrid/js' }, - 'backgrid-filter.min.js': { 'backgrid-filter': 'backgrid-filter/js' }, - 'backgrid-orderable-columns.js': { 'backgrid-orderable-columns': 'backgrid-orderable-columns/js' }, - 'backgrid-paginator.min.js': { 'backgrid-paginator': 'backgrid-paginator/js' }, - 'backgrid-sizeable-columns.js': { 'backgrid-sizeable-columns': 'backgrid-sizeable-columns/js' }, - 'Backgrid.ColumnManager.js': { 'backgrid-columnmanager/src': 'backgrid-columnmanager/js' }, - 'jquery-asBreadcrumbs.min.js': { 'jquery-asBreadcrumbs/dist': 'jquery-asBreadcrumbs/js' }, - 'd3.min.js': { 'd3/dist': 'd3' }, - 'index.js': { 'd3-tip': 'd3/' }, - 'dagre-d3.min.js': { 'dagre-d3/dist': 'dagre-d3' }, - 'select2.full.min.js': { 'select2/dist/js': 'select2' }, - 'backgrid-select-all.min.js': { 'backgrid-select-all': 'backgrid-select-all' }, - 'moment.min.js': { 'moment/min': 'moment/js' }, - 'moment-timezone-with-data.min.js': { 'moment-timezone/builds': 'moment-timezone' }, - 'jquery.placeholder.js': { 'jquery-placeholder': 'jquery-placeholder/js' }, - 'platform.js': { 'platform': 'platform' }, - 'query-builder.standalone.min.js': { 'jQuery-QueryBuilder/dist/js': 'jQueryQueryBuilder/js' }, - 'daterangepicker.js': { 'bootstrap-daterangepicker': 'bootstrap-daterangepicker/js' }, - 'jquery.sparkline.min.js': { 'jquery-sparkline': 'sparkline' }, - 'table-dragger.js': { 'table-dragger/dist': 'table-dragger' }, - 'jstree.min.js': { 'jstree/dist': 'jstree' }, - 'jquery.steps.min.js': { 'jquery-steps/build': 'jquery-steps' }, - 'dropzone-amd-module.js': { 'dropzone/dist': "dropzone/js" }, - 'lossless-json.js': { 'lossless-json/dist': 'lossless-json' } - } - - }, - css: { - options: { - destPrefix: libPath, - srcPrefix: nodeModulePath - }, - files: { - 'bootstrap.min.css': { 'bootstrap/dist/css': 'bootstrap/css' }, - 'glyphicons-halflings-regular.woff2': { 'bootstrap/fonts': 'bootstrap/fonts' }, - 'backgrid.css': { 'backgrid/lib': 'backgrid/css' }, - 'backgrid-filter.min.css': { 'backgrid-filter': 'backgrid-filter/css' }, - 'backgrid-orderable-columns.css': { 'backgrid-orderable-columns': 'backgrid-orderable-columns/css' }, - 'backgrid-paginator.css': { 'backgrid-paginator': 'backgrid-paginator/css' }, - 'backgrid-sizeable-columns.css': { 'backgrid-sizeable-columns': 'backgrid-sizeable-columns/css' }, - 'Backgrid.ColumnManager.css': { 'backgrid-columnmanager/lib': 'backgrid-columnmanager/css' }, - 'asBreadcrumbs.min.css': { 'jquery-asBreadcrumbs/dist/css': 'jquery-asBreadcrumbs/css' }, - 'select2.min.css': { 'select2/dist/css': 'select2/css' }, - 'backgrid-select-all.min.css': { 'backgrid-select-all': 'backgrid-select-all' }, - 'font-awesome.min.css': { 'font-awesome/css': 'font-awesome/css' }, - '*': [{ - 'expand': true, - 'dot': true, - 'cwd': nodeModulePath + 'font-awesome', - 'src': ['fonts/*.*'], - 'dest': libPath + 'font-awesome/' - }, { - 'expand': true, - 'dot': true, - 'cwd': nodeModulePath + 'jstree/dist/themes/', - 'src': ['**'], - 'dest': libPath + 'jstree/css/' - }], - 'query-builder.default.min.css': { 'jQuery-QueryBuilder/dist/css': 'jQueryQueryBuilder/css' }, - 'daterangepicker.css': { 'bootstrap-daterangepicker': 'bootstrap-daterangepicker/css' }, - 'pretty-checkbox.min.css': { 'pretty-checkbox/dist': 'pretty-checkbox/css' }, - 'dropzone.css': { 'dropzone/dist': "dropzone/css" } - } - - }, - license: { - options: { - destPrefix: libPath, - srcPrefix: nodeModulePath - }, - files: { - 'LICENSE.txt': [ - { 'jquery': 'jquery' }, - { 'jquery-placeholder': 'jquery-placeholder' } - ], - 'LICENSE': [{ 'requirejs-text': 'requirejs-text' }, - { 'underscore': 'underscore' }, - { 'bootstrap': 'bootstrap' }, - { 'backgrid-columnmanager': 'backgrid-columnmanager' }, - { 'jquery-asBreadcrumbs': 'jquery-asBreadcrumbs' }, - { 'd3': 'd3' }, - { 'd3-tip': 'd3/' }, - { 'dagre-d3': 'dagre-d3' }, - { 'platform': 'platform/' }, - { 'jQuery-QueryBuilder': 'jQueryQueryBuilder/' }, - { 'moment-timezone': 'moment-timezone' }, - { 'pretty-checkbox': 'pretty-checkbox' } - ], - 'LICENSE.md': [{ 'backbone.babysitter': 'backbone-babysitter' }, - { 'backbone.wreqr': 'backbone-wreqr' }, - { 'lossless-json': 'lossless-json' } - ], - 'license.txt': [{ 'backbone.marionette': 'backbone-marionette' }], - 'license': [{ 'table-dragger': 'table-dragger' }], - 'LICENSE-MIT': [{ 'backbone.paginator': 'backbone-paginator' }, - { 'backgrid': 'backgrid' }, - { 'backgrid-filter': 'backgrid-filter' }, - { 'backgrid-orderable-columns': 'backgrid-orderable-columns' }, - { 'backgrid-paginator': 'backgrid-paginator' }, - { 'backgrid-sizeable-columns': 'backgrid-sizeable-columns' }, - { 'backgrid-select-all': 'backgrid-select-all' } - ] - } - } - }, - rename: { - main: { - files: [ - { src: [libPath + 'jstree/css/default/style.min.css'], dest: libPath + 'jstree/css/default/default-theme.min.css' }, - { src: [libPath + 'jstree/css/default-dark/style.min.css'], dest: libPath + 'jstree/css/default-dark/default-dark-theme.min.css' }, - ] - } - }, - sass: { - options: { - implementation: sass, - sourceMap: false - }, - build: { - files: { - [distPath + '/css/style.css']: modulesPath + 'css/scss/style.scss', - [distPath + '/css/migration-style.css']: modulesPath + 'css/scss/migration-style.scss', - [distPath + '/css/login.css']: modulesPath + 'css/scss/login.scss' - } - } - }, - copy: { - build: { - expand: true, - cwd: modulesPath, - src: ['**', '!**/scss/**', "!**/atlas-lineage/**", "**/atlas-lineage/dist/**", "!index.html.tpl"], - dest: distPath - } - }, - clean: { - build: [distPath, libPath], - options: { - force: true - } - }, - uglify: { - buildlibs: { - options: { - mangle: true, - compress: true, - beautify: false - }, - files: [{ - expand: true, - cwd: distPath + '/js', - src: ['external_lib/**/*.js', 'libs/**/*.js'], - dest: distPath + '/js' - }] - }, - buildjs: { - options: { - mangle: false, - compress: true, - beautify: true - }, - files: [{ - expand: true, - cwd: distPath + '/js', - src: ['**/*.js', '!libs/**', '!external_lib/**'], - dest: distPath + '/js' - }] - } - }, - cssmin: { - build: { - files: [{ - expand: true, - cwd: distPath + '/css', - src: '*.css', - dest: distPath + '/css' - }] - } - }, - htmlmin: { - build: { - options: { - removeComments: true, - collapseWhitespace: true - }, - files: [{ - expand: true, - cwd: distPath + '/js/templates', - src: '**/*.html', - dest: distPath + '/js/templates' - }] - } - }, - template: { - build: { - options: { - data: { - 'bust': buildTime - } - }, - files: { - [distPath + '/index.html']: [modulesPath + 'index.html.tpl'], - [distPath + '/migration-status.html']: [modulesPath + 'migration-status.html.tpl'] - } - } - } - }); - - // Dynamically add copy-task using npmcopy - var npmCopy = grunt.config.get('npmcopy'), - libFiles = [], - createPath = function(options) { - var obj = options.obj, - fileName = options.fileName, - pathPrefix = options.pathPrefix; - if (obj.length) { - for (var i in obj) { - createPath({ - 'obj': obj[i], - 'libFiles': options.libFiles, - 'pathPrefix': pathPrefix, - 'fileName': fileName - }); - } - } else { - if (fileName == "*") { - options.libFiles.push(obj); - } else { - key = Object.keys(obj); - options.libFiles.push({ 'src': pathPrefix.srcPrefix + key + "/" + fileName, 'dest': pathPrefix.destPrefix + obj[key] + "/" + fileName }); - } - } - }; - - for (var key in npmCopy) { - var options = npmCopy[key].options, - files = npmCopy[key].files; - for (var fileName in files) { - createPath({ - 'obj': files[fileName], - 'libFiles': libFiles, - 'pathPrefix': options, - 'fileName': fileName - }); - } - }; - grunt.config.set('copy.libs', { files: libFiles }); - - grunt.loadNpmTasks('grunt-contrib-connect'); - grunt.loadNpmTasks('grunt-middleware-proxy'); - grunt.loadNpmTasks('grunt-contrib-watch'); - grunt.loadNpmTasks('grunt-contrib-uglify'); - grunt.loadNpmTasks('grunt-contrib-cssmin'); - grunt.loadNpmTasks('grunt-contrib-htmlmin'); - grunt.loadNpmTasks('grunt-template'); - grunt.loadNpmTasks('grunt-contrib-rename'); - - require('load-grunt-tasks')(grunt); - - grunt.registerTask('dev', [ - 'clean', - 'copy:libs', - 'copy:build', - 'rename', - 'sass:build', - 'template', - 'setupProxies:server', - 'connect:server', - 'watch' - ]); - - grunt.registerTask('build', [ - 'clean', - 'copy:libs', - 'copy:build', - 'rename', - 'sass:build', - 'template' - ]); - - grunt.registerTask('dev-minify', [ - 'clean', - 'copy:libs', - 'copy:build', - 'rename', - 'sass:build', - 'uglify', - 'cssmin', - 'template', - 'setupProxies:server', - 'connect:server', - 'watch' - ]); - - grunt.registerTask('build-minify', [ - 'clean', - 'copy:libs', - 'copy:build', - 'rename', - 'sass:build', - 'uglify', - 'cssmin', - 'template' - ]); -}; \ No newline at end of file diff --git a/dashboardv2/package-lock.json b/dashboardv2/package-lock.json deleted file mode 100644 index 61fd944c622..00000000000 --- a/dashboardv2/package-lock.json +++ /dev/null @@ -1,3882 +0,0 @@ -{ - "name": "atlas-metadata", - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - } - }, - "almond": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/almond/-/almond-0.3.3.tgz", - "integrity": "sha1-oOfJWsdiTWQXtElLHmi/9pMWiiA=" - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - }, - "dependencies": { - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - } - } - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "async-foreach": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atoa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atoa/-/atoa-1.0.0.tgz", - "integrity": "sha1-DMDpGkgOc4+SPrwQNnZHF3mzSkk=" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", - "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", - "dev": true - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "backbone": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.2.3.tgz", - "integrity": "sha1-wiz9B/yG676uYdGJKe0RXpmdZbk=", - "requires": { - "underscore": ">=1.7.0" - } - }, - "backbone.babysitter": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/backbone.babysitter/-/backbone.babysitter-0.1.12.tgz", - "integrity": "sha1-fKlGQ07u+94aVTYFx0twSbbfr8E=", - "requires": { - "backbone": ">=0.9.9 <=1.3.x", - "underscore": ">=1.4.0 <=1.8.3" - } - }, - "backbone.marionette": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/backbone.marionette/-/backbone.marionette-2.3.2.tgz", - "integrity": "sha1-9OPGd8n6bIS8bRyJOSIVbV7+ojo=", - "requires": { - "backbone": "1.0.0 - 1.1.2", - "backbone.babysitter": "^0.1.0", - "backbone.wreqr": "^1.0.0", - "underscore": "1.4.4 - 1.6.0" - }, - "dependencies": { - "backbone": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.1.2.tgz", - "integrity": "sha1-wsBMZr+HJo+4LBd6zr7/fTe6by0=", - "requires": { - "underscore": ">=1.5.0" - } - }, - "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" - } - } - }, - "backbone.paginator": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/backbone.paginator/-/backbone.paginator-2.0.5.tgz", - "integrity": "sha1-T9+oJjIDx+7ieqtpYBnTKc1/AG0=", - "requires": { - "backbone": "1.1.2 || 1.2.3 || ^1.3.2", - "underscore": "^1.8.0" - } - }, - "backbone.wreqr": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/backbone.wreqr/-/backbone.wreqr-1.4.0.tgz", - "integrity": "sha1-doIDDJqvCQ7Nhzsh2/SFAWk7JpY=", - "requires": { - "backbone": ">=0.9.9 <=1.3.x", - "underscore": ">=1.3.3 <=1.8.3" - } - }, - "backgrid": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/backgrid/-/backgrid-0.3.8.tgz", - "integrity": "sha1-fSaBZ0LXLIWcrTmxPxnJ8nuv/tc=", - "requires": { - "backbone": "1.1.2 || 1.2.3 || ~1.3.2", - "underscore": "^1.8.0" - } - }, - "backgrid-filter": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/backgrid-filter/-/backgrid-filter-0.3.7.tgz", - "integrity": "sha1-1LGdDnBwE9fxgfnox/67SZfVbwM=", - "requires": { - "backbone": "~1.2.3", - "backgrid": "~0.3.7", - "lunr": "^0.7.0", - "underscore": "^1.8.3" - } - }, - "backgrid-orderable-columns": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/backgrid-orderable-columns/-/backgrid-orderable-columns-0.1.2.tgz", - "integrity": "sha1-hjXt9taG6QsLERLUbt9kEZjG8EI=" - }, - "backgrid-paginator": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/backgrid-paginator/-/backgrid-paginator-0.3.9.tgz", - "integrity": "sha1-2vZhFGwTdmWgqN6ifNrR8jgmk3g=", - "requires": { - "backbone": "1.1.2 || 1.2.3 || ~1.3.2", - "backbone.paginator": "^2.0.5", - "backgrid": "~0.3.7", - "underscore": "^1.8.0" - } - }, - "backgrid-select-all": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/backgrid-select-all/-/backgrid-select-all-0.3.5.tgz", - "integrity": "sha1-FDqADl2V/yrlqE14v0+6QflIHpQ=" - }, - "backgrid-sizeable-columns": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/backgrid-sizeable-columns/-/backgrid-sizeable-columns-0.1.1.tgz", - "integrity": "sha1-7G+lkrJjs5DfHYPlZqSNylA28Cs=" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "~2.0.0" - } - }, - "body": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", - "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", - "dev": true, - "requires": { - "continuable-cache": "^0.3.1", - "error": "^7.0.0", - "raw-body": "~1.1.0", - "safe-json-parse": "~1.0.1" - } - }, - "bootstrap": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz", - "integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA==" - }, - "bootstrap-daterangepicker": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bootstrap-daterangepicker/-/bootstrap-daterangepicker-3.1.0.tgz", - "integrity": "sha512-oaQZx6ZBDo/dZNyXGVi2rx5GmFXThyQLAxdtIqjtLlYVaQUfQALl5JZMJJZzyDIX7blfy4ppZPAJ10g8Ma4d/g==", - "requires": { - "jquery": ">=1.10", - "moment": "^2.9.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", - "dev": true, - "requires": { - "pako": "~0.2.0" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", - "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", - "dev": true - }, - "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", - "dev": true, - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "clean-css": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.0.13.tgz", - "integrity": "sha1-/rKhdgYtcqbD5iTZITysagxIXoA=", - "dev": true, - "requires": { - "source-map": "0.5.x" - } - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "coffeescript": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.10.0.tgz", - "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=", - "dev": true - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "dev": true, - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - } - }, - "connect-livereload": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", - "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "continuable-cache": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", - "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=", - "dev": true - }, - "contra": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/contra/-/contra-1.9.4.tgz", - "integrity": "sha1-9TveQtfltZhcrk2ZqNYQUm3o8o0=", - "requires": { - "atoa": "1.0.0", - "ticky": "1.0.1" - } - }, - "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cross-spawn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", - "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "crossvent": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/crossvent/-/crossvent-1.5.5.tgz", - "integrity": "sha1-rSCHjkkh6b5z2daXb4suzQ9xoLE=", - "requires": { - "custom-event": "^1.0.0" - } - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, - "custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=" - }, - "d3": { - "version": "5.14.2", - "resolved": "https://registry.npmjs.org/d3/-/d3-5.14.2.tgz", - "integrity": "sha512-Ccipa9XrYW5N0QkP6u0Qb8kU6WekIXBiDenmZm1zLvuq/9pBBhRCJLCICEOsH5Og4B0Xw02bhqGkK5VN/oPH0w==", - "requires": { - "d3-array": "1", - "d3-axis": "1", - "d3-brush": "1", - "d3-chord": "1", - "d3-collection": "1", - "d3-color": "1", - "d3-contour": "1", - "d3-dispatch": "1", - "d3-drag": "1", - "d3-dsv": "1", - "d3-ease": "1", - "d3-fetch": "1", - "d3-force": "1", - "d3-format": "1", - "d3-geo": "1", - "d3-hierarchy": "1", - "d3-interpolate": "1", - "d3-path": "1", - "d3-polygon": "1", - "d3-quadtree": "1", - "d3-random": "1", - "d3-scale": "2", - "d3-scale-chromatic": "1", - "d3-selection": "1", - "d3-shape": "1", - "d3-time": "1", - "d3-time-format": "2", - "d3-timer": "1", - "d3-transition": "1", - "d3-voronoi": "1", - "d3-zoom": "1" - } - }, - "d3-array": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", - "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" - }, - "d3-axis": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz", - "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==" - }, - "d3-brush": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz", - "integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "d3-chord": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", - "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", - "requires": { - "d3-array": "1", - "d3-path": "1" - } - }, - "d3-collection": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", - "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==" - }, - "d3-color": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", - "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==" - }, - "d3-contour": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", - "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", - "requires": { - "d3-array": "^1.1.1" - } - }, - "d3-dispatch": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", - "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==" - }, - "d3-drag": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", - "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", - "requires": { - "d3-dispatch": "1", - "d3-selection": "1" - } - }, - "d3-dsv": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", - "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", - "requires": { - "commander": "2", - "iconv-lite": "0.4", - "rw": "1" - } - }, - "d3-ease": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", - "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==" - }, - "d3-fetch": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz", - "integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==", - "requires": { - "d3-dsv": "1" - } - }, - "d3-force": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz", - "integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==", - "requires": { - "d3-collection": "1", - "d3-dispatch": "1", - "d3-quadtree": "1", - "d3-timer": "1" - } - }, - "d3-format": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", - "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==" - }, - "d3-geo": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz", - "integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==", - "requires": { - "d3-array": "1" - } - }, - "d3-hierarchy": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", - "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==" - }, - "d3-interpolate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", - "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", - "requires": { - "d3-color": "1" - } - }, - "d3-path": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" - }, - "d3-polygon": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", - "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==" - }, - "d3-quadtree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", - "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==" - }, - "d3-queue": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/d3-queue/-/d3-queue-3.0.7.tgz", - "integrity": "sha1-yTouVLQXwJWRKdfXP2z31Ckudhg=" - }, - "d3-random": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz", - "integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==" - }, - "d3-request": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-request/-/d3-request-1.0.6.tgz", - "integrity": "sha512-FJj8ySY6GYuAJHZMaCQ83xEYE4KbkPkmxZ3Hu6zA1xxG2GD+z6P+Lyp+zjdsHf0xEbp2xcluDI50rCS855EQ6w==", - "requires": { - "d3-collection": "1", - "d3-dispatch": "1", - "d3-dsv": "1", - "xmlhttprequest": "1" - } - }, - "d3-scale": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", - "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", - "requires": { - "d3-array": "^1.2.0", - "d3-collection": "1", - "d3-format": "1", - "d3-interpolate": "1", - "d3-time": "1", - "d3-time-format": "2" - } - }, - "d3-scale-chromatic": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz", - "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==", - "requires": { - "d3-color": "1", - "d3-interpolate": "1" - } - }, - "d3-selection": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", - "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==" - }, - "d3-shape": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", - "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", - "requires": { - "d3-path": "1" - } - }, - "d3-time": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", - "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==" - }, - "d3-time-format": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", - "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", - "requires": { - "d3-time": "1" - } - }, - "d3-timer": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", - "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==" - }, - "d3-tip": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/d3-tip/-/d3-tip-0.7.1.tgz", - "integrity": "sha1-eMv1VPZ7cgpw47DxkeFM/+aM3Xk=", - "requires": { - "d3": "^4.2" - }, - "dependencies": { - "d3": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-4.13.0.tgz", - "integrity": "sha512-l8c4+0SldjVKLaE2WG++EQlqD7mh/dmQjvi2L2lKPadAVC+TbJC4ci7Uk9bRi+To0+ansgsS0iWfPjD7DBy+FQ==", - "requires": { - "d3-array": "1.2.1", - "d3-axis": "1.0.8", - "d3-brush": "1.0.4", - "d3-chord": "1.0.4", - "d3-collection": "1.0.4", - "d3-color": "1.0.3", - "d3-dispatch": "1.0.3", - "d3-drag": "1.2.1", - "d3-dsv": "1.0.8", - "d3-ease": "1.0.3", - "d3-force": "1.1.0", - "d3-format": "1.2.2", - "d3-geo": "1.9.1", - "d3-hierarchy": "1.1.5", - "d3-interpolate": "1.1.6", - "d3-path": "1.0.5", - "d3-polygon": "1.0.3", - "d3-quadtree": "1.0.3", - "d3-queue": "3.0.7", - "d3-random": "1.1.0", - "d3-request": "1.0.6", - "d3-scale": "1.0.7", - "d3-selection": "1.3.0", - "d3-shape": "1.2.0", - "d3-time": "1.0.8", - "d3-time-format": "2.1.1", - "d3-timer": "1.0.7", - "d3-transition": "1.1.1", - "d3-voronoi": "1.1.2", - "d3-zoom": "1.7.1" - } - }, - "d3-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.1.tgz", - "integrity": "sha512-CyINJQ0SOUHojDdFDH4JEM0552vCR1utGyLHegJHyYH0JyCpSeTPxi4OBqHMA2jJZq4NH782LtaJWBImqI/HBw==" - }, - "d3-axis": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.8.tgz", - "integrity": "sha1-MacFoLU15ldZ3hQXOjGTMTfxjvo=" - }, - "d3-brush": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.0.4.tgz", - "integrity": "sha1-AMLyOAGfJPbAoZSibUGhUw/+e8Q=", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "d3-chord": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.4.tgz", - "integrity": "sha1-fexPC6iG9xP+ERxF92NBT290yiw=", - "requires": { - "d3-array": "1", - "d3-path": "1" - } - }, - "d3-collection": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.4.tgz", - "integrity": "sha1-NC39EoN8kJdPM/HMCnha6lcNzcI=" - }, - "d3-color": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.0.3.tgz", - "integrity": "sha1-vHZD/KjlOoNH4vva/6I2eWtYUJs=" - }, - "d3-dispatch": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.3.tgz", - "integrity": "sha1-RuFJHqqbWMNY/OW+TovtYm54cfg=" - }, - "d3-drag": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.1.tgz", - "integrity": "sha512-Cg8/K2rTtzxzrb0fmnYOUeZHvwa4PHzwXOLZZPwtEs2SKLLKLXeYwZKBB+DlOxUvFmarOnmt//cU4+3US2lyyQ==", - "requires": { - "d3-dispatch": "1", - "d3-selection": "1" - } - }, - "d3-dsv": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.0.8.tgz", - "integrity": "sha512-IVCJpQ+YGe3qu6odkPQI0KPqfxkhbP/oM1XhhE/DFiYmcXKfCRub4KXyiuehV1d4drjWVXHUWx4gHqhdZb6n/A==", - "requires": { - "commander": "2", - "iconv-lite": "0.4", - "rw": "1" - } - }, - "d3-ease": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.3.tgz", - "integrity": "sha1-aL+8NJM4o4DETYrMT7wzBKotjA4=" - }, - "d3-force": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.1.0.tgz", - "integrity": "sha512-2HVQz3/VCQs0QeRNZTYb7GxoUCeb6bOzMp/cGcLa87awY9ZsPvXOGeZm0iaGBjXic6I1ysKwMn+g+5jSAdzwcg==", - "requires": { - "d3-collection": "1", - "d3-dispatch": "1", - "d3-quadtree": "1", - "d3-timer": "1" - } - }, - "d3-format": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.2.2.tgz", - "integrity": "sha512-zH9CfF/3C8zUI47nsiKfD0+AGDEuM8LwBIP7pBVpyR4l/sKkZqITmMtxRp04rwBrlshIZ17XeFAaovN3++wzkw==" - }, - "d3-geo": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.9.1.tgz", - "integrity": "sha512-l9wL/cEQkyZQYXw3xbmLsH3eQ5ij+icNfo4r0GrLa5rOCZR/e/3am45IQ0FvQ5uMsv+77zBRunLc9ufTWSQYFA==", - "requires": { - "d3-array": "1" - } - }, - "d3-hierarchy": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.5.tgz", - "integrity": "sha1-ochFxC+Eoga88cAcAQmOpN2qeiY=" - }, - "d3-interpolate": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.6.tgz", - "integrity": "sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==", - "requires": { - "d3-color": "1" - } - }, - "d3-path": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.5.tgz", - "integrity": "sha1-JB6xhJvZ6egCHA0KeZ+KDo5EF2Q=" - }, - "d3-polygon": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.3.tgz", - "integrity": "sha1-FoiOkCZGCTPysXllKtN4Ik04LGI=" - }, - "d3-quadtree": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.3.tgz", - "integrity": "sha1-rHmH4+I/6AWpkPKOG1DTj8uCJDg=" - }, - "d3-random": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.0.tgz", - "integrity": "sha1-ZkLlBsb6OmSFldKyRpeIqNElKdM=" - }, - "d3-scale": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.7.tgz", - "integrity": "sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw==", - "requires": { - "d3-array": "^1.2.0", - "d3-collection": "1", - "d3-color": "1", - "d3-format": "1", - "d3-interpolate": "1", - "d3-time": "1", - "d3-time-format": "2" - } - }, - "d3-selection": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.3.0.tgz", - "integrity": "sha512-qgpUOg9tl5CirdqESUAu0t9MU/t3O9klYfGfyKsXEmhyxyzLpzpeh08gaxBUTQw1uXIOkr/30Ut2YRjSSxlmHA==" - }, - "d3-shape": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.2.0.tgz", - "integrity": "sha1-RdAVOPBkuv0F6j1tLLdI/YxB93c=", - "requires": { - "d3-path": "1" - } - }, - "d3-time": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.0.8.tgz", - "integrity": "sha512-YRZkNhphZh3KcnBfitvF3c6E0JOFGikHZ4YqD+Lzv83ZHn1/u6yGenRU1m+KAk9J1GnZMnKcrtfvSktlA1DXNQ==" - }, - "d3-time-format": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.1.1.tgz", - "integrity": "sha512-8kAkymq2WMfzW7e+s/IUNAtN/y3gZXGRrdGfo6R8NKPAA85UBTxZg5E61bR6nLwjPjj4d3zywSQe1CkYLPFyrw==", - "requires": { - "d3-time": "1" - } - }, - "d3-timer": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.7.tgz", - "integrity": "sha512-vMZXR88XujmG/L5oB96NNKH5lCWwiLM/S2HyyAQLcjWJCloK5shxta4CwOFYLZoY3AWX73v8Lgv4cCAdWtRmOA==" - }, - "d3-transition": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.1.1.tgz", - "integrity": "sha512-xeg8oggyQ+y5eb4J13iDgKIjUcEfIOZs2BqV/eEmXm2twx80wTzJ4tB4vaZ5BKfz7XsI/DFmQL5me6O27/5ykQ==", - "requires": { - "d3-color": "1", - "d3-dispatch": "1", - "d3-ease": "1", - "d3-interpolate": "1", - "d3-selection": "^1.1.0", - "d3-timer": "1" - } - }, - "d3-voronoi": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.2.tgz", - "integrity": "sha1-Fodmfo8TotFYyAwUgMWinLDYlzw=" - }, - "d3-zoom": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.7.1.tgz", - "integrity": "sha512-sZHQ55DGq5BZBFGnRshUT8tm2sfhPHFnOlmPbbwTkAoPeVdRTkB4Xsf9GCY0TSHrTD8PeJPZGmP/TpGicwJDJQ==", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - } - } - }, - "d3-transition": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", - "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", - "requires": { - "d3-color": "1", - "d3-dispatch": "1", - "d3-ease": "1", - "d3-interpolate": "1", - "d3-selection": "^1.1.0", - "d3-timer": "1" - } - }, - "d3-voronoi": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", - "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==" - }, - "d3-zoom": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz", - "integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "dagre": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", - "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", - "requires": { - "graphlib": "^2.1.8", - "lodash": "^4.17.15" - } - }, - "dagre-d3": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz", - "integrity": "sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==", - "requires": { - "d3": "^5.14", - "dagre": "^0.8.5", - "graphlib": "^2.1.8", - "lodash": "^4.17.15" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "dot": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dot/-/dot-1.1.3.tgz", - "integrity": "sha512-/nt74Rm+PcfnirXGEdhZleTwGC2LMnuKTeeTIlI82xb5loBBoXNYzr2ezCroPSMtilK8EZIfcNZwOcHN+ib1Lg==" - }, - "dragula-with-animation": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/dragula-with-animation/-/dragula-with-animation-3.7.4.tgz", - "integrity": "sha512-Kdvld/s4ASLRgP5w8lzK64P+8XUX9ccNGn0rmXDCG9AuvyzUxvVo+HxLQoRMyRPCQWAZ3xzA7b3ghcFIz+QsIA==", - "requires": { - "contra": "1.9.4", - "crossvent": "1.5.4" - }, - "dependencies": { - "crossvent": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/crossvent/-/crossvent-1.5.4.tgz", - "integrity": "sha1-2ixPj0DJR4JRe/K+7BBEFIGUq5I=", - "requires": { - "custom-event": "1.0.0" - } - }, - "custom-event": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.0.tgz", - "integrity": "sha1-LkYovhncSyFLXAJjDFlx6BFhgGI=" - } - } - }, - "dropzone": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.7.0.tgz", - "integrity": "sha512-kOltiZXH5cO/72I22JjE+w6BoT6uaVLfWdFMsi1PMKFkU6BZWpqRwjnsRm0o6ANGTBuZar5Piu7m/CbKqRPiYg==" - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "error": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", - "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", - "dev": true, - "requires": { - "string-template": "~0.2.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "eventemitter2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", - "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", - "dev": true - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "file-sync-cmp": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz", - "integrity": "sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs=", - "dev": true - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "findup-sync": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", - "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", - "dev": true, - "requires": { - "glob": "~5.0.0" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "font-awesome": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", - "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=" - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true, - "requires": { - "globule": "^1.0.0" - } - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, - "getobject": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", - "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", - "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "globule": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", - "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", - "dev": true, - "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "graphlib": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", - "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", - "requires": { - "lodash": "^4.17.15" - } - }, - "grunt": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.4.tgz", - "integrity": "sha512-PYsMOrOC+MsdGEkFVwMaMyc6Ob7pKmq+deg1Sjr+vvMWp35sztfwKE7qoN51V+UEtHsyNuMcGdgMLFkBHvMxHQ==", - "dev": true, - "requires": { - "coffeescript": "~1.10.0", - "dateformat": "~1.0.12", - "eventemitter2": "~0.4.13", - "exit": "~0.1.1", - "findup-sync": "~0.3.0", - "glob": "~7.0.0", - "grunt-cli": "~1.2.0", - "grunt-known-options": "~1.1.0", - "grunt-legacy-log": "~2.0.0", - "grunt-legacy-util": "~1.1.1", - "iconv-lite": "~0.4.13", - "js-yaml": "~3.13.0", - "minimatch": "~3.0.2", - "mkdirp": "~0.5.1", - "nopt": "~3.0.6", - "path-is-absolute": "~1.0.0", - "rimraf": "~2.6.2" - } - }, - "grunt-cli": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", - "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=", - "dev": true, - "requires": { - "findup-sync": "~0.3.0", - "grunt-known-options": "~1.1.0", - "nopt": "~3.0.6", - "resolve": "~1.1.0" - }, - "dependencies": { - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } - } - }, - "grunt-contrib-clean": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-1.1.0.tgz", - "integrity": "sha1-Vkq/LQN4qYOhW54/MO51tzjEBjg=", - "dev": true, - "requires": { - "async": "^1.5.2", - "rimraf": "^2.5.1" - } - }, - "grunt-contrib-connect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/grunt-contrib-connect/-/grunt-contrib-connect-1.0.2.tgz", - "integrity": "sha1-XPkzuRpnOGBEJzwLJERgPNmIebo=", - "dev": true, - "requires": { - "async": "^1.5.2", - "connect": "^3.4.0", - "connect-livereload": "^0.5.0", - "http2": "^3.3.4", - "morgan": "^1.6.1", - "opn": "^4.0.0", - "portscanner": "^1.0.0", - "serve-index": "^1.7.1", - "serve-static": "^1.10.0" - } - }, - "grunt-contrib-copy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz", - "integrity": "sha1-cGDGWB6QS4qw0A8HbgqPbj58NXM=", - "dev": true, - "requires": { - "chalk": "^1.1.1", - "file-sync-cmp": "^0.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "grunt-contrib-cssmin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-cssmin/-/grunt-contrib-cssmin-2.0.0.tgz", - "integrity": "sha1-O8joyIZcgZFZzCd5+C/PgzRzNFs=", - "dev": true, - "requires": { - "chalk": "^1.0.0", - "clean-css": "~4.0.3", - "maxmin": "^1.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "grunt-contrib-htmlmin": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-htmlmin/-/grunt-contrib-htmlmin-2.2.0.tgz", - "integrity": "sha1-FB8M+4cBKO2c5uqGGrEwVlyQzZc=", - "dev": true, - "requires": { - "chalk": "^1.0.0", - "html-minifier": "~3.3.0", - "pretty-bytes": "^4.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "pretty-bytes": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", - "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "grunt-contrib-rename": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-rename/-/grunt-contrib-rename-0.2.0.tgz", - "integrity": "sha1-1CPU+SqZpYcncEX4MikdmM4V/co=", - "dev": true - }, - "grunt-contrib-uglify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-2.1.0.tgz", - "integrity": "sha1-s/8CjaR0g3h/GfCyMrehtRIS/YU=", - "dev": true, - "requires": { - "chalk": "^1.0.0", - "maxmin": "^1.1.0", - "object.assign": "^4.0.4", - "uglify-js": "~2.7.0", - "uri-path": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "grunt-contrib-watch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz", - "integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==", - "dev": true, - "requires": { - "async": "^2.6.0", - "gaze": "^1.1.0", - "lodash": "^4.17.10", - "tiny-lr": "^1.1.1" - }, - "dependencies": { - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - } - } - }, - "grunt-known-options": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.1.tgz", - "integrity": "sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==", - "dev": true - }, - "grunt-legacy-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz", - "integrity": "sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==", - "dev": true, - "requires": { - "colors": "~1.1.2", - "grunt-legacy-log-utils": "~2.0.0", - "hooker": "~0.2.3", - "lodash": "~4.17.5" - } - }, - "grunt-legacy-log-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz", - "integrity": "sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==", - "dev": true, - "requires": { - "chalk": "~2.4.1", - "lodash": "~4.17.10" - } - }, - "grunt-legacy-util": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz", - "integrity": "sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==", - "dev": true, - "requires": { - "async": "~1.5.2", - "exit": "~0.1.1", - "getobject": "~0.1.0", - "hooker": "~0.2.3", - "lodash": "~4.17.10", - "underscore.string": "~3.3.4", - "which": "~1.3.0" - } - }, - "grunt-middleware-proxy": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/grunt-middleware-proxy/-/grunt-middleware-proxy-1.0.7.tgz", - "integrity": "sha1-YUPO05nBrzOlRmgvPUBcp2m6fRg=", - "dev": true - }, - "grunt-sass": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/grunt-sass/-/grunt-sass-3.1.0.tgz", - "integrity": "sha512-90s27H7FoCDcA8C8+R0GwC+ntYD3lG6S/jqcavWm3bn9RiJTmSfOvfbFa1PXx4NbBWuiGQMLfQTj/JvvqT5w6A==", - "dev": true - }, - "grunt-template": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/grunt-template/-/grunt-template-1.0.0.tgz", - "integrity": "sha1-Vgj5sFoGp4b6BIymZEfktI09HCE=", - "dev": true - }, - "gzip-size": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz", - "integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=", - "dev": true, - "requires": { - "browserify-zlib": "^0.1.4", - "concat-stream": "^1.4.1" - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "dev": true, - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "hooker": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", - "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", - "dev": true - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, - "html-minifier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.3.3.tgz", - "integrity": "sha1-XoVRayr/PD+5vaNRh5N1hoOG1vY=", - "dev": true, - "requires": { - "camel-case": "3.0.x", - "clean-css": "4.0.x", - "commander": "2.9.x", - "he": "1.1.x", - "ncname": "1.0.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "2.7.x" - }, - "dependencies": { - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } - } - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } - } - }, - "http-parser-js": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.2.tgz", - "integrity": "sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ==", - "dev": true - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "http2": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/http2/-/http2-3.3.7.tgz", - "integrity": "sha512-puSi8M8WNlFJm9Pk4c/Mbz9Gwparuj3gO9/RRO5zv6piQ0FY+9Qywp0PdWshYgsMJSalixFY7eC6oPu0zRxLAQ==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "in-publish": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz", - "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==", - "dev": true - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "jQuery-QueryBuilder": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/jQuery-QueryBuilder/-/jQuery-QueryBuilder-2.4.3.tgz", - "integrity": "sha1-F3vGKm+YXa0Ozu30kqo/yk5qKuU=", - "requires": { - "bootstrap": ">=3.1.0", - "dot": ">=1.0.3", - "jquery": ">=1.9.0", - "jquery-extendext": ">=0.1.2", - "moment": ">=2.6.0" - } - }, - "jquery": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz", - "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==" - }, - "jquery-asBreadcrumbs": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/jquery-asBreadcrumbs/-/jquery-asBreadcrumbs-0.2.2.tgz", - "integrity": "sha1-eAOj55hzLBI3zni7hmqi11/iJPg=", - "requires": { - "jquery": ">=2.2.0" - } - }, - "jquery-extendext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/jquery-extendext/-/jquery-extendext-1.0.0.tgz", - "integrity": "sha512-gDJjpQ8ISd4ZMwSn0yXSuyufsPMCeWtWJ8kmqE85VromJqyVT2sdkHzS5yL0w1GK81UpOzmr2f9JgFln2sbJSg==", - "requires": { - "jquery": ">=1.9.1" - } - }, - "jquery-mousewheel": { - "version": "3.1.13", - "resolved": "https://registry.npmjs.org/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz", - "integrity": "sha1-BvAzXxbjU6aV5yBr9QUDy1I6buU=" - }, - "jquery-placeholder": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/jquery-placeholder/-/jquery-placeholder-2.3.1.tgz", - "integrity": "sha1-YCWhJBAZwIqPs6uO0HYoXAW6XpE=" - }, - "jquery-sparkline": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jquery-sparkline/-/jquery-sparkline-2.4.0.tgz", - "integrity": "sha1-G+i3twTdOFcVJwiu+x1KSzpp+zM=" - }, - "jquery-steps": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jquery-steps/-/jquery-steps-1.1.0.tgz", - "integrity": "sha1-DO7gsNLkkUOYGtEg1FjtVuqOGSQ=" - }, - "js-base64": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", - "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "jstree": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jstree/-/jstree-3.3.5.tgz", - "integrity": "sha1-nFeNsy0KZDd1zd2AIK1ZkvQRnBM=", - "requires": { - "jquery": ">=1.9.1" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "livereload-js": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", - "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==", - "dev": true - }, - "load-grunt-tasks": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-3.5.2.tgz", - "integrity": "sha1-ByhWEYD9IP+KaSdQWFL8WKrqDIg=", - "dev": true, - "requires": { - "arrify": "^1.0.0", - "multimatch": "^2.0.0", - "pkg-up": "^1.0.0", - "resolve-pkg": "^0.1.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "lossless-json": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lossless-json/-/lossless-json-1.0.4.tgz", - "integrity": "sha512-zEkWwELMSQQISdtOF44vk0bRJhN/PJ93qcgJLcodizQjxrJKdFrq2H1+Xv5QDe7v3dTYYbBI5hOsh4a9l0B2Ow==" - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "lunr": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-0.7.2.tgz", - "integrity": "sha1-eaMOky4hbLoWNUHuN6NgfBLNcoE=" - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "maxmin": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz", - "integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=", - "dev": true, - "requires": { - "chalk": "^1.0.0", - "figures": "^1.0.1", - "gzip-size": "^1.0.0", - "pretty-bytes": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "dev": true - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dev": true, - "requires": { - "mime-db": "1.44.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "moment": { - "version": "2.21.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.21.0.tgz", - "integrity": "sha512-TCZ36BjURTeFTM/CwRcViQlfkMvL1/vFISuNLO5GkcVm1+QHfbSiNqZuWeMFjj1/3+uAjXswgRk30j1kkLYJBQ==" - }, - "moment-timezone": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.14.tgz", - "integrity": "sha1-TrOP+VOLgBCLpGekWPPtQmjM/LE=", - "requires": { - "moment": ">= 2.9.0" - } - }, - "morgan": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", - "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", - "dev": true, - "requires": { - "basic-auth": "~2.0.1", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-finished": "~2.3.0", - "on-headers": "~1.0.2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "multimatch": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", - "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", - "dev": true, - "requires": { - "array-differ": "^1.0.0", - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "minimatch": "^3.0.0" - } - }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "dev": true - }, - "ncname": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ncname/-/ncname-1.0.0.tgz", - "integrity": "sha1-W1etGLHKCShk72Kwse2BlPODtxw=", - "dev": true, - "requires": { - "xml-char-classes": "^1.0.0" - } - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true - }, - "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "dev": true, - "requires": { - "lower-case": "^1.1.1" - } - }, - "node-gyp": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", - "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", - "dev": true, - "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "dependencies": { - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - } - } - }, - "node-sass": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.13.1.tgz", - "integrity": "sha512-TTWFx+ZhyDx1Biiez2nB0L3YrCZ/8oHagaDalbuBSlqXgUPsdkUSzJsVxeDO9LtPB49+Fh3WQl3slABo6AotNw==", - "dev": true, - "requires": { - "async-foreach": "^0.1.3", - "chalk": "^1.1.1", - "cross-spawn": "^3.0.0", - "gaze": "^1.0.0", - "get-stdin": "^4.0.1", - "glob": "^7.0.3", - "in-publish": "^2.0.0", - "lodash": "^4.17.15", - "meow": "^3.7.0", - "mkdirp": "^0.5.1", - "nan": "^2.13.2", - "node-gyp": "^3.8.0", - "npmlog": "^4.0.0", - "request": "^2.88.0", - "sass-graph": "^2.2.4", - "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "opn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", - "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", - "dev": true - }, - "param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", - "dev": true, - "requires": { - "no-case": "^2.2.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-up": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz", - "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - } - }, - "platform": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.4.tgz", - "integrity": "sha1-bw+xftqqSPIUQrOpdcBjEw8cPr0=" - }, - "pnotify": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/pnotify/-/pnotify-3.2.0.tgz", - "integrity": "sha1-IvQabCjY1CcKgR2o4JuoKOjgI3c=", - "requires": { - "jquery": ">=1.6.0" - } - }, - "portscanner": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-1.2.0.tgz", - "integrity": "sha1-sUu9olfRTDEPqcwJaCrwLUCWGAI=", - "dev": true, - "requires": { - "async": "1.5.2" - } - }, - "pretty-bytes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", - "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.1.0" - } - }, - "pretty-checkbox": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pretty-checkbox/-/pretty-checkbox-3.0.3.tgz", - "integrity": "sha1-1JyAE6j8CO4MLW695FNGS/28Qo4=" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", - "dev": true - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", - "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", - "dev": true, - "requires": { - "bytes": "1", - "string_decoder": "0.10" - }, - "dependencies": { - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "requirejs": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.3.tgz", - "integrity": "sha1-qln9OgKH6vQHlZoTgigES13WpqM=" - }, - "requirejs-text": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/requirejs-text/-/requirejs-text-2.0.15.tgz", - "integrity": "sha1-ExOHM2E/xEV7fhJH6Mt1HfeqVCk=" - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", - "dev": true - }, - "resolve-pkg": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-0.1.0.tgz", - "integrity": "sha1-AsyZNBDik2livZcWahsHfalyVTE=", - "dev": true, - "requires": { - "resolve-from": "^2.0.0" - } - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "^0.1.1" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" - }, - "rx": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", - "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safe-json-parse": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", - "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sass-graph": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.6.tgz", - "integrity": "sha512-MKuEYXFSGuRSi8FZ3A7imN1CeVn9Gpw0/SFJKdL1ejXJneI9a5rwlEZrKejhEFAA3O6yr3eIyl/WuvASvlT36g==", - "dev": true, - "requires": { - "glob": "^7.0.0", - "lodash": "^4.0.0", - "scss-tokenizer": "^0.2.3", - "yargs": "^7.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "yargs": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", - "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "5.0.0-security.0" - } - } - } - }, - "scss-tokenizer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", - "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", - "dev": true, - "requires": { - "js-base64": "^2.1.8", - "source-map": "^0.4.2" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "select2": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/select2/-/select2-4.0.3.tgz", - "integrity": "sha1-IHcz/pHqy5yxoT8SRjQB9HJEng8=", - "requires": { - "almond": "~0.3.1", - "jquery-mousewheel": "~3.1.13" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - } - } - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", - "dev": true - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stdout-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", - "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, - "string-template": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "table-dragger": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/table-dragger/-/table-dragger-1.0.2.tgz", - "integrity": "sha1-mB9Gxi/SiZs/xeZEBV6nKDGUlwc=", - "requires": { - "babel-runtime": "^6.20.0", - "crossvent": "^1.5.5", - "dragula-with-animation": "^3.7.2", - "rx": "^4.1.0" - } - }, - "tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "dev": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - }, - "ticky": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ticky/-/ticky-1.0.1.tgz", - "integrity": "sha1-t8+nHnaPHJAAxJe5FRswlHxQ5G0=" - }, - "tiny-lr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", - "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", - "dev": true, - "requires": { - "body": "^5.1.0", - "debug": "^3.1.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.3.0", - "object-assign": "^4.1.0", - "qs": "^6.4.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", - "dev": true, - "requires": { - "glob": "^7.1.2" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "uglify-js": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", - "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", - "dev": true, - "requires": { - "async": "~0.2.6", - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - } - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true - }, - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "underscore.string": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz", - "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==", - "dev": true, - "requires": { - "sprintf-js": "^1.0.3", - "util-deprecate": "^1.0.2" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true - }, - "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "uri-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", - "integrity": "sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI=", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xml-char-classes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/xml-char-classes/-/xml-char-classes-1.0.0.tgz", - "integrity": "sha1-ZGV4SKIP/F31g6Qq2KJ3tFErvE0=", - "dev": true - }, - "xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - }, - "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - } - } - }, - "yargs-parser": { - "version": "5.0.0-security.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", - "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - } - } - } - } -} \ No newline at end of file diff --git a/dashboardv2/package.json b/dashboardv2/package.json deleted file mode 100644 index 2cc1d4b08b2..00000000000 --- a/dashboardv2/package.json +++ /dev/null @@ -1,74 +0,0 @@ -{ - "name": "atlas-metadata", - "description": "Apache Atlas", - "private": true, - "repository": { - "type": "git", - "url": "https://git-wip-us.apache.org/repos/asf/incubator-atlas.git" - }, - "scripts": { - "start": "grunt dev", - "build": "grunt build", - "dev-minify": "grunt dev-minify", - "build-minify": "grunt build-minify" - }, - "keywords": [ - "Apache", - "Atlas" - ], - "dependencies": { - "backbone": "1.2.3", - "backbone.babysitter": "0.1.12", - "backbone.marionette": "2.3.2", - "backbone.paginator": "2.0.5", - "backbone.wreqr": "1.4.0", - "backgrid": "0.3.8", - "backgrid-filter": "0.3.7", - "backgrid-orderable-columns": "0.1.2", - "backgrid-paginator": "0.3.9", - "backgrid-select-all": "0.3.5", - "backgrid-sizeable-columns": "0.1.1", - "bootstrap": "3.4.1", - "bootstrap-daterangepicker": "3.1.0", - "d3": "5.14.2", - "d3-tip": "^0.7.1", - "dagre-d3": "0.6.4", - "dropzone": "5.7.0", - "font-awesome": "4.7.0", - "jQuery-QueryBuilder": "2.4.3", - "jquery": "3.5.1", - "jquery-asBreadcrumbs": "0.2.2", - "jquery-placeholder": "2.3.1", - "jquery-sparkline": "2.4.0", - "jquery-steps": "1.1.0", - "jstree": "3.3.5", - "lossless-json": "1.0.4", - "moment": "2.21.0", - "moment-timezone": "0.5.14", - "platform": "1.3.4", - "pnotify": "3.2.0", - "pretty-checkbox": "3.0.3", - "requirejs": "2.3.3", - "requirejs-text": "2.0.15", - "select2": "4.0.3", - "table-dragger": "1.0.2", - "underscore": "1.8.3" - }, - "devDependencies": { - "grunt": "1.0.4", - "grunt-cli": "1.2.0", - "grunt-contrib-clean": "1.1.0", - "grunt-contrib-connect": "1.0.2", - "grunt-contrib-copy": "1.0.0", - "grunt-contrib-cssmin": "2.0.0", - "grunt-contrib-htmlmin": "2.2.0", - "grunt-contrib-rename": "0.2.0", - "grunt-contrib-uglify": "2.1.0", - "grunt-contrib-watch": "1.1.0", - "grunt-middleware-proxy": "1.0.7", - "grunt-sass": "3.1.0", - "grunt-template": "1.0.0", - "load-grunt-tasks": "3.5.2", - "node-sass": "4.13.1" - } -} diff --git a/dashboardv2/pom.xml b/dashboardv2/pom.xml deleted file mode 100644 index 12b01c3f326..00000000000 --- a/dashboardv2/pom.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - 4.0.0 - - org.apache.atlas - apache-atlas - 3.0.0-SNAPSHOT - - - atlas-dashboardv2 - Apache Atlas UI Application - Apache Atlas UI - war - https://atlas.apache.org - - - - - - - com.github.eirslett - frontend-maven-plugin - - validate - ${project.build.directory} - - - - - - - org.apache.maven.plugins - maven-war-plugin - - false - - - ${project.build.directory}/dist - - - - - - maven-resources-plugin - 2.7 - - - copy-resources - - copy-resources - - validate - - ${basedir}/target/ - - - ${basedir} - - package.json - package-lock.json - gruntfile.js - - - - - - - - - com.github.eirslett - frontend-maven-plugin - - - install node and npm - - install-node-and-npm - - - ${node-for-v2.version} - ${npm-for-v2.version} - - - - npm install - - npm - - - install - - - - grunt dist - - grunt - - - ${project.build.dashboardv2.gruntBuild} - - - - - - - diff --git a/dashboardv2/public/css/animate.min.css b/dashboardv2/public/css/animate.min.css deleted file mode 100755 index bf71d18417c..00000000000 --- a/dashboardv2/public/css/animate.min.css +++ /dev/null @@ -1 +0,0 @@ -@charset "UTF-8";/*!;Animate.css - http://daneden.me/animate;Licensed under the MIT license - http://opensource.org/licenses/MIT;;Copyright (c) 2015 Daniel Eden;*/.animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.animated.hinge{-webkit-animation-duration:2s;animation-duration:2s}.animated.bounceIn,.animated.bounceOut,.animated.flipOutX,.animated.flipOutY{-webkit-animation-duration:.75s;animation-duration:.75s}@-webkit-keyframes bounce{0%,100%,20%,53%,80%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}40%,43%{-webkit-transition-timing-function:cubic-bezier(0.755,.050,.855,.060);transition-timing-function:cubic-bezier(0.755,.050,.855,.060);-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}70%{-webkit-transition-timing-function:cubic-bezier(0.755,.050,.855,.060);transition-timing-function:cubic-bezier(0.755,.050,.855,.060);-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}@keyframes bounce{0%,100%,20%,53%,80%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}40%,43%{-webkit-transition-timing-function:cubic-bezier(0.755,.050,.855,.060);transition-timing-function:cubic-bezier(0.755,.050,.855,.060);-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}70%{-webkit-transition-timing-function:cubic-bezier(0.755,.050,.855,.060);transition-timing-function:cubic-bezier(0.755,.050,.855,.060);-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}.bounce{-webkit-animation-name:bounce;animation-name:bounce;-webkit-transform-origin:center bottom;transform-origin:center bottom}@-webkit-keyframes flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}@keyframes flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}.flash{-webkit-animation-name:flash;animation-name:flash}@-webkit-keyframes pulse{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes pulse{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.pulse{-webkit-animation-name:pulse;animation-name:pulse}@-webkit-keyframes rubberBand{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(0.75,1.25,1);transform:scale3d(0.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes rubberBand{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(0.75,1.25,1);transform:scale3d(0.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.rubberBand{-webkit-animation-name:rubberBand;animation-name:rubberBand}@-webkit-keyframes shake{0%,100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}@keyframes shake{0%,100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}.shake{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes swing{20%{-webkit-transform:rotate3d(0,0,1,15deg);transform:rotate3d(0,0,1,15deg)}40%{-webkit-transform:rotate3d(0,0,1,-10deg);transform:rotate3d(0,0,1,-10deg)}60%{-webkit-transform:rotate3d(0,0,1,5deg);transform:rotate3d(0,0,1,5deg)}80%{-webkit-transform:rotate3d(0,0,1,-5deg);transform:rotate3d(0,0,1,-5deg)}100%{-webkit-transform:rotate3d(0,0,1,0deg);transform:rotate3d(0,0,1,0deg)}}@keyframes swing{20%{-webkit-transform:rotate3d(0,0,1,15deg);transform:rotate3d(0,0,1,15deg)}40%{-webkit-transform:rotate3d(0,0,1,-10deg);transform:rotate3d(0,0,1,-10deg)}60%{-webkit-transform:rotate3d(0,0,1,5deg);transform:rotate3d(0,0,1,5deg)}80%{-webkit-transform:rotate3d(0,0,1,-5deg);transform:rotate3d(0,0,1,-5deg)}100%{-webkit-transform:rotate3d(0,0,1,0deg);transform:rotate3d(0,0,1,0deg)}}.swing{-webkit-transform-origin:top center;transform-origin:top center;-webkit-animation-name:swing;animation-name:swing}@-webkit-keyframes tada{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes tada{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.tada{-webkit-animation-name:tada;animation-name:tada}@-webkit-keyframes wobble{0%{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}100%{-webkit-transform:none;transform:none}}@keyframes wobble{0%{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}100%{-webkit-transform:none;transform:none}}.wobble{-webkit-animation-name:wobble;animation-name:wobble}@-webkit-keyframes bounceIn{0%,100%,20%,40%,60%,80%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes bounceIn{0%,100%,20%,40%,60%,80%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.bounceIn{-webkit-animation-name:bounceIn;animation-name:bounceIn}@-webkit-keyframes bounceInDown{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInDown{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}100%{-webkit-transform:none;transform:none}}.bounceInDown{-webkit-animation-name:bounceInDown;animation-name:bounceInDown}@-webkit-keyframes bounceInLeft{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0);transform:translate3d(-3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0);transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInLeft{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0);transform:translate3d(-3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0);transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}100%{-webkit-transform:none;transform:none}}.bounceInLeft{-webkit-animation-name:bounceInLeft;animation-name:bounceInLeft}@-webkit-keyframes bounceInRight{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(3000px,0,0);transform:translate3d(3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0);transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInRight{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(3000px,0,0);transform:translate3d(3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0);transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}100%{-webkit-transform:none;transform:none}}.bounceInRight{-webkit-animation-name:bounceInRight;animation-name:bounceInRight}@-webkit-keyframes bounceInUp{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,3000px,0);transform:translate3d(0,3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes bounceInUp{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,3000px,0);transform:translate3d(0,3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.bounceInUp{-webkit-animation-name:bounceInUp;animation-name:bounceInUp}@-webkit-keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}100%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}@keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}100%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}.bounceOut{-webkit-animation-name:bounceOut;animation-name:bounceOut}@-webkit-keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.bounceOutDown{-webkit-animation-name:bounceOutDown;animation-name:bounceOutDown}@-webkit-keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.bounceOutLeft{-webkit-animation-name:bounceOutLeft;animation-name:bounceOutLeft}@-webkit-keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0);transform:translate3d(-20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0);transform:translate3d(-20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.bounceOutRight{-webkit-animation-name:bounceOutRight;animation-name:bounceOutRight}@-webkit-keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0);transform:translate3d(0,20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0);transform:translate3d(0,20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.bounceOutUp{-webkit-animation-name:bounceOutUp;animation-name:bounceOutUp}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInDown{-webkit-animation-name:fadeInDown;animation-name:fadeInDown}@-webkit-keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInDownBig{-webkit-animation-name:fadeInDownBig;animation-name:fadeInDownBig}@-webkit-keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInLeft{-webkit-animation-name:fadeInLeft;animation-name:fadeInLeft}@-webkit-keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInLeftBig{-webkit-animation-name:fadeInLeftBig;animation-name:fadeInLeftBig}@-webkit-keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInRight{-webkit-animation-name:fadeInRight;animation-name:fadeInRight}@-webkit-keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInRightBig{-webkit-animation-name:fadeInRightBig;animation-name:fadeInRightBig}@-webkit-keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInUp{-webkit-animation-name:fadeInUp;animation-name:fadeInUp}@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInUpBig{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeOutDown{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes fadeOutDown{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.fadeOutDown{-webkit-animation-name:fadeOutDown;animation-name:fadeOutDown}@-webkit-keyframes fadeOutDownBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes fadeOutDownBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.fadeOutDownBig{-webkit-animation-name:fadeOutDownBig;animation-name:fadeOutDownBig}@-webkit-keyframes fadeOutLeft{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@keyframes fadeOutLeft{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.fadeOutLeft{-webkit-animation-name:fadeOutLeft;animation-name:fadeOutLeft}@-webkit-keyframes fadeOutLeftBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes fadeOutLeftBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.fadeOutLeftBig{-webkit-animation-name:fadeOutLeftBig;animation-name:fadeOutLeftBig}@-webkit-keyframes fadeOutRight{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}@keyframes fadeOutRight{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.fadeOutRight{-webkit-animation-name:fadeOutRight;animation-name:fadeOutRight}@-webkit-keyframes fadeOutRightBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes fadeOutRightBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.fadeOutRightBig{-webkit-animation-name:fadeOutRightBig;animation-name:fadeOutRightBig}@-webkit-keyframes fadeOutUp{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes fadeOutUp{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp}@-webkit-keyframes fadeOutUpBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes fadeOutUpBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.fadeOutUpBig{-webkit-animation-name:fadeOutUpBig;animation-name:fadeOutUpBig}@-webkit-keyframes flip{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-360deg);transform:perspective(400px) rotate3d(0,1,0,-360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95);transform:perspective(400px) scale3d(.95,.95,.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}@keyframes flip{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-360deg);transform:perspective(400px) rotate3d(0,1,0,-360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95);transform:perspective(400px) scale3d(.95,.95,.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}.animated.flip{-webkit-backface-visibility:visible;backface-visibility:visible;-webkit-animation-name:flip;animation-name:flip}@-webkit-keyframes flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInX{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInX;animation-name:flipInX}@-webkit-keyframes flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInY{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInY;animation-name:flipInY}@-webkit-keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}@keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}.flipOutX{-webkit-animation-name:flipOutX;animation-name:flipOutX;-webkit-backface-visibility:visible!important;backface-visibility:visible!important}@-webkit-keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}@keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}.flipOutY{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipOutY;animation-name:flipOutY}@-webkit-keyframes lightSpeedIn{0%{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}100%{-webkit-transform:none;transform:none;opacity:1}}@keyframes lightSpeedIn{0%{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}100%{-webkit-transform:none;transform:none;opacity:1}}.lightSpeedIn{-webkit-animation-name:lightSpeedIn;animation-name:lightSpeedIn;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}@-webkit-keyframes lightSpeedOut{0%{opacity:1}100%{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}@keyframes lightSpeedOut{0%{opacity:1}100%{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}.lightSpeedOut{-webkit-animation-name:lightSpeedOut;animation-name:lightSpeedOut;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}@-webkit-keyframes rotateIn{0%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,-200deg);transform:rotate3d(0,0,1,-200deg);opacity:0}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateIn{0%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,-200deg);transform:rotate3d(0,0,1,-200deg);opacity:0}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}.rotateIn{-webkit-animation-name:rotateIn;animation-name:rotateIn}@-webkit-keyframes rotateInDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInDownLeft{-webkit-animation-name:rotateInDownLeft;animation-name:rotateInDownLeft}@-webkit-keyframes rotateInDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInDownRight{-webkit-animation-name:rotateInDownRight;animation-name:rotateInDownRight}@-webkit-keyframes rotateInUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInUpLeft{-webkit-animation-name:rotateInUpLeft;animation-name:rotateInUpLeft}@-webkit-keyframes rotateInUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-90deg);transform:rotate3d(0,0,1,-90deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-90deg);transform:rotate3d(0,0,1,-90deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInUpRight{-webkit-animation-name:rotateInUpRight;animation-name:rotateInUpRight}@-webkit-keyframes rotateOut{0%{-webkit-transform-origin:center;transform-origin:center;opacity:1}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,200deg);transform:rotate3d(0,0,1,200deg);opacity:0}}@keyframes rotateOut{0%{-webkit-transform-origin:center;transform-origin:center;opacity:1}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,200deg);transform:rotate3d(0,0,1,200deg);opacity:0}}.rotateOut{-webkit-animation-name:rotateOut;animation-name:rotateOut}@-webkit-keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}}@keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}}.rotateOutDownLeft{-webkit-animation-name:rotateOutDownLeft;animation-name:rotateOutDownLeft}@-webkit-keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}@keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}.rotateOutDownRight{-webkit-animation-name:rotateOutDownRight;animation-name:rotateOutDownRight}@-webkit-keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}@keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}.rotateOutUpLeft{-webkit-animation-name:rotateOutUpLeft;animation-name:rotateOutUpLeft}@-webkit-keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,90deg);transform:rotate3d(0,0,1,90deg);opacity:0}}@keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,90deg);transform:rotate3d(0,0,1,90deg);opacity:0}}.rotateOutUpRight{-webkit-animation-name:rotateOutUpRight;animation-name:rotateOutUpRight}@-webkit-keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0,0,1,80deg);transform:rotate3d(0,0,1,80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0,0,1,60deg);transform:rotate3d(0,0,1,60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}100%{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}@keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0,0,1,80deg);transform:rotate3d(0,0,1,80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0,0,1,60deg);transform:rotate3d(0,0,1,60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}100%{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}.hinge{-webkit-animation-name:hinge;animation-name:hinge}@-webkit-keyframes rollIn{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes rollIn{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg)}100%{opacity:1;-webkit-transform:none;transform:none}}.rollIn{-webkit-animation-name:rollIn;animation-name:rollIn}@-webkit-keyframes rollOut{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg)}}@keyframes rollOut{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg)}}.rollOut{-webkit-animation-name:rollOut;animation-name:rollOut}@-webkit-keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}@keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}.zoomIn{-webkit-animation-name:zoomIn;animation-name:zoomIn}@-webkit-keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomInDown{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomInLeft{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes zoomInRight{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomInRight{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomInRight{-webkit-animation-name:zoomInRight;animation-name:zoomInRight}@-webkit-keyframes zoomInUp{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomInUp{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomInUp{-webkit-animation-name:zoomInUp;animation-name:zoomInUp}@-webkit-keyframes zoomOut{0%{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}100%{opacity:0}}@keyframes zoomOut{0%{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}100%{opacity:0}}.zoomOut{-webkit-animation-name:zoomOut;animation-name:zoomOut}@-webkit-keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomOutDown{-webkit-animation-name:zoomOutDown;animation-name:zoomOutDown}@-webkit-keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;transform-origin:left center}}@keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;transform-origin:left center}}.zoomOutLeft{-webkit-animation-name:zoomOutLeft;animation-name:zoomOutLeft}@-webkit-keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;transform-origin:right center}}@keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;transform-origin:right center}}.zoomOutRight{-webkit-animation-name:zoomOutRight;animation-name:zoomOutRight}@-webkit-keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomOutUp{-webkit-animation-name:zoomOutUp;animation-name:zoomOutUp}@-webkit-keyframes slideInDown{0%{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0)}}@keyframes slideInDown{0%{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInDown{-webkit-animation-name:slideInDown;animation-name:slideInDown}@-webkit-keyframes slideInLeft{0%{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0)}}@keyframes slideInLeft{0%{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInLeft{-webkit-animation-name:slideInLeft;animation-name:slideInLeft}@-webkit-keyframes slideInRight{0%{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0)}}@keyframes slideInRight{0%{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInRight{-webkit-animation-name:slideInRight;animation-name:slideInRight}@-webkit-keyframes slideInUp{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0)}}@keyframes slideInUp{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInUp{-webkit-animation-name:slideInUp;animation-name:slideInUp}@-webkit-keyframes slideOutDown{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%)}}@keyframes slideOutDown{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.slideOutDown{-webkit-animation-name:slideOutDown;animation-name:slideOutDown}@-webkit-keyframes slideOutLeft{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%)}}@keyframes slideOutLeft{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.slideOutLeft{-webkit-animation-name:slideOutLeft;animation-name:slideOutLeft}@-webkit-keyframes slideOutRight{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%)}}@keyframes slideOutRight{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.slideOutRight{-webkit-animation-name:slideOutRight;animation-name:slideOutRight}@-webkit-keyframes slideOutUp{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%)}}@keyframes slideOutUp{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.slideOutUp{-webkit-animation-name:slideOutUp;animation-name:slideOutUp} \ No newline at end of file diff --git a/dashboardv2/public/css/bootstrap-sidebar.css b/dashboardv2/public/css/bootstrap-sidebar.css deleted file mode 100644 index 23db223b5a1..00000000000 --- a/dashboardv2/public/css/bootstrap-sidebar.css +++ /dev/null @@ -1,150 +0,0 @@ -/*! - * Start Bootstrap - Simple Sidebar (http://startbootstrap.com/) - * Copyright 2013-2016 Start Bootstrap - * Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap/blob/gh-pages/LICENSE) - */ - - -/* Toggle Styles */ - -#wrapper { - padding-left: 0; - -webkit-transition: all 0.3s ease; - -moz-transition: all 0.3s ease; - -o-transition: all 0.3s ease; - transition: all 0.3s ease; -} - -#wrapper.toggled { - padding-left: 300px; -} - -#sidebar-wrapper { - z-index: 1000; - position: fixed; - left: 350px; - width: 0; - height: 100%; - margin-left: -350px; - overflow-y: auto; - background: #323544; - -moz-transition: left 0.3s; - -o-transition: left 0.3s; - -webkit-transition: left 0.3s; - transition: left 0.3s; -} - -#wrapper.toggled #sidebar-wrapper { - width: 350px; -} - -#page-content-wrapper { - width: 100%; - position: absolute; -} - -#wrapper.toggled #page-content-wrapper { - position: absolute; - margin-right: -350px; -} - - -/* Sidebar Styles */ - -.sidebar-nav { - margin: 0; - padding: 0; - list-style: none; -} - -.sidebar-nav>li { - line-height: 50px; - padding: 5px 20px; - border-bottom: 1px #1c1e2a solid; -} - -.sidebar-nav>li a { - display: block; - text-decoration: none; - color: #fff; -} - -.sidebar-nav>li a:hover { - text-decoration: none; - color: #fff; -} - -.sidebar-nav>li a:active, -.sidebar-nav>li a:focus { - text-decoration: none; -} - -.sidebar-nav>.sidebar-brand { - font-size: 18px; - line-height: 50px; -} - -.sidebar-nav>.sidebar-brand a { - color: #ddd; - letter-spacing: 1px; -} - -.sidebar-nav>.sidebar-brand a:hover { - color: #fff; - background: none; -} - - -/* Extended Elements */ - -.sidebar-input .input-group { - margin: 10px 0px; -} - -.sidebar-input .form-control, -.sidebar-input .input-group-addon { - background-color: transparent; - border-radius: 0px; -} - -.sidebar-input .form-control { - border-right: none; - color: #eee; -} - -.sidebar-input .input-group-addon { - border-left: none; - color: #ccc; -} - -.sidebar-input .form-control:focus+.input-group-addon { - border-color: #66afe9; -} - -@media(min-width:768px) { - #wrapper { - padding-left: 350px; - } - - #wrapper.toggled { - padding-left: 0; - } - - #sidebar-wrapper { - width: 350px; - } - - #wrapper.toggled #sidebar-wrapper { - width: 0; - padding: 0; - } - - #page-content-wrapper { - position: relative; - } - - #wrapper.toggled #page-content-wrapper { - position: relative; - margin-right: 0; - } -} \ No newline at end of file diff --git a/dashboardv2/public/css/googlefonts.css b/dashboardv2/public/css/googlefonts.css deleted file mode 100644 index 53ffba87497..00000000000 --- a/dashboardv2/public/css/googlefonts.css +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - - -/* source-sans-pro-regular - latin */ - -@font-face { - font-family: 'Source Sans Pro'; - font-style: normal; - font-weight: 400; - src: url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.eot'); - /* IE9 Compat Modes */ - src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff') format('woff'), /* Modern Browsers */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.svg#SourceSansPro') format('svg'); - /* Legacy iOS */ -} - - -/* source-sans-pro-600 - latin */ - -@font-face { - font-family: 'Source Sans Pro'; - font-style: normal; - font-weight: 600; - src: url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.eot'); - /* IE9 Compat Modes */ - src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff2') format('woff2'), /* Super Modern Browsers */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff') format('woff'), /* Modern Browsers */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.ttf') format('truetype'), /* Safari, Android, iOS */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.svg#SourceSansPro') format('svg'); - /* Legacy iOS */ -} - - -/* source-sans-pro-700 - latin */ - -@font-face { - font-family: 'Source Sans Pro'; - font-style: normal; - font-weight: 700; - src: url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.eot'); - /* IE9 Compat Modes */ - src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff2') format('woff2'), /* Super Modern Browsers */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff') format('woff'), /* Modern Browsers */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.ttf') format('truetype'), /* Safari, Android, iOS */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.svg#SourceSansPro') format('svg'); - /* Legacy iOS */ -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/__mixin.scss b/dashboardv2/public/css/scss/__mixin.scss deleted file mode 100644 index f3ce565cb58..00000000000 --- a/dashboardv2/public/css/scss/__mixin.scss +++ /dev/null @@ -1,72 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -@mixin clearfix() { - - &:before, - &:after { - content: " "; // 1 - display: table; // 2 - } - - &:after { - clear: both; - } -} - -@mixin ellipsis() { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; -} - -@mixin transition($transition...) { - -webkit-transition: $transition; - -moz-transition: $transition; - -o-transition: $transition; - transition: $transition; -} - -@mixin transition-property($properties...) { - -webkit-transition-property: $properties; - -moz-transition-property: $properties; - -o-transition-property: $properties; - transition-property: $properties; -} - -@mixin btn-action-effect($color) { - @if $color=='default' { - border: 1px $color_keppel_approx solid; - color: $color_keppel_approx; - } - - @else if $color=='blue' { - border: 1px $color_havelock_blue_approx solid; - color: $color_havelock_blue_approx; - } -} - -@mixin btn-action-hover-effect($color1) { - @if $color1=='default' { - background-color: $color_keppel_approx; - color: $white; - } - - @else if $color1=='blue' { - color: $white; - background-color: $tag_color; - } -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/__variable.scss b/dashboardv2/public/css/scss/__variable.scss deleted file mode 100644 index 1d1cbb4503b..00000000000 --- a/dashboardv2/public/css/scss/__variable.scss +++ /dev/null @@ -1,100 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -//fonts -$font_0: Source Sans Pro; -$font_1: sans-serif; -$font_2: FontAwesome; -$font_3: Helvetica; -$font_4: Arial; -$font_5: sans-serf; -//Colors -$white: #fff; -$black: #000; -$red: #f00; -$gray: #808080; -$dark_gray: #666; -$action_gray: #999999; -$color_keppel_approx: #37bb9b; -$color_gallery_approx: #eee; -$color_tuna_approx: #323544; -$color_celeste_approx: #ccc; -$color_cornflower_blue_approx: #66afe9; -$color_mystic_approx: #e8e9ee; -$color_jungle_green_approx: #38bb9b; -$color_jungle_green_light: #7ed3be; -$color_froly_approx: #ee6e73; -$color_manatee_approx: #9398a0; -$color_havelock_blue_approx: #4a90e2; -$color_ironside_gray_approx: #686868; -$color_mercury_approx: #e6e6e6; -$color_whisper_approx: #f6f7fa; -$color_bombay_approx: #b5b9bc; -$color_white_lilac_approx: #f6f7fb; -$color_puerto_rico_approx: #3dd4af; -$color_star_dust_approx: #9a9a9a; -$color_mirage_approx: #1c1e2a; -$concrete: #f2f2f2; -$lightGrey: #e1e2e4; -$color_form_control: #e8e8e8; -$attribute-dash-box: #cbcbcb; -//old - style color -$color_bali_hai_approx: #8fa5b1; -$transparent: transparent; -$black_7_5: rgba(0, 0, 0, 0.075); -$color_hoki_approx: #698797; -$color_curious_blue_approx: #1ba9e2; -$color_blue_bayoux_approx: #44697d; -$color_pickled_bluewood_approx: #334f5e; -$color_picton_blue_approx: #3cb5e6; -$color_yellow_sea_approx: #f5a700; -$color_gamboge_approx: #de9800; -$color_trinidad_approx: #e14f00; -$color_grenadier_approx: #c74600; -$color_athens_gray_approx: #e9ecf2; -$color_green_house_approx: #26530c; -$color_dark_grey_approx: #333; -$black_10: rgba(0, 0, 0, 0.1); -$color_cararra_approx: #ececec; -$black_30: rgba(0, 0, 0, 0.3); -$color_pizazz_approx: #ff8e00; -$black_25: rgba(0, 0, 0, 0.25); -$color_cape_cod_approx: #414141; -$color_apple_blossom_approx: #a94442; -$color_mine_shaft_approx: #333; -$white_80: rgba(255, 255, 255, 0.8); -$color_alto_approx: #dadada; -$color_fuscous_gray_approx: #545454; -$black_65: rgba(0, 0, 0, 0.65); -$white_25: rgba(255, 255, 255, 0.25); -$color_fern_approx: #65bd63; -$color_opal_approx: #a7cec6; -$white_50: rgba(255, 255, 255, 0.5); -$black_20: rgba(0, 0, 0, 0.2); -$color_pelorous_approx: #3aa2d0; -$color_laser_approx: #c4bb61; -$color_zombie_approx: #e0dd94; -$steel_blue: steelblue; -$black_80: rgba(0, 0, 0, 0.8); -$color_bright_turquoise_approx: #00ffd0; -$color_mountain_mist_approx: #999; -$color_suva_gray_approx: #868686; -$tag_color: #4a90e2; -$delete_link: #bb5838; -//urls -$url_0: url(../img/loading.gif); - -$switchTransition: 0.4s ease-out; \ No newline at end of file diff --git a/dashboardv2/public/css/scss/business-metadata.scss b/dashboardv2/public/css/scss/business-metadata.scss deleted file mode 100644 index 5bcbb5df9fc..00000000000 --- a/dashboardv2/public/css/scss/business-metadata.scss +++ /dev/null @@ -1,243 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* business-metadata */ -.business-metadata-tree-parent { - padding: 0px; - - >li:first-child { - font-weight: 600; - word-break: break-all; - } - - .business-metadata-tree-child { - &.entity-detail-table table { - td { - &:nth-child(1) { - width: 35%; - } - - word-break: break-word; - } - } - - padding-left: 5px; - margin-top: 10px; - font-weight: 100; - } - - .custom-table { - &:not(.bm-create) { - .custom-tr { - - .custom-col-1 { - width: calc(50% - 55px); - - .select2-selection--multiple .select2-selection__rendered { - overflow: scroll; - } - } - - .custom-col-2 { - width: 45px; - } - } - } - } - -} - -.business-metadata-options.dropdown { - .dropdown-menu { - min-width: 100px; - - .dropdown-item { - display: block; - width: 100%; - padding: .25rem 1.5rem; - clear: both; - font-weight: 400; - color: $color_jungle_green_approx; - text-align: inherit; - white-space: nowrap; - background-color: transparent; - border: 0; - } - } -} - -.business-metadata-options.dropdown.open { - .btn-action { - background-color: $color_jungle_green_approx; - border: 1px solid $color_jungle_green_approx; - color: #fff !important; - } -} - -.business-metadata-details, -.admin-details { - .tableOverlay { - background-color: transparent; - } - - .expandable .attr-details { - max-height: 300px; - overflow: auto; - margin-left: 30px; - width: calc(100% - 30px); - } - - .expandable .admin-audit-details { - display: flex; - flex-wrap: wrap; - margin-left: 20px; - - .attr-type-container { - border: 1px solid #ddd; - border-radius: 4px; - padding: 5px 10px; - margin: 5px; - width: 32%; - } - } - - .expandable .admin-attr-details { - max-height: 100px; - margin-left: 20px; - width: calc(100% - 27px); - } - - .import-export .admin-audit-details { - display: table; - border: 1px solid #ddd; - border-radius: 4px; - - tr>td:nth-child(2) { - text-align: right; - } - } -} - -.admin-details .expandable .admin-audit-details .attr-type-container { - max-height: 200px; - overflow: auto; -} - -.admin-details .attributeResultContainer { - float: left; -} - -.tab-pane { - .business-metadata-attr-page { - position: absolute; - top: 62px; - left: 0px; - padding: 20px; - background-color: $white; - width: 100%; - height: inherit; - } -} - -.business-metadata-attr-page { - .form-horizontal { - padding: 10px 22px; - // border: 1px solid #DEDEDE; - - .control-label-sm { - padding-top: 3px; - } - - .control-label-sm-pl { - @extend .control-label-sm; - padding-left: 10px; - } - - .control-label-sm-pr { - @extend .control-label-sm; - padding-right: 10px; - } - - .business-metadata-attr { - border: 1px solid #DEDEDE; - padding: 10px 20px - } - } -} - -.business-metadata-attr-fontLoader { - position: absolute; - top: 50%; - left: 50%; - display: none; -} - -.business-metadata-attr-tableOverlay { - position: absolute; - width: calc(100% - 40px); - height: 100%; - background: #808080; - z-index: 99; - display: none; - opacity: 0.2; -} - -.business-metadata-attr-page { - .modal-footer { - text-align: center; - } -} - -.remove-from-list { - .select2-results__option[aria-selected=true] { - display: none; - } -} - -.business-metadata-detail-attr { - margin-bottom: 0px; - box-shadow: none; - - .panel-heading { - color: #686868 !important; - font-size: 13px; - padding: 0; - - .panel-title { - font-size: 14px; - word-break: break-all; - width: inherit; - - a:hover { - color: #686868 !important; - opacity: 1 !important; - } - } - } - - .btn-group>button { - color: #686868 !important; - } - - td { - word-break: break-word; - } - - .business-metadata-detail-attr-key { - width: 30%; - } -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/common.scss b/dashboardv2/public/css/scss/common.scss deleted file mode 100644 index 5bf8b6131da..00000000000 --- a/dashboardv2/public/css/scss/common.scss +++ /dev/null @@ -1,347 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -/* common.scss */ -.readOnly { - - span, - button, - a { - i { - &.fa-trash[data-guid] { - display: none; - } - - &.fa-trash[data-id="delete"] { - display: none; - } - } - - &.btn[data-id="addTag"] { - display: none; - } - - &.btn[data-id="addTerm"] { - display: none; - } - - &.btn[data-id="editButton"] { - display: none; - } - - &.editbutton[data-id="editButton"] { - display: none !important; - } - - &[data-id="delete"], - &[data-id="edit"] { - display: none; - } - - &.btn[data-id="tagClick"] { - span { - display: block; - padding: 3px 5px 3px 5px; - } - - i.fa-close[data-id="deleteTag"], - i.fa-times[data-id="deleteTag"], - i.fa-times[data-id="delete"] { - display: none; - } - } - } -} - -.details-backbutton { - display: none !important; -} - -.full-screen { - #sidebar-wrapper { - left: 0; - } - - #wrapper { - padding-left: 0px; - } -} - -.detail-page { - .details-backbutton { - display: table-cell !important; - } - - .searched-term-highlight { - background-color: #eeee31; - transition: background-color 4s, font-weight 2s; - - &.bold { - background-color: transparent; - font-weight: bold; - } - } -} - -pre { - background-color: ghostwhite; - border: 1px solid silver; - padding: 10px; - white-space: -moz-pre-wrap; - /* Mozilla, supported since 1999 */ - white-space: -pre-wrap; - /* Opera */ - white-space: -o-pre-wrap; - /* Opera */ - white-space: pre-wrap; - /* CSS3 - Text module (Candidate Recommendation) http://www.w3.org/TR/css3-text/#white-space */ - word-wrap: break-word; - - /* IE 5.5+ */ - &.code-block { - code { - position: relative; - max-height: 400px; - display: block; - overflow: auto; - text-align: left; - } - - position: relative; - overflow: hidden; - - &.shrink { - height: 112px; - white-space: -moz-pre-wrap; - /* Mozilla, supported since 1999 */ - white-space: -pre-wrap; - /* Opera */ - white-space: -o-pre-wrap; - /* Opera */ - white-space: pre-wrap; - /* CSS3 - Text module (Candidate Recommendation) http://www.w3.org/TR/css3-text/#white-space */ - word-wrap: break-word; - - /* IE 5.5+ */ - code { - height: 100px; - } - - &.fixed-height { - height: 75px; - - code { - height: 54px; - } - } - - &.medium-height { - height: 100px; - } - - .expand-collapse-button { - i:before { - content: "\f107"; - } - } - } - - .expand-collapse-button { - position: absolute; - right: 3px; - top: 4px; - z-index: 1; - - i:before { - content: "\f106"; - } - } - - .json-key { - color: brown; - } - - .json-value { - color: navy; - } - - .json-string { - color: olive; - - &.cursor { - cursor: pointer; - text-decoration: underline; - } - } - } - - code { - font-family: monospace; - } -} - -.panel-body .memory-details { - pre { - &.code-block { - &.fixed-height { - max-height: 112px; - overflow: auto; - } - - &.shrink { - height: 144px; - - code { - height: 130px; - } - } - } - } -} - -.footer-content { - position: fixed; - right: 0px; - padding: 2px; - bottom: 0; - background: white; -} - -#accordion { - .panel-default>.panel-heading { - cursor: pointer; - width: 100%; - } -} - -.custom-table { - width: 100%; - display: flex; - - tbody { - display: flex; - flex-flow: column; - width: 100%; - } - - .custom-tr { - margin-left: 15px; - display: flex; - width: calc(100% - 15px); - - .custom-col-0, - .custom-col-1, - .custom-col-2 { - vertical-align: top; - display: inline-block; - - textarea { - resize: vertical; - height: 34px; - min-height: 34px; - max-height: 70px; - } - } - - - .custom-col-0 { - line-height: 31px; - width: 9px; - padding: 0px 2px; - } - - .custom-col-1 { - width: calc(50% - 90px); - flex-grow: 2; - - &:first-child { - width: 30% !important; - flex-grow: 1; - } - } - - .custom-col-2 { - text-align: center; - width: 80px; - padding-left: 10px; - - &>button { - padding: 7px 10px; - margin-bottom: 10px; - } - } - } -} - -.errorMsg { - color: $red; -} - -.badge-default { - background-color: $color_havelock_blue_approx; - color: $white; - font-size: 12px; - font-weight: normal; - margin-bottom: 5px; - margin-left: 5px; - float: left; -} - -.errorValidate { - border-color: red !important; -} - -.errorValidate+span .select2-selection { - border-color: red !important; - -} - -.button-loader { - position: relative; - padding-left: 22px !important; - - &:after { - content: "\f021"; - position: absolute; - display: flex; - justify-content: center; - align-items: center; - left: 0px; - top: 0px; - font-family: FontAwesome; - background: transparent; - height: 100%; - width: 26px; - font-size: 11px; - animation: spin 1000ms infinite linear; - } -} - -.attr-details { - ul { - list-style: disc; - - li { - cursor: pointer; - } - } -} - -.long-description { - width: 85%; - cursor: default !important; - background-color: transparent !important; -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/form.scss b/dashboardv2/public/css/scss/form.scss deleted file mode 100644 index 68761e18a14..00000000000 --- a/dashboardv2/public/css/scss/form.scss +++ /dev/null @@ -1,548 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -/* form.scss */ - -.form-horizontal { - .control-label-sm { - padding-top: 3px; - } - - .control-label-sm-pl { - @extend .control-label-sm; - padding-left: 10px; - } - - .control-label-sm-pr { - @extend .control-label-sm; - padding-right: 10px; - } -} - -.form-group { - .required:after { - content: "*"; - padding-left: 1%; - color: $red; - } - - .control-label { - &.text-left { - text-align: left; - } - - &.text-right { - text-align: right; - } - } - - .form-control { - //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - background-color: $color_white_lilac_approx; - border: 1px $color_mystic_approx solid; - - &[disabled] { - background-color: $color_gallery_approx; - } - - &:focus { - border-color: $color_bali_hai_approx; - outline: 0; //Instead of the line below you could use @include box-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - box-shadow: inset 0 1px 1px $black_7_5, 0 0 2px $color_bali_hai_approx; - } - } -} - -.form-color { - - .form-group span[class^="select2-selection select2-selection--"], - .form-control { - background-color: $color_form_control !important; - } -} - -.sidebar-wrapper { - z-index: 9 !important; - - .form-control { - background-color: $white; - border: 1px $white solid; - } -} - -.well { - background-color: $color_whisper_approx; - border: 1px solid $color_mystic_approx; -} - -textarea { - resize: none; - - &:focus { - outline: none !important; - } -} - -label { - font-weight: 600; -} - -button { - &:focus { - outline: none !important; - } - - &[disabled] { - .fa { - opacity: .65; - } - } -} - -.btn { - //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 4px; - - &:hover { - text-decoration: none; - } -} - -[class^="col-md-"], -[class^="col-sm-"] { - - .btn.checkbox-inline, - .btn.radio-inline { - padding-left: 19px; - } -} - -.btn-primary { - color: $white; - background-color: $color_blue_bayoux_approx; - border-color: $color_blue_bayoux_approx; - - &:hover { - color: $white; - background-color: $color_pickled_bluewood_approx; - border-color: $color_pickled_bluewood_approx; - } -} - -.btn-success { - color: $white; - background-color: $color_jungle_green_approx; - border-color: $color_jungle_green_approx; - - &:hover { - color: $white; - background-color: $color_jungle_green_approx; - border-color: $color_jungle_green_approx; - } - - &:focus { - color: $white; - background-color: $color_jungle_green_approx; - border-color: $color_jungle_green_approx; - } -} - -.btn-info { - color: $white; - background-color: $color_picton_blue_approx; - border-color: $color_picton_blue_approx; - - &:hover { - color: $white; - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - } - - &:focus { - color: $white; - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - } -} - -.btn-warning { - color: $white; - background-color: $color_yellow_sea_approx; - border-color: $color_yellow_sea_approx; - - &:hover { - color: $white; - background-color: $color_gamboge_approx; - border-color: $color_gamboge_approx; - } - - &:focus { - color: $white; - background-color: $color_gamboge_approx; - border-color: $color_gamboge_approx; - } -} - -.btn-danger { - color: $white; - background-color: $color_trinidad_approx; - border-color: $color_trinidad_approx; - - &:hover { - color: $white; - background-color: $color_grenadier_approx; - border-color: $color_grenadier_approx; - } - - &:focus { - color: $white; - background-color: $color_grenadier_approx; - border-color: $color_grenadier_approx; - } -} - -.btn-atlas { - padding: 10px 20px; - background-color: $color_keppel_approx; - color: $white; - margin-bottom: 10px; - border: 1px $color_keppel_approx solid; //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 4px; //Instead of the line below you could use @include transition($transition-1, $transition-2, $transition-3, $transition-4, $transition-5, $transition-6, $transition-7, $transition-8, $transition-9, $transition-10) - transition: all 0.3s ease; - margin: 2px; - - &:hover { - @include btn-action-effect('default'); - background-color: $transparent; - } - - &:focus { - @include btn-action-effect('default'); - background-color: $transparent; - } - - &.btn-sm { - padding: 2px 6px; - } - - &.btn-md { - padding: 6px 10px; - } -} - -.btn-inline { - .btn-action { - margin: 0px 3px 3px 0px; - display: inline-block; - } -} - -.btn-fixed-width { - .btn-icon { - min-width: 100px; - - &.propagte-classification { - >span { - width: 98px; - } - } - - >span { - @include ellipsis(); - float: left; - width: 76px; - padding: 2px 5px !important; - } - - >i { - float: right; - line-height: 15px; - } - } -} - -.btn-action { - @extend .btn-atlas; - @include btn-action-effect('default'); - border-radius: 4px; - font-size: 14px; - background-color: $transparent; - - &.active { - @include btn-action-hover-effect('default'); - } - - &:hover { - @include btn-action-hover-effect('default'); - color: $white !important; - } - - &:focus { - @include btn-action-effect('default'); - } - - &.btn-sm { - padding: 2px 6px; - } - - &.btn-md { - padding: 5px 10px; - } - - &.btn-blue { - @include btn-action-effect('blue'); - - &.active { - @include btn-action-hover-effect('blue'); - } - - &:hover { - @include btn-action-hover-effect('blue'); - } - - &:focus { - @include btn-action-effect('blue'); - } - - &.btn-icon { - @include btn-action-effect('blue'); - color: $tag_color !important; - - &:hover { - color: $color_havelock_blue_approx; - background-color: $transparent; - } - - >span { - &:hover { - @include btn-action-hover-effect('blue'); - } - } - - i.fa { - &:hover { - @include btn-action-hover-effect('blue'); - } - } - } - } - - &.btn-disabled { - border: 1px $action_gray solid; - color: $action_gray; - cursor: default; - - i.fa { - position: relative; - right: -5px; - } - - &:hover { - color: $white; - background-color: $action_gray; - } - } - - &.btn-icon { - padding: 0px; - overflow: hidden; - background-color: $transparent; - - &:hover { - color: $color_keppel_approx; - background-color: $transparent; - } - - >span { - padding: 5px; - - &.active { - color: $white; - background-color: $tag_color; - } - - &:hover { - @include btn-action-hover-effect('default'); - } - } - - i.fa { - position: relative; - padding: 5px; - cursor: pointer; - - &:hover { - @include btn-action-hover-effect('default'); - } - } - } - - &.btn-icon-pd { - i.fa { - padding: 5px; - cursor: pointer; - } - } -} - -.btn-group { - - .btn-atlas, - .btn-action { - margin: 0px; - } -} - -.pagination>.active { - >a { - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - - &:focus { - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - } - - &:hover { - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - } - } - - >span { - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - - &:focus { - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - } - - &:hover { - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - } - } -} - -.deleteBtn { - border-color: $color_mountain_mist_approx; - color: $color_mountain_mist_approx; - cursor: default; - margin: 0px 10px; - - &:hover { - border-color: $color_mountain_mist_approx; - color: $color_mountain_mist_approx !important; - background-color: $transparent; - } - - &:focus { - border-color: $color_mountain_mist_approx; - color: $color_mountain_mist_approx; - background-color: $transparent; - } -} - -.block { - display: block !important; -} - -.list-style-disc { - list-style: disc; -} - -.has-feedback.align-left { - .form-control { - padding-left: 32.5px; - padding-right: 12px; - } - - .form-control-feedback { - top: 10px; - left: 0px; - height: 14px - } -} - -.has-feedback.align-left-right-icon { - position: relative; - - .form-control { - padding-left: 32.5px; - padding-right: 32.5px; - } - - .form-control-feedback { - top: 10px; - height: 14px; - - &:first-child { - left: 0; - } - - &.clearable:last-child { - right: 0; - overflow: hidden; - padding-left: 33px; - transition: padding 0.4s; - pointer-events: all; - cursor: pointer; - - &.in { - padding-left: 0; - } - } - } -} - -.create-entity-form { - &.all { - .attribute-dash-box { - &.alloptional { - display: block; - } - } - } - - .attribute-dash-box { - border-style: dashed; - border-width: 2px; - border-spacing: 8px; - border-radius: 12px; - border-color: $attribute-dash-box; - position: relative; - padding: 18px 10px 0px 10px; - margin-top: 25px; - - span.required:after { - content: "*"; - padding-left: 1%; - color: $red; - } - - &.alloptional { - display: none; - } - - .attribute-type-label { - background: $white; - padding: 5px 10px; - position: absolute; - top: -16px; - } - } -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/glossary.scss b/dashboardv2/public/css/scss/glossary.scss deleted file mode 100644 index bc1c5969a4d..00000000000 --- a/dashboardv2/public/css/scss/glossary.scss +++ /dev/null @@ -1,68 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -.jstree-contextmenu { - z-index: 99; -} - -.jstree-default-dark { - background: transparent !important; - - .jstree-anchor { - width: calc(100% - 50px); - overflow: hidden; - text-overflow: ellipsis; - } - - .jstree-children.jstree-children>li>a { - max-width: 500px; - } - - .jstree-clicked, - .jstree-wholerow-clicked { - background: $color_jungle_green_approx !important; - } - - .jstree-hovered { - background: $color_star_dust_approx; - } - - .jstree-anchor { - color: #dbdbdb; - } - - .jstree-search { - color: #fbfece !important - } - - li[role="treeitem"] { - .jstree-wholerow-clicked { - .tools { - display: inline-block; - } - } - - .tools { - display: none; - position: absolute; - width: 30px; - text-align: center; - cursor: pointer; - top: 0; - right: 0; - } - } -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/graph.scss b/dashboardv2/public/css/scss/graph.scss deleted file mode 100644 index a369841fb51..00000000000 --- a/dashboardv2/public/css/scss/graph.scss +++ /dev/null @@ -1,349 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -/* graph.scss */ - -.invisible { - .node circle { - transition: all 0s; - } -} - -.graph-toolbar { - background-color: $white; - margin-bottom: 10px; - padding: 10px; -} - -.legends { - >i { - >span { - font-family: "Source Sans Pro"; - } - } -} - -.lineage-box { - position: absolute; - height: 100%; - width: 100%; - overflow: hidden; -} - -.graph-button-group { - &>div { - display: inline-block; - } - - .zoom-button-group {} -} - -.box-panel { - position: absolute; - top: 37px; - border: 1px solid #ccc; - width: 250px; - max-height: 99%; - overflow: auto; - transition: all 0.3s ease; - right: -273px; - background-color: $white; - z-index: 999; - box-shadow: 1px 19px 22px -17px; - border-radius: 10px; - max-height: 88%; - - &.slide-from-left { - left: -273px; - right: 0px; - - &.size-lg { - left: -373px; - } - } - - &.size-lg { - width: 350px; - } - - &.show-box-panel { - right: 0px !important; - - &.slide-from-left { - left: 0; - } - } - - .entity-list { - overflow: auto; - list-style-type: decimal; - list-style-position: outside; - padding-left: 15px; - } - - ul>li { - word-wrap: break-word; - margin-bottom: 5px; - text-align: left; - - &.deleted-relation { - .deleteBtn { - padding: 2px 8px !important; - margin: 5px 5px !important; - } - } - } - - .header { - background: $color_havelock_blue_approx; - color: white; - position: relative; - text-align: center; - width: 100%; - position: sticky; - height: 37px; - top: 0; - z-index: 999; - - >h4 { - padding: 0px 36px 0px 10px; - word-break: break-all; - } - - .btn-close { - position: absolute; - right: 0px; - top: 0px; - font-size: 18px; - - &:hover { - color: $white; - } - } - } - - .body { - padding: 10px; - width: 100%; - position: relative; - height: calc(100% - 37px); - overflow: hidden; - } -} - -.btn-gray { - border: 1px solid #686868; - color: $dark_gray; - background: white; - - &[disabled] { - opacity: 0.3; - } - - &:hover { - border: 1px solid #686868; - color: $dark_gray !important; - background-color: white !important; - } -} - -span#zoom_in { - border-bottom: 1px solid #625555; -} - -.depth-container { - - //display: inline-block; - //margin-top: 3px; - .inline { - display: inline-block; - } -} - -.resizeGraph { - position: relative; - width: 100%; - height: 64vh; - overflow: hidden !important; - - &.auto-height { - height: auto !important; - } -} - -.active.fullscreen-mode { - position: fixed !important; - height: 100% !important; - top: 0; - bottom: 0; - left: 0; - width: 100%; - right: 0; - padding: 0 !important; - z-index: 99; - overflow: hidden !important; - background: white; - - .systemTypeTree { - height: 100vh !important; - padding: 10px; - } - - .resizeGraph { - position: fixed; - height: 100% !important; - - .ui-resizable-handle { - display: none; - } - } - - .lineage-box { - padding: 10px !important; - } - - .box-panel { - margin: 10px !important; - } -} - -.lineage-node-detail { - .table-quickMenu { - td:nth-child(1n) { - width: 150px; - } - - word-break: break-all; - } -} - -#tab-relationship { - .entity-status { - &.active { - color: $color_jungle_green_approx; - } - - &.deleted { - color: $delete_link; - } - } - - .entity-list { - list-style-position: inside; - } -} - -@-webkit-keyframes blink { - from { - opacity: 0.2; - } - - to { - opacity: 0.5; - } -} - -.mini-map-type-system { - background: white; - width: 200px; - position: absolute; - bottom: 5px; - right: 5px; - - &>svg { - box-shadow: 0px 0px 3px 1px #80808080; - } - -} - - -.box-panel.fix-box { - position: absolute; - top: 37px; - right: 0; - bottom: 0; - height: auto; - max-height: initial; - z-index: 999; - bottom: 0; - width: 400px; - overflow: hidden; - border-radius: 10px; - margin: 0 !important; - - &.slide-from-right.size-lg { - right: -413px; - - &.show-box-panel { - right: 0px; - } - } - - .body { - - position: relative; - - table{ - position: relative; - height: 100%; - } - tbody { - overflow: auto; - height: auto; - display: block; - position: absolute; - padding-bottom: 15px; - } - } -} - -.profile-bar { - fill: #38bb9b; - stroke: #38bb9b; - fill-opacity: 0.75; -} - -.axislabel { - text-anchor: middle; - fill: #999; - font: 400 12px Arial, sans-serif; -} - -.grid { - - path, - line { - stroke: lightgrey; - stroke-opacity: 0.7; - shape-rendering: crispEdges; - } -} - -.d3-tip { - table td { - padding: 2px 9px 2px 0; - vertical-align: middle; - - &.value { - text-align: right; - font-weight: 700; - } - - &.key { - font-weight: 400; - } - } -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/loader.scss b/dashboardv2/public/css/scss/loader.scss deleted file mode 100644 index a7db0ad5951..00000000000 --- a/dashboardv2/public/css/scss/loader.scss +++ /dev/null @@ -1,172 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* loader.scss */ - -.fa-spin-custom { - animation: spin 1000ms infinite linear; -} - -@-webkit-keyframes spin { - 0% { - //Instead of the line below you could use @include transform($scale, $rotate, $transx, $transy, $skewx, $skewy, $originx, $originy) - transform: rotate(0deg); - } - - 100% { - //Instead of the line below you could use @include transform($scale, $rotate, $transx, $transy, $skewx, $skewy, $originx, $originy) - transform: rotate(359deg); - } -} - -@keyframes spin { - 0% { - //Instead of the line below you could use @include transform($scale, $rotate, $transx, $transy, $skewx, $skewy, $originx, $originy) - transform: rotate(0deg); - } - - 100% { - //Instead of the line below you could use @include transform($scale, $rotate, $transx, $transy, $skewx, $skewy, $originx, $originy) - transform: rotate(359deg); - } -} - -.contentLoading { - position: absolute; - background: rgba(247, 247, 247, 0.24); - top: 0; - right: 0; - left: 0; - z-index: 99; - bottom: 0; - display: none; -} - -.fontLoader { - top: 50%; - left: 50%; - position: absolute; - display: none; -} - -.fontLoader-relative { - @extend .fontLoader; - position: relative; - left: 0%; - text-align: center; -} - -.initialLoading { - position: fixed; - top: 0; - right: 0; - left: 0; - bottom: 0; - background: url("../img/ring.gif") no-repeat; - background-position: 50% 50%; - background-size: 60px; - - @media (min-width: 768px) { - left: 350px; - } -} - -.tableOverlay { - position: absolute; - width: 100%; - height: 100%; - background: $gray; - z-index: 99; - display: none; - opacity: 0.2; -} - -.value-loader { - height: 4px; - width: 50%; - position: relative; - overflow: hidden; - background-color: #ddd; -} - -.value-loader:before { - display: block; - position: absolute; - content: ""; - left: -200px; - width: 200px; - height: 4px; - background-color: #2980b9; - animation: value-loader 2s linear infinite; -} - -@keyframes value-loader { - from { - left: -200px; - width: 30%; - } - - 50% { - width: 30%; - } - - 70% { - width: 70%; - } - - 80% { - left: 50%; - } - - 95% { - left: 120%; - } - - to { - left: 100%; - } -} - -.searchTableLogoLoader { - width: 20px; - -webkit-animation-duration: 1.5s; - animation-duration: 1.5s; - -webkit-animation-fill-mode: forwards; - animation-fill-mode: forwards; - -webkit-animation-iteration-count: infinite; - animation-iteration-count: infinite; - -webkit-animation-timing-function: linear; - animation-timing-function: linear; - -webkit-animation-name: placeHolderLoader; - animation-name: placeHolderLoader; - background: #f6f7f8; - background: linear-gradient(to right, #eeeeee 8%, #dddddd 18%, #eeeeee 33%); - background-size: 700px 10px; - border-radius: 8px; - outline: 1px #fff solid; - outline-offset: -1px; -} - -@keyframes placeHolderLoader { - 0% { - background-position: -468px 0; - } - - 100% { - background-position: 468px 0; - } -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/login.scss b/dashboardv2/public/css/scss/login.scss deleted file mode 100644 index d4dba17f1c9..00000000000 --- a/dashboardv2/public/css/scss/login.scss +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -@import "__variable.scss"; - -body { - font-family: $font_0, $font_1; - background-color: $color_white_lilac_approx; - color: $color_dark_grey_approx; - font-size: 14px; - line-height: 1.42857143; -} - -.login-body { - height: 100vh; - padding-top: calc(50vh - 206px); - - .login-form { - padding: 60px; - width: 500px; - margin: 0 auto; - background: $white; - box-shadow: 0px 0px 3px 0px rgba(128, 128, 128, 0.2); - - h4 { - font-size: 16px; - margin-bottom: 24px; - } - - img { - height: 65px; - padding: 6px; - margin-bottom: 28px; - } - - .icon-group { - position: relative; - margin-bottom: 24px; - - &.user:after { - content: "\f007"; - } - - &.password:after { - content: "\f023"; - } - - .show-password, - &:after { - position: absolute; - left: 4px; - bottom: 4px; - font-family: FontAwesome; - font-size: 16px; - background: transparent; - height: 34px; - width: 38px; - line-height: 34px; - text-align: center; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; - border-right: 1px solid #ccc; - } - - &.text { - .show-password { - color: $color_jungle_green_approx; - } - } - - .show-password { - right: 4px; - border: none; - left: auto; - cursor: pointer; - } - - input { - height: auto; - padding: 10px 12px 10px 52px; - background: transparent; - border-radius: 0px; - border-width: 1px; - - &#password { - padding-right: 37px - } - - &:focus { - border-image-source: #38bb9b; - border-width: 2px; - border-image-slice: 5; - border-image-source: -moz-linear-gradient(-45deg, #38bb9b 0%, #4a90e2 100%); - border-image-source: -webkit-linear-gradient(-45deg, #38bb9b 0%, #4a90e2 100%); - border-image-source: linear-gradient(135deg, #38bb9b 0%, #4a90e2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#38bb9b', endColorstr='#4a90e2', GradientType=1); - box-shadow: none; - -webkit-box-shadow: none; - } - } - } - - button.btn-login { - padding: 10px 12px; - background: #38bb9b; - background: -moz-linear-gradient(-45deg, #38bb9b 0%, #4a90e2 100%); - background: -webkit-linear-gradient(-45deg, #38bb9b 0%, #4a90e2 100%); - background: linear-gradient(135deg, #38bb9b 0%, #4a90e2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#38bb9b', endColorstr='#4a90e2', GradientType=1); - color: #fff; - margin-top: 32px; - border: none; - - &:focus, - &:hover, - &:active, - &:active:focus, - &:active:hover { - background: #38bb9b; - background: -moz-linear-gradient(-45deg, #38bb9b 0%, #4a90e2 100%); - background: -webkit-linear-gradient(-45deg, #38bb9b 0%, #4a90e2 100%); - background: linear-gradient(135deg, #38bb9b 0%, #4a90e2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#38bb9b', endColorstr='#4a90e2', GradientType=1); - color: #fff; - } - } - } -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/migration-style.scss b/dashboardv2/public/css/scss/migration-style.scss deleted file mode 100644 index 60c9758c394..00000000000 --- a/dashboardv2/public/css/scss/migration-style.scss +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -@import "__mixin.scss"; -@import "__variable.scss"; -@import "common.scss"; -@import "table.scss"; -@import "form.scss"; -@import "panel.scss"; -@import "loader.scss"; -@import "theme.scss"; -@import "stats.scss"; -@import "override.scss"; - -.initialLoading { - left: 0px !important; -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/nav.scss b/dashboardv2/public/css/scss/nav.scss deleted file mode 100644 index 4bbcfbef22c..00000000000 --- a/dashboardv2/public/css/scss/nav.scss +++ /dev/null @@ -1,74 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* nav.scss */ - -.navbar-atlas { - background-color: $color_tuna_approx; //Instead of the line below you could use @include box-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - box-shadow: inset 0 0 0 $black_10, 0 1px 10px $black_10; - - .navbar-brand { - color: $white; - } - - .nav>li>a { - color: $white; - padding-top: 18px; - padding-bottom: 18px; - font-size: 100%; - - &:focus { - background-color: transparent; - } - - &:hover { - background-color: transparent; - } - } -} - -.navbar-toggle .icon-bar { - background-color: $white; -} - -.navbar-fixed-top+.wrapper { - margin-top: 90px; - padding-bottom: 90px; -} - -.navbar-brand { - font-size: 30px; - height: auto; -} - -.navbar-form { - width: 30%; - padding: 0; - - .form-control { - width: 100%; - padding: 6px 0; - background-color: transparent; - color: $white; - border: none; //Instead of the line below you could use @include box-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - box-shadow: 0 2px $white; - } -} - -.navbar-nav>li>a { - padding: 15px 10px; -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/old-style.scss b/dashboardv2/public/css/scss/old-style.scss deleted file mode 100644 index 1c76ab21c4a..00000000000 --- a/dashboardv2/public/css/scss/old-style.scss +++ /dev/null @@ -1,180 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* old-style.scss */ - -//@extend-elements -//original selectors -//.inputs button.addAttr, .inputs button.saveAttr -%extend_1 { - height: 40px; //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 4px; - border: 1px solid $white; - color: $white; //Instead of the line below you could use @include text-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - text-shadow: 0 -1px 0 $black_25; - font-weight: bold; -} - -.row-margin-bottom { - margin-bottom: 15px; -} - -.list-group-item { - &:first-child { - //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 0; - } - - &:last-child { - //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 0; - } -} - -.h160 { - height: 160px !important; -} - -.subContent { - width: 500px; - margin: 30px; -} - -.headerDroupDown { - border-left: 1px solid $white; - font-size: 11px; - padding-left: 15px; - margin-left: 15px; -} - - - - -/* .switch { - float: left; - margin-top: 4px; - position: absolute; - z-index: 99; - top: 0; - left: 20px; - height: 26px; - width: 120px; - background: $color_alto_approx; - //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 3px; - //Instead of the line below you could use @include box-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - box-shadow: inset 0 1px 3px $color_fuscous_gray_approx, 0 1px $white; -} */ - - -/* .switch-label { - position: relative; - z-index: 2; - float: left; - width: 58px; - line-height: 26px; - font-size: 11px; - text-align: center; - cursor: pointer; - &:active { - font-weight: bold; - } -} - -.switch-label-off { - padding-left: 2px; -} - -.switch-label-on { - padding-right: 2px; -} - -.switch-input { - display: none; - &:checked + { - &.switch-label { - font-weight: bold; - color: $black_65; - //Instead of the line below you could use @include text-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - text-shadow: 0 1px $white_25; - //Instead of the line below you could use @include transition($transition-1, $transition-2, $transition-3, $transition-4, $transition-5, $transition-6, $transition-7, $transition-8, $transition-9, $transition-10) - transition: 0.15s ease-out; - } - &.switch-label-on ~ .switch-selection { - left: 60px; - } - } -} - -.switch-selection { - display: block; - position: absolute; - z-index: 1; - top: 2px; - left: 2px; - width: 58px; - height: 22px; - background: $color_fern_approx; - //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 3px; - background-image: linear-gradient(to bottom, $color_opal_approx, $color_jungle_green_approx); - background-image: linear-gradient(to bottom, $color_opal_approx, $color_jungle_green_approx); - //Instead of the line below you could use @include box-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - box-shadow: inset 0 1px $white_50, 0 0 2px $black_20; - //Instead of the line below you could use @include transition($transition-1, $transition-2, $transition-3, $transition-4, $transition-5, $transition-6, $transition-7, $transition-8, $transition-9, $transition-10) - transition: left 0.15s ease-out; -} */ - -.scrollTagList { - height: 330px; - overflow-y: auto; - margin-bottom: 0; - - i.fa { - margin-right: 5px; - } -} - -.menuItem { - padding: 10px; - color: $color_havelock_blue_approx; - cursor: pointer; -} - -.tagging { - display: inline-block; -} - -.crossClearText { - line-height: 20px !important; -} - -text { - font-weight: 300; - font-family: $font_2, $font_3, $font_4, $font_5; - font-size: 14px; -} - -.switch-blue .switch-selection { - background: $color_pelorous_approx; - background-image: linear-gradient(to bottom, $color_picton_blue_approx, $color_pelorous_approx); -} - -.switch-yellow .switch-selection { - background: $color_laser_approx; - background-image: linear-gradient(to bottom, $color_zombie_approx, $color_laser_approx); -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/override.scss b/dashboardv2/public/css/scss/override.scss deleted file mode 100644 index 94548ffa42f..00000000000 --- a/dashboardv2/public/css/scss/override.scss +++ /dev/null @@ -1,593 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* override.scss */ - -.tabs li.tab.active { - border-bottom: 2px solid $color_keppel_approx; - - a { - color: $color_keppel_approx; - } -} - -.modal-header { - padding: 15px; - border-bottom: 1px solid #DEDEDE; - - .header-button { - float: right; - opacity: .2; - color: $black; - margin-top: -2px; - - &:hover { - color: $black; - text-decoration: none; - cursor: pointer; - filter: alpha(opacity=50); - opacity: .5; - } - } -} - -.modal-title { - font-weight: 600; - -webkit-font-smoothing: antialiased; -} - -.modal-footer { - padding: 15px; - text-align: right; - border-top: 1px solid #DEDEDE; - - .btn+.btn { - margin-bottom: 0; - } -} - -.modal-body { - position: relative; - padding: 15px; - max-height: calc(100vh - 215px); - min-height: 70px; - overflow: auto; - - .btn+.btn { - margin-bottom: 2px; - } - - .admin-audit-details { - border: 1px solid #ddd; - border-radius: 4px; - - tr>td:nth-child(2) { - text-align: right; - } - } - - .tree-container { - max-height: 140px; - overflow-y: auto !important; - } -} - -.modal-full-screen { - width: 80%; - height: 80vh; - - .modal-content { - width: 100%; - } - -} - -.switch.pull-left { - margin-right: 8px; -} - -.modal-content { - border-radius: 10px; -} - - -.select2-container { - width: 100% !important; -} - -.select2-mini { - - .select2-container .select2-selection--single, - .select2-container .select2-selection--multiple { - min-height: 28px; - } - - .select2-container--default .select2-selection--single { - .select2-selection__rendered { - line-height: 28px; - font-size: 13px; - } - - .select2-selection__arrow { - height: 28px; - } - - } -} - -.select2-container--default { - &.select2-container--disabled { - .select2-selection--multiple { - background-color: $color_gallery_approx !important; - cursor: not-allowed; - - input.select2-search__field { - cursor: not-allowed; - } - } - } - - .select2-selection--multiple { - - background-color: $color_white_lilac_approx !important; - border: 1px $color_mystic_approx solid !important; - - &.errorClass { - border: 1px solid red !important; - } - } - - .select2-selection--single { - .select2-selection__arrow { - height: 34px; - } - - .select2-selection__rendered { - line-height: 32px; - font-size: 14px; - } - } - - &.select2-container--focus .select2-selection--multiple { - border-color: $color_bali_hai_approx !important; - } -} - -.select2-container { - - .select2-selection--single, - .select2-selection--multiple { - min-height: 34px; - - .select2-selection__rendered { - padding-left: 12px; - } - } -} - -.select2-container--default .select2-selection--multiple .select2-selection__choice { - background-color: $white; - color: $color_mountain_mist_approx; - border: 1px solid $tag_color; -} - -.select2-container--default .select2-search--inline .select2-search__field { - color: #555; - // width: 300px !important; -} - -.typeLOV { - .select2-container--default { - .select2-selection--multiple { - .select2-selection__rendered { - padding-right: 13px; - - .select2-selection__choice { - font-size: 14px; - color: $color_mountain_mist_approx; - border: 1px solid $color_mountain_mist_approx; - } - - .select2-search__field { - font-size: 14px; - } - } - - .select2-selection__clear { - position: absolute; - float: none; - margin: 0px; - right: 4px; - top: 5px; - color: $color_mountain_mist_approx; - } - } - } -} - -.fixed-popover { - position: fixed; -} - -.popover.fade { - -webkit-transition: ease-in .1s ease-out; - -o-transition: ease-in .1s ease-out; - transition: ease-in .1s ease-out; -} - -.pager { - margin: 0px; -} - -.popover { - z-index: 1000; -} - -.popover-content { - max-height: 150px; - overflow: auto; - - ul { - color: $dark_gray; - padding: 0px 5px; - margin-bottom: 0px; - cursor: pointer; - - a { - color: $dark_gray; - padding: 5px; - } - } -} - -.tab-content>.tab-pane.active { - overflow-x: hidden; - overflow: initial; -} - -.tab-content>.tab-pane.active.debug-metrics { - padding: 5px 20px 15px 20px; -} - -.advancedInfo { - margin-left: 5px; - cursor: pointer; -} - -.metricsUIInfo { - font-size: 20px !important; - margin-right: 5px; -} - -.query-builder { - .rule-container { - margin: 6px 0; - display: flex; - flex-wrap: wrap; - - .values-box { - display: flex; - flex-grow: 1; - width: 100%; - padding-right: 26px; - } - - .action-box { - position: absolute; - right: 4px; - top: calc(50% - 18px); - } - - .rule-header { - .rule-actions { - padding: 7px 0px; - } - } - - .error-container { - color: $color_trinidad_approx; - } - - .rule-value-container { - display: inline-block !important; - border-left: none; - width: calc(65% - 105px); - - .form-control { - width: 100% !important; - padding: 6px 12px !important; - } - } - - .rule-filter-container { - width: 35%; - - .form-control { - width: 100% !important; - } - } - - .rule-operator-container { - width: 150px; - - .form-control { - width: 100% !important; - } - } - } - - .rules-list>:first-child::before { - top: -8px; - } - - .rules-group-container { - border-color: transparent; - background: none; - - .rules-group-header { - .group-actions { - .btn-success { - color: #38BB9B !important; - background-color: transparent !important; - border-color: #38BB9B !important; - } - - .btn-danger { - color: #e14f00; - background-color: transparent; - border-color: #e14f00; - } - } - - .group-conditions { - .btn-primary { - color: #333 !important; - background-color: $white !important; - border-color: #ccc !important; - } - - .active { - color: $white !important; - background-color: #5bc0de !important; - border-color: #46b8da !important; - } - } - } - } - - - .rules-group-header .btn-group.pull-right.group-actions { - float: right !important; - } -} - -div.columnmanager-visibilitycontrol { - width: auto; - margin-bottom: 5px; - - &.open .btn-action { - background-color: $color_keppel_approx; - color: $white; - } -} - -div.columnmanager-dropdown-container { - .columnmanager-dropdown-item { - padding: 2px 13px; - } - - &.open { - overflow: auto; - width: auto; - } - - >li>span.column-label { - width: auto; - } -} - -.stack-modal[aria-role="alertdialog"] { - &.width-600 { - width: 600px !important; - left: calc(50% - 250px) !important; - margin-left: 0 !important; - } - - &.width-500 { - width: 500px !important; - left: calc(50% - 216px) !important; - margin-left: 0 !important; - } - - &.width-400 { - width: 400px !important; - left: calc(50% - 183px); - margin-left: 0 !important; - } - - .alert.ui-pnotify-container { - color: $color_ironside_gray_approx; - background-color: $white; - border: 1px solid rgba(0, 0, 0, .2); - padding: 0px; - outline: 0; - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - - .ui-pnotify-icon, - .ui-pnotify-title { - padding: 15px; - } - - .ui-pnotify-text { - position: relative; - padding: 15px; - max-height: 400px; - min-height: 70px; - overflow: auto; - border-top: 1px solid #DEDEDE; - word-break: break-word; - } - - .ui-pnotify-action-bar { - padding: 15px; - text-align: right; - border-top: 1px solid #DEDEDE; - } - } -} - -.ui-pnotify-icon, -.ui-pnotify-icon span { - padding: 2px 0px; -} - -.btn-round-xs { - border-radius: 11px; - padding-left: 10px; - padding-right: 10px; - background-color: transparent !important; - color: #626467; - border: 1px solid black; -} - -.text-center { - text-align: center !important; -} - -.margin-15 { - margin: 15px 0px; -} - -.padding-left-0 { - padding-left: 0px !important; -} - -.fa-color { - color: $color_keppel_approx -} - -.w30 { - width: 30% !important; -} - -.query-builder .error-container { - cursor: pointer; -} - -.renderable { - .glyphicon { - color: $color_jungle_green_approx; - font-size: large; - font-weight: bold; - } - - .noToggle { - color: $gray; - } -} - -.backgrid-internal-table { - - th, - td { - display: table-cell; - } -} - -.table-hover>tbody>tr:hover { - background-color: #fafafa; -} - -.input-group { - .form-control { - z-index: 1; - } -} - -.ui-pnotify-container { - .ui-pnotify-text { - word-break: break-word; - } -} - -.jstree-wholerow-ul { - width: 100%; - - .jstree-anchor { - width: calc(100% - 50px); - overflow: hidden; - text-overflow: ellipsis; - } -} - -.modal { - position: absolute; -} - -.modal-open { - overflow-y: auto; -} - -.daterangepicker { - max-height: 400px; - overflow-y: scroll; - - .ranges { - max-height: 328px; - overflow: auto; - } - - .ranges li.active, - td.active { - background-color: $color_havelock_blue_approx; - } - - .drp-buttons { - .applyBtn { - background-color: $color_havelock_blue_approx; - border-color: $color_havelock_blue_approx; - } - } -} - -.dropzone .dz-preview .dz-details .dz-filename { - padding-top: 20px; -} - -.select2-container--default .select2-search--inline .select2-search__field { - width: 100% !important; -} - -.tooltip-inner>div { - max-width: 250px; - text-align: left; - - ul { - list-style: disc; - } -} - -.ideal-timeout { - .modal-content { - border-radius: 0px !important; - } -} - -.user-circle { - display: inline; -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/panel.scss b/dashboardv2/public/css/scss/panel.scss deleted file mode 100644 index 9a94221c3a9..00000000000 --- a/dashboardv2/public/css/scss/panel.scss +++ /dev/null @@ -1,159 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* panel.scss */ - -.panel-default { - >.panel-heading { - color: $color_jungle_green_approx; - background: $white; - border-color: $color_jungle_green_approx; - - button { - color: $color_jungle_green_approx; - background: $white; - border: none; - } - - .panel-title { - font-weight: bold; - padding-top: 6px; - } - } - - .nav-tabs { - >li { - &.active { - >a { - color: $color_jungle_green_approx; - } - } - - >a { - color: $black; - } - } - } -} - -.panel-fullscreen { - .panel-body { - //overflow: hidden; - height: calc(100% - 46px) !important; - } - - .ui-resizable-handle { - display: none !important; - } -} - -.nav-tabs { - >li { - &:first-child { - margin-left: 25px; - } - } -} - -.with-nav-tabs { - .tab-content { - >.tab-pane { - &>div { - position: relative; - } - - &.active { - padding: 20px 10px 0px 10px; - min-height: 50px; - } - } - } -} - -.panel-fullscreen { - position: fixed; - height: 100%; - top: 0px; - bottom: 0; - left: 0; - width: 100%; - right: 0; - z-index: 999; -} - -.panel.expand_collapse_panel-icon { - .panel-heading { - .panel-title { - display: inline-block; - } - - i.ec-icon:before { - content: "\f054" - } - - &.collapsed, - &[aria-expanded="false"] { - i.ec-icon:before { - content: "\f054" - } - } - - &[aria-expanded="true"] { - i.ec-icon:before { - content: "\f078" - } - } - } -} - -.panel-default.custom-panel>.panel-heading { - color: $color_jungle_green_approx; - cursor: pointer; - border-bottom: none; - display: inline-block; - - .panel-title { - font-weight: normal; - - a:hover { - color: $color_jungle_green_approx; - opacity: 0.7; - } - } - - .btn-group { - margin-top: 4px; - } -} - -.panel-default.custom-panel>.panel-actions { - float: right; - margin-top: 15px; - margin-right: 10px; - - button { - margin-top: -4px; - } -} - -.panel-default.custom-panel>.panel-collapse>.panel-body { - border-top: none; -} - -.panel-default.custom-panel>.panel-heading>.btn-group>button { - color: $color_jungle_green_approx; -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/profile-table.scss b/dashboardv2/public/css/scss/profile-table.scss deleted file mode 100644 index 598af2ed360..00000000000 --- a/dashboardv2/public/css/scss/profile-table.scss +++ /dev/null @@ -1,72 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* Profile Tab css */ - -.graphkey { - font-size: 12px; - color: $action_gray; -} - -.graphval { - font-size: 15px; - - .value-loader { - top: 10px; - } -} - -.nv-axislabel { - fill: $action_gray; -} - -.profileGraphDetail hr { - margin: 3px; -} - -svg.dateType .nv-bar { - cursor: pointer; -} - -.jqstooltip { - height: auto !important; - width: auto !important; -} - -.progress.cstm_progress { - margin-bottom: 0px; - - .progress-bar-success.cstm_success-bar { - background-color: $color_jungle_green_approx; - } - - .progress-bar-success.cstm_success-bar:hover { - background-color: $color_puerto_rico_approx; - } -} - -th.renderable.nonNullData { - a { - text-align: center; - } -} - -.profileGraphDetail>div div { - text-align: right; - white-space: nowrap; - @include ellipsis(); -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/relationship.scss b/dashboardv2/public/css/scss/relationship.scss deleted file mode 100644 index 7bf2560725c..00000000000 --- a/dashboardv2/public/css/scss/relationship.scss +++ /dev/null @@ -1,35 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -.relationship-box, -.lineage-box { - position: absolute; - height: 100%; - width: 100%; - overflow: hidden; - z-index: 1; - - .relatioship-link { - fill: none; - stroke-width: 1.5px; - } -} - -.relationship-node-details { - &.box-panel { - top: 0; - } -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/search.scss b/dashboardv2/public/css/scss/search.scss deleted file mode 100644 index f10d962fe15..00000000000 --- a/dashboardv2/public/css/scss/search.scss +++ /dev/null @@ -1,338 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -//colors -$color_celeste_approx: #1D1F2B; - -.switch { - position: relative; - width: 50px; - height: 22px; - margin-left: 8px; - padding: 3px; - vertical-align: top; - background-color: $color_celeste_approx; - border-radius: 18px; - cursor: pointer; -} - -.switch-input { - position: absolute; - top: 0; - left: 0; - opacity: 0; -} - -.switch-slider { - position: absolute; - top: 1px; - left: 3px; - width: 16px; - height: 16px; - border-radius: 10px; - box-shadow: 1px 1px 5px rgba(black, .2); - @include transition(left #{$switchTransition}); - - &:before { - content: ''; - position: absolute; - top: 50%; - left: 50%; - margin: -6px 0 0 -8px; - width: 16px; - height: 16px; - background-color: $color_jungle_green_approx; - border-radius: 10px; - box-shadow: inset 0 1px rgba(black, .02); - @include transition(inherit); - } - - .switch-input:checked~& { - left: 30px; - box-shadow: -1px 1px 5px rgba(black, .2); - } -} - -.labelShowRecord { - line-height: 40px; -} - -.srchType { - margin: 5px 0px; - - .srchTitle { - font-size: 14px; - color: $gray - } -} - -.filterQuery { - word-break: break-all; - - span { - font-size: 15px; - font-weight: bold; - } - - .key { - color: $color_jungle_green_approx; - } - - .operator { - color: $action_gray; - } - - .value { - color: $tag_color; - } -} - -.popup-tag-term { - display: none; -} - -.popover-tag-term { - .btn { - display: block; - } -} - -.gu-mirror { - .table-quickMenu { - border: none; - - td { - height: 54px; - } - } -} - -.table-responsive { - position: relative; -} - -.sindu_dragger { - @extend .gu-mirror; - - &.sindu_column { - li { - float: none !important; - display: table-cell !important; - } - } - - .gu-transit { - //box-shadow: 0px 1px 15px inset; - } - - table { - background: rgb(242, 242, 242) !important; - } -} - -.filter-box { - .inline-content-fr { - .inline { - margin: 0px; - } - } -} - -.typeFilter { - .dropdown { - span.type-clear-btn { - position: absolute; - color: #444444; - font-size: 8px; - right: 23px; - top: 12px; - cursor: pointer; - } - } - - button.dropdown-toggle { - width: 99.5%; - text-align: left; - background-color: white; - color: $color_star_dust_approx; - border: $color_star_dust_approx; - - &:hover { - color: $color_star_dust_approx !important; - border: $color_star_dust_approx !important; - } - } -} - -ul.type-filter-ul { - color: black; - padding: 10px; - max-height: 415px; - overflow: auto; - width: 100%; - padding-top: 0px; - margin-bottom: 0px; - - li { - padding: 2px; - } - - .typeLi li { - padding: 3px; - background-color: #f7fbff; - margin: 3px; - border: 1px solid #dbd6d6; - border-radius: 4px; - - &:hover { - color: $white; - background-color: $color_star_dust_approx; - cursor: pointer; - } - - &.active { - background-color: #37bb9b; - color: white; - } - } - - .filterLi li { - padding: 2px; - margin: 4px; - } -} - -.dark-text { - color: black; -} - -hr.hr-filter { - margin-top: 7px; - margin-bottom: 7px; - border: 0; - border-top: 1px solid #bdc3c7; -} - - - -.searchTable { - &.noData { - - .labelShowRecord, - .inline[data-id="colManager"], - .row.searach-result-pagination, - table thead { - display: none !important; - } - } -} - -.query-builder { - .rule-container { - &.user-define { - .values-box { - display: flex; - flex-wrap: wrap; - - .rule-filter-container { - width: 200px; - } - - .rule-value-container { - width: 100%; - padding: 7px 0px 0px 0px; - } - } - } - - .rule-value-container { - &>table.custom-table { - tr { - display: none; - - &.custom-tr { - display: table-row; - - td.custom-col-1 { - width: 48%; - - .errorMsg { - display: none; - } - } - } - } - - input, - textarea { - width: 100% !important; - } - } - } - } -} - -.attributeResultContainer { - &.overlay { - z-index: 3; - } - - .attribute-filter-container { - position: absolute; - z-index: 3; - left: 21px; - width: 75%; - right: 0; - // display: none; - background: $white; - box-shadow: 0px 13px 34px -13px grey; - padding: 15px; - transition: all ease 0.3s; - - &.no-attr { - .filter-box { - display: inline-block; - padding: 0px 15px; - } - } - - .filter-box { - padding: 5px; - } - - .entity-detail-table-toggle { - display: inline-block; - } - - .pretty.p-switch.p-fill input:checked~.state.p-primary:before { - background-color: #38bb9b !important; - } - - .pretty.p-switch input:checked~.state.p-primary:before { - border-color: #38bb9b; - } - - .panel { - border: none; - } - - .attribute-result-footer, - .attribute-edit-footer { - text-align: right; - } - } - -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/stats.scss b/dashboardv2/public/css/scss/stats.scss deleted file mode 100644 index 7bf75815f8a..00000000000 --- a/dashboardv2/public/css/scss/stats.scss +++ /dev/null @@ -1,173 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -.server-stats-container { - - .connection-status { - height: 10px; - width: 10px; - border-radius: 50%; - display: inline-block; - - &.connected { - background-color: #4CAF50; - } - - &.not-connected { - background-color: #f44336; - } - } - - .notification-card { - padding-top: 5px; - } - - .card-container { - &.panel { - &.panel-primary { - border: 1px solid #ddd; - padding: 5px; - } - } - - &.panel-primary>.panel-heading { - color: #686868; - background-color: $white; - font-size: 14px; - font-weight: bold; - } - } - - - .panel-group { - .panel { - padding: 5px; - } - } - - .panel { - &.panel-default { - padding: 5px; - margin: 5px; - } - - .panel-body { - - .col-sm-6, - .col-sm-12 { - padding: 5px; - - .panel-heading { - padding: 5px 0 0 15px; - } - } - - } - - } - - .table { - &.stat-table { - width: 100%; - - td { - display: table-cell; - } - - &.notification-table { - &.table-striped>tbody>tr:nth-of-type(odd) { - background-color: $color_white_lilac_approx; - } - - tr { - - th:not(:first-child), - td:not(:first-child) { - text-align: right; - } - } - } - - - } - } - - .entityTable { - &.table { - tr { - - th:not(:first-child), - td:not(:first-child) { - width: 33%; - text-align: right; - } - } - - } - } -} - -.statistics-header { - height: 50px; - width: 100%; - display: flex; - justify-content: center; - align-items: center; - position: fixed; - z-index: 999; - top: 0px; - padding: 0px 15px; - background: #fff; - border-bottom: 1px #e8e9ee solid; - box-shadow: 0 2px 6px 0 rgba(0, 0, 0, .05); - - &>div { - margin: 0px 5px; - } - - pre { - width: 100%; - padding: 5px 10px; - margin: 0px 10px; - color: $gray; - - .color { - color: $color_jungle_green_approx; - font-weight: bold; - } - } - - .progress { - width: 100%; - margin-top: 7px; - margin-bottom: 0px; - - .progress-bar-success { - background-color: $color_jungle_green_approx; - } - } - - .refresh-container { - background: white; - border-radius: 23px; - - .btn { - margin: 0px; - border-radius: 23px; - padding: 10px 10px; - } - } -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/style.scss b/dashboardv2/public/css/scss/style.scss deleted file mode 100644 index 9f4482c27d5..00000000000 --- a/dashboardv2/public/css/scss/style.scss +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -@import "__mixin.scss"; -@import "__variable.scss"; -@import "common.scss"; -@import "table.scss"; -@import "tab.scss"; -@import "form.scss"; -@import "nav.scss"; -@import "panel.scss"; -@import "loader.scss"; -@import "graph.scss"; -@import "relationship.scss"; -@import "old-style.scss"; -@import "theme.scss"; -@import "tag.scss"; -@import "search.scss"; -@import "profile-table.scss"; -@import "glossary.scss"; -@import "wizard.scss"; -@import "business-metadata.scss"; -@import "stats.scss"; -@import "override.scss"; \ No newline at end of file diff --git a/dashboardv2/public/css/scss/tab.scss b/dashboardv2/public/css/scss/tab.scss deleted file mode 100644 index c164b47440d..00000000000 --- a/dashboardv2/public/css/scss/tab.scss +++ /dev/null @@ -1,208 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* tab.scss */ - -.atlast-tabbable { - margin: 25px 0; - - .nav-tabs { - border-bottom: 1px solid $color_mystic_approx; - - >li { - >a { - padding: 15px 30px; - text-transform: uppercase; - letter-spacing: 1px; //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 2px 2px 0 0; - } - - &.active>a { - border: 1px solid $color_mystic_approx; - border-bottom-color: transparent; - - &:focus { - border: 1px solid $color_mystic_approx; - border-bottom-color: transparent; - } - - &:hover { - border: 1px solid $color_mystic_approx; - border-bottom-color: transparent; - } - } - } - } - - .tab-content { - background-color: $white; - padding: 35px; - border: 1px solid $color_mystic_approx; - border-top: none; - } -} - -ul.tabs li.tab { - padding: 0; -} - -.tab-content>.tab-pane { - display: block; - opacity: 0; - height: 0; - padding: 0px; - overflow: hidden; - - &.active { - padding: 15px 20px; - opacity: 1; - height: auto; - overflow: auto; - } -} - -.tagsList .atlast-tabbable { - margin: 0; - - .tab-content { - padding: 10px 22px; - } - - .nav-tabs>li>a { - padding: 10px 20px; - } -} - -// NEW theme style -.tabs { - position: relative; - height: 42px; - width: 100%; - white-space: nowrap; - padding: 0; - transition: color 0.28s ease; - - .indicator { - position: absolute; - bottom: 0; - height: 2px; - background-color: $color_keppel_approx; - will-change: left, right; - } - - li.tab { - display: block; - float: left; - text-align: center; - line-height: 42px; - height: 42px; - padding: 0 20px; - margin: 0; - text-transform: uppercase; - letter-spacing: 0.8px; - border-bottom: 1px solid $color_mirage_approx; - - a { - font-size: 14px; - font-weight: 600; - color: $white; - display: block; - text-decoration: none; - width: 100%; - height: 100%; //Instead of the line below you could use @include transition($transition-1, $transition-2, $transition-3, $transition-4, $transition-5, $transition-6, $transition-7, $transition-8, $transition-9, $transition-10) - transition: color 0.28s ease; - /* color: $color_manatee_approx; */ - /* &:hover { - color: $color_keppel_approx; - } - &.active { - color: $color_keppel_approx; - } */ - } - } -} - -.atlast-tabbable { - margin: 25px 0; - - .nav-tabs { - border-bottom: 1px solid $color_mystic_approx; - - >li { - >a { - padding: 15px 30px; - text-transform: uppercase; - letter-spacing: 1px; //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 2px 2px 0 0; - } - - &.active>a { - border: 1px solid $color_mystic_approx; - border-bottom-color: transparent; - - &:focus { - border: 1px solid $color_mystic_approx; - border-bottom-color: transparent; - } - - &:hover { - border: 1px solid $color_mystic_approx; - border-bottom-color: transparent; - } - } - } - } - - .tab-content { - background-color: $white; - padding: 35px; - border: 1px solid $color_mystic_approx; - border-top: none; - } -} - -.default-tab { - .nav-tabs { - >li { - &.active { - >a { - color: $color_jungle_green_approx; - // background: $color_white_lilac_approx; - } - } - - >a { - color: $black; - } - } - } -} - -.pending-task { - - .pending-refresh-btn { - margin-bottom: 15px; - } - - table tr th { - padding: 6px 8px !important; - } - - .panel-heading { - font-size: 16px; - } -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/table.scss b/dashboardv2/public/css/scss/table.scss deleted file mode 100644 index 121769b18c5..00000000000 --- a/dashboardv2/public/css/scss/table.scss +++ /dev/null @@ -1,335 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -.table.bold-key>tbody>tr>td:first-child { - font-weight: 600; -} - -tr.empty { - td { - display: table-cell; - text-align: center; - } -} - - -.stat-table { - - tbody, - thead { - >tr { - - td:nth-child(2), - th:nth-child(2) { - text-align: right; - } - } - } -} - -.entity-detail-table, -.type-node-details, -.relationship-detail-table { - position: relative; - - .hide-empty-value { - .hide-row { - display: none; - } - } - - .entity-relationship-table-toggle, - .entity-detail-table-toggle { - position: absolute; - right: 0; - top: 7px; - } - - table { - - th:nth-child(1), - td:nth-child(1) { - width: 20%; - } - } -} - -.type-node-details { - .header { - .pretty.p-switch .state:before { - border: 1px solid white; - } - - .pretty.p-switch .state label:after { - background-color: white !important; - } - - .pretty.p-switch.p-fill input:checked~.state label:after { - background-color: #4a90e2 !important; - } - - .pretty.p-switch.p-fill input:checked~.state.p-primary:before { - background-color: white !important; - } - } -} - -.backgrid { - td { - white-space: normal; - } - - .select-all-header-cell, - .select-row-cell { - width: 42px; - text-overflow: clip; - } - - thead { - th { - button { - padding-right: 11px; - } - } - } - - .sortable:not(.descending):not(.ascending) { - .sort-caret { - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - font-size: 11px; - - &:before { - content: "\f0dc"; - } - } - } - - .debuggging-table-header { - padding-right: 0px !important; - - button { - float: right; - } - } -} - -.backgrid-paginator ul { - display: inline-block; - padding-left: 0; - margin: 20px 0; - border: 1px $color_keppel_approx solid; - margin: 0px; - float: right; - border-radius: 4px; - overflow: hidden; - - >.active>span, - >.active>a, - >.active>a:hover { - background: none; - color: $color_keppel_approx; - background: none; - color: #37bb9b; - font-weight: 600; - font-family: sans-serif; - } - - >li>a, - >li>span, - >li>button { - width: 30px; - height: 30px; - padding: 0; - line-height: 30px; - text-decoration: none; - border: none; - float: left; - background: $transparent; - color: $color_keppel_approx; - @include ellipsis(); - - i { - font-weight: bold; - } - - &:hover { - color: $white; - background: $color_keppel_approx - } - } - - >.disabled>span, - >.disabled>a, - >li>button[disabled] { - color: $color_mountain_mist_approx; - - &:hover { - cursor: not-allowed; - color: $white; - background: $color_jungle_green_light !important; - } - } -} - -.toggleList.semi-collapsed div:nth-child(n+2) { - display: none; - -} - -.table-quickMenu { - border: thin $lightGrey solid; - border-collapse: separate; - border-radius: 6px; - box-shadow: 0px 0px 4px #d8d8d8; - overflow: scroll !important; - max-height: 500px; - width: 100%; - - .resizeHandler { - &.grid-draggable { - background-color: $color_jungle_green_approx !important; - } - - &:hover { - border-left: 1px solid #d2d2d2; - } - } - - >thead>tr { - background: #eeeeee; - - &>th { - border-width: thin; - // border-color: $color_jungle_green_approx; - border-bottom-style: solid; - box-shadow: none; - padding: 6px 15px !important; - background-color: transparent; - text-align: left; - font-weight: 800; - border-top: 0; - font-size: 14px; - letter-spacing: 0.25px; - color: #6a6a6a; - - &.no-capitalize { - text-transform: none !important; - } - } - - >td { - border-color: $color_gallery_approx; - color: #333333; - font-weight: 100; - padding: 9px 15px; - } - } - - >tbody>tr>td { - &.select-row-cell { - text-align: center; - } - } - - .expandable { - .expandable-content { - max-width: none; - background: #f8f8f8; - - div { - - table { - width: 100%; - - td { - - display: table-cell; - } - - tr:last-child>td { - border-bottom: none; - } - } - } - } - } -} - -td { - - div.scroll-y, - pre.scroll-y { - max-height: 200px; - overflow-y: auto; - word-break: break-all; - } - - &.searchTableName { - min-width: 150px; - - &:hover { - img { - transform: scale(1.5); - transform-origin: 100% 50%; - transition: transform 0.2s; - outline-color: #f5f5f5; - } - } - - a { - max-width: calc(100% - 36px); - overflow: hidden; - float: left; - text-overflow: ellipsis; - } - - img { - height: 20px; - margin: 0px 5px; - float: left; - } - } -} - -.auditStatusContainer { - display: flex; - flex-wrap: wrap; - justify-content: center; - - &>div { - flex-grow: 1; - } -} - -.debug-metrics-table table { - - tr th:not(:first-child), - tr td:not(:first-child) { - text-align: center !important; - - button { - margin: 0 auto; - } - } -} - -.debug-btn-wrapper { - margin-bottom: 5px; - z-index: 2; -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/tag.scss b/dashboardv2/public/css/scss/tag.scss deleted file mode 100644 index e07c3b9deba..00000000000 --- a/dashboardv2/public/css/scss/tag.scss +++ /dev/null @@ -1,210 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -//tag.scss -.tag-tree { - padding: 0; // overflow: auto; - - &.saveSearchList { - height: 150px; - overflow-y: auto; - } - - .child>li, - >li { - list-style: none; - cursor: pointer; - - &.parent-node { - position: relative; - - &.active { - &>div { - background-color: $color_jungle_green_approx; - border: none; - - .tools { - display: block; - } - - &:hover { - background-color: $color_jungle_green_approx; - } - } - - ul.child { - &:after { - height: 4px; - top: -5px; - } - } - } - - &>div { - position: relative; - margin-top: 5px; - /* margin-bottom: 5px; */ - border-radius: 4px; - - &:hover { - background-color: $color_star_dust_approx; - } - - >.fa.toggleArrow { - position: absolute; - left: 0; - padding: 8px; - cursor: pointer; - } - - // >ul>li { - // line-height: 30px; - // margin-left: -20px; - // text-indent: 20px; - // &:hover { - // background-color: $color_keppel_approx; - // } - // &.selected { - // background-color: $color_keppel_approx; - // } - // } - .tools { - display: none; - position: absolute; - right: 0; - color: $white; - padding: 5px 10px; - } - - >a, - >div>a { - display: block; - color: $white !important; - white-space: nowrap; - padding: 5px 10px; - max-width: 91%; - @include ellipsis(); - font-size: 14px; - - &:hover { - color: $white !important; - text-decoration: none !important; - } - } - - >i+a { - padding: 5px 25px; - } - } - - >ul.child { - margin-left: 11px; - padding-left: 10px; - border-left: 1px dotted gray; - position: relative; - - &:after { - position: absolute; - content: ""; - height: 13px; - width: 11px; - top: -14px; - left: -1px; - border-left: 1px dotted gray; - } - - li { - &.parent-node { - &:after { - position: absolute; - content: ""; - height: 2px; - width: 14px; - top: 16px; - left: -9px; - border-top: 1px dotted gray; - } - - &.active:after { - width: 9px; - } - } - } - } - } - } -} - -.input-group.attributes .form-control { - height: 40px; - box-shadow: none; - border-right: none; -} - -.input-group.attributes .input-group-addon { - background-color: $color_white_lilac_approx; - border: 1px $color_mystic_approx solid; - border-radius: 0px; - border-left: none; -} - -.input-group.attributes .input-group-addon i.fa { - cursor: pointer; -} - -.input-group.attributes .form-control:focus+.input-group-addon { - border-color: $color_bali_hai_approx; -} - -.entityLink { - font-size: 16px; -} - -.mainAttrTable { - max-height: 180px; - overflow: auto; - - table.attriTable { - width: 100%; - - td { - // &[data-type="int"], - // &[data-type="long"], - // &[data-type="float"], - // &[data-type="byte"], - // &[data-type="double"], - // &[data-type="short"] { - // text-align: right; - // } - } - - th, - td { - border: 1px solid #ddd; - padding: 5px 7px; - width: 50%; - - &.renderable.html-cell { - min-width: 150px; - } - } - } -} - -.addtag-propagte-box { - border: 1px solid #ddd; - border-radius: 7px; -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/theme.scss b/dashboardv2/public/css/scss/theme.scss deleted file mode 100644 index 4838ca3afb9..00000000000 --- a/dashboardv2/public/css/scss/theme.scss +++ /dev/null @@ -1,663 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -/* theme.scss */ - -body { - font-family: $font_0, $font_1; - color: $color_ironside_gray_approx; - overflow-x: hidden; -} - -header.atlas-header { - background-color: $white; - border-bottom: 1px $color_mystic_approx solid; - - table { - width: 100%; - } - - .navbar-nav { - display: table; - - li { - float: none; - display: table-cell; - padding: 0px 5px; - } - } - - &>table { - td { - padding: 3px 2px; - position: relative; - transition: width 0.3s !important; - } - } - - .header-menu { - .dropdown-menu>li>a { - color: $color_ironside_gray_approx; - - &:hover { - color: $color_jungle_green_approx; - } - - i { - padding-right: 3px; - } - } - - td>a { - display: inline-block; - color: $color_ironside_gray_approx; - padding: 15px 14px; - - &:hover { - border-bottom: 2px solid $color_jungle_green_approx; - padding: 14px 14px; - color: $color_jungle_green_approx; - } - - span { - padding: 5px; - } - - i { - font-size: 18px; - } - } - } -} - -#new-page-wrapper { - height: calc(100vh - 63px); - overflow: auto; - padding-top: 15px !important; - padding-bottom: 10px !important; - - &>div { - height: 100%; - } -} - -.full-parent-width { - height: 100%; -} - -.sidebar-brand { - padding-left: 6px !important; - - .logo { - height: 42px; - padding: 6px; - } -} - -.main-search { - .form-control { - border: none; - border-left: 1px $color_mystic_approx solid; //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 0; //Instead of the line below you could use @include box-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - box-shadow: none; - height: 60px; - font-size: 18px; - font-style: italic; - } - - .input-group-addon { - font-size: 20px; - color: $color_bombay_approx; - background: none; - border: none; - } -} - -.close { - font-size: 2em; -} - -#sidebar-wrapper { - background: $color_tuna_approx; - - #sideNav-wrapper { - color: $white; - font-size: 16px !important; - - .well { - background: transparent; - border: 1px solid #666363; - overflow: hidden; - @include clearfix(); - } - - .tab-content>.tab-pane.active { - padding: 18px; - } - } -} - -.page-title { - padding: 0px 15px 0px 15px; - - .title { - padding-top: 0; - margin-top: 0; - } - - h1 { - &.title { - word-break: break-all; - } - - // margin-top: 50px; - margin-bottom: 10px; - font-weight: 600; - @include ellipsis(); - max-width: 91%; - display: inline-block; - - small { - position: relative; - bottom: 5px; - margin-left: 15px; - padding-left: 15px; - border-left: 1px $color_mystic_approx solid; - color: $color_bombay_approx; - font-size: 40%; - font-weight: 600; - text-transform: uppercase; - } - } - - .sub-title { - margin-bottom: 40px; - } -} - -.sm-title { - line-height: 30px; -} - -.md-title { - line-height: 34px; -} - -.lg-title { - line-height: 40px; -} - -a { - color: $color_jungle_green_approx; - cursor: pointer; - - &:focus { - color: $color_puerto_rico_approx; - text-decoration: none; - outline: none; - cursor: pointer; - } - - &:hover { - color: $color_puerto_rico_approx; - text-decoration: none; - cursor: pointer; - } -} - -.cursor-default, -.cursor-default a { - cursor: default; -} - -.blue-link { - color: $color_havelock_blue_approx; - - &:focus { - color: $color_havelock_blue_approx; - text-decoration: none; - outline: none; - } - - &:hover { - color: $color_havelock_blue_approx; - text-decoration: underline; - } -} - -a[href^="#!/"]:not(.btn, .not-blue-link) { - @extend .blue-link; -} - -th { - text-transform: capitalize; -} - -ul { - list-style: none; -} - -hr[size="10"] { - margin: 10px 0px; -} - -.table { - margin-bottom: 2px; - background-color: $white; - max-width: none; - - .table { - width: auto; - } -} - -.card { - background: $white none repeat scroll 0 0; //Instead of the line below you could use @include box-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - box-shadow: 0 1px 3px $black_30; - margin-bottom: 30px; -} - -// Colors Class -.white-bg { - background-color: $white; - padding: 30px 0; -} - -.gray-text { - color: $color_star_dust_approx; -} - -.gray-bg { - background-color: $color_white_lilac_approx; -} - -.comment-input { - background-color: $color_white_lilac_approx; - padding: 20px; - font-size: 16px; - margin-bottom: 20px; -} - -.comment-box { - padding: 25px 0; - margin-top: 25px; - border-top: 1px $color_mystic_approx solid; - - .comment { - margin-bottom: 25px; - } - - .author { - color: $color_keppel_approx; - margin-bottom: 0; - } - - .date { - color: $color_star_dust_approx; - } -} - -.col-sm-custom { - margin: 15px 25px 0px; - position: relative; -} - -.no-padding { - padding: 0px !important; -} - -.no-padding-bottom { - padding-bottom: 0px !important; -} - -.no-padding-top { - padding-top: 0px !important; -} - -.no-padding-left { - padding-left: 0px !important; -} - -.no-padding-right { - padding-right: 0px !important; -} - -.no-margin { - margin: 0px !important; -} - -.no-margin-bottom { - margin-bottom: 0px !important; -} - -.no-margin-top { - margin-top: 0px !important; -} - -.no-margin-left { - margin-left: 0px !important; -} - -.no-margin-right { - margin-right: 0px !important; -} - -.no-border { - border: none !important; -} - -.no-pointer { - pointer-events: none; -} - -.position-relative { - position: relative; -} - -.pagination-box { - margin-top: 15px; -} - -.ellipsis-with-margin { - @include ellipsis(); - margin-bottom: 10px; -} - -.ellipsis { - @include ellipsis(); -} - -.readOnlyLink { - @include ellipsis(); - - .deleteBtn { - padding: 0px 5px; - } - - a { - color: $delete_link !important; - } -} - -.add-seperator { - margin-bottom: 10px; - border-bottom: 1px solid $color_mirage_approx; - padding-bottom: 10px; -} - -.legend-sm { - font-size: 17px; -} - -.errorClass { - border: 1px solid red !important; - box-shadow: none !important; -} - -.inline-content { - >.inline { - display: inline-block; - - &+.inline { - margin-left: 5px; - } - } -} - -.inline-content-fl { - @extend .inline-content; - - >.inline { - display: block; - float: left; - } -} - -.inline-content-fr { - @extend .inline-content-fl; - - >.inline { - float: right; - - &+.inline { - margin-right: 5px; - } - } -} - -.has-error { - - .select2-selection--single, - .select2-selection--multiple { - border-color: $color_apple_blossom_approx; - } -} - -.search-entity-icon-box { - padding: 10px; - border-radius: 50%; - width: 25px; - height: 25px; - - img { - width: 25px; - height: 25px; - cursor: default; - } -} - -.entity-icon-box { - display: inline-block; - background: #cee0fa; - padding: 10px; - border-radius: 50%; - min-width: 76.25px; - min-height: 70px; - - &.disabled { - background: #e3e3e3; - } - - img { - height: 50px; - } -} - -.ui-menu.ui-widget-content.ui-autocomplete { - box-shadow: 0px 11px 30px -8px grey; - max-width: 60% !important; - max-height: 70vh; - overflow-y: auto; - /* prevent horizontal scrollbar */ - overflow-x: hidden; - - .ui-autocomplete-category { - padding: 5px 15px; - color: #acacac; - text-transform: capitalize; - } - - li.empty { - padding: 5px 2px; - line-height: 45px; - - span.empty-message { - padding: 10px; - } - } - - .ui-menu-item { - padding: 2px 2px; - color: $color_ironside_gray_approx; - - &.with-icon { - img { - height: 25px; - width: 30px; - margin-right: 10px; - background: none; - } - } - - span.searched-term { - display: inline-block; - padding: 0; - font-weight: bold; - color: $black !important; - } - - .ui-state-active { - margin: 0px; - border: none; - background: #cee0fa; - color: $black !important; - } - - a, - span { - padding: 6px 10px; - display: block; - color: inherit !important; - } - } -} - -.tooltip-inner { - max-width: none; - color: #2c2c2c; - background-color: #f9f9f9; - box-shadow: 0px 0px 3px 0px #8080806b; -} - -.tooltip.bottom .tooltip-arrow { - border-bottom-color: #000; -} - -.dropdown-menu.multi-level { - .dropdown-submenu { - position: relative; - - &>a:after { - display: none; - content: " "; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - border-width: 5px 5px 5px 0px; - border-right-color: #ccc; - position: absolute; - left: 8px; - top: calc(50% - 5px); - } - - &>a:hover:after { - display: block; - } - - &>.dropdown-menu { - top: 0; - left: -100%; - width: 100%; - margin-top: -6px; - margin-left: -1px; - -webkit-border-radius: 0 6px 6px 6px; - -moz-border-radius: 0 6px 6px; - border-radius: 0 6px 6px 6px; - - .submenu { - left: -125%; - top: -5px; - } - } - - &:hover>.dropdown-menu { - display: table; - } - - } -} - -.select2-results__option { - &.select2-results__option--highlighted { - .option-title-light { - color: #eaeaea; - } - } - - .option-title-light { - font-size: 12px; - color: #a4a4a4; - } - - -} - -.dropzone { - border-radius: 10px; - border: 2px dashed $color_havelock_blue_approx; - - .dz-default.dz-message { - font-weight: 500; - font-size: 20px; - } - - &.single-file-center { - .dz-file-preview { - margin-left: calc(50% - 68px); - } - } -} - -.dropzone-modal { - .modal-body { - background: $color_white_lilac_approx; - } -} - -.help-btn { - cursor: pointer; - font-size: 20px; -} - -.back-button { - display: inline-block; - float: left; - position: absolute; - left: 4px; - top: 9px; - font-size: 38px; - color: #bfbfbf; - cursor: pointer; - - &:hover { - color: $gray; - } -} - -.modal-header { - .back-button { - margin-left: 10px; - top: 9px; - font-size: 38px; - } - - .modal-name { - font-size: 22px; - margin-top: 5px; - margin-left: 20px; - } -} \ No newline at end of file diff --git a/dashboardv2/public/css/scss/wizard.scss b/dashboardv2/public/css/scss/wizard.scss deleted file mode 100644 index 85efe73555c..00000000000 --- a/dashboardv2/public/css/scss/wizard.scss +++ /dev/null @@ -1,392 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -$color_scarlet_approx: #ff3111; -$color_pippin_approx: #fbe3e4; -$color_your_pink_approx: #fbc2c4; -$color_falu_red_approx: #8a1f11; - -%wizard_tabcontrol { - display: block; - width: 100%; -} - -%extend_2 { - list-style: none !important; - padding: 0; - margin: 0; -} - -%extend_3 { - display: block; - width: auto; - margin: 0 .5em .5em; - padding: 1em; - text-decoration: none; - position: relative; - border-radius: 5px; -} - -%extend_4 { - background: #f5f5f5; - color: #bbb; - cursor: default; -} - -%extend_5 { - background: $color_keppel_approx; - color: $white; - cursor: default; -} - -%extend_befor_after { - content: " "; - display: block; - width: 0; - height: 0; - border-top: 50px solid transparent; - border-bottom: 50px solid transparent; - position: absolute; - top: 50%; - margin-top: -50px; - left: 100%; -} - -.wizard { - @extend %wizard_tabcontrol; - - a { - outline: 0; - } - - ul { - @extend %extend_2; - - >li { - display: block; - padding: 0; - } - } - - > { - .steps { - position: relative; - display: block; - width: 100%; - - .current-info { - position: absolute; - left: -999em; - } - - .number { - font-size: 1.429em; - } - - &>ul { - position: relative; - border: 0; - padding: 0px; - background: #f5f5f5; - border-radius: 0; - list-style: none; - overflow: hidden; - margin-bottom: 10px; - - >li { - width: 25%; - float: left; - - &:first-child>a { - padding-left: 15px; - } - - a { - @extend %extend_3; - - &:hover { - cursor: pointer; - } - - margin: 0; - border: none; - border-radius: 0; - padding: 10px 0 10px 45px; - - &:before { - @extend %extend_befor_after; - border-left: 30px solid #ddd; - margin-left: 1px; - z-index: 1; - } - - &:after { - @extend %extend_befor_after; - border-left: 30px solid #f5f5f5; - z-index: 2; - } - } - - &.disabled a { - @extend %extend_4; - } - - &.current a { - @extend %extend_5; - - &:after { - border-left: 30px solid $color_keppel_approx; - } - } - - &.done a { - background: #b4e5d9; - color: $white; - - &:after { - border-left: 30px solid #b4e5d9; - } - } - - &.error a { - background: $color_scarlet_approx; - color: $white; - - &:after { - border-left: 30px solid $color_scarlet_approx; - } - } - } - } - } - - .content { - background: #f5f5f5; - display: block; - margin: .5em; - position: relative; - width: 100%; //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 5px; - - > { - .title { - display: none; - } - - .body { - float: left; - width: 100%; - height: 95%; - padding: 2.5%; - - >ul { - list-style: disc !important; - - >li { - display: list-item; - } - } - } - } - } - - .actions { - position: relative; - display: block; - text-align: right; - width: 100%; - - ul[role="menu"] { - li+li { - margin-left: 5px; - } - - li.disabled { - a { - opacity: .65; - } - } - - a { - padding: 10px 20px; - background-color: $color_keppel_approx; - color: $white; - margin-bottom: 10px; - border: 1px $color_keppel_approx solid; - border-radius: 4px; - transition: all .3s ease; - margin: 2px; - } - - a[href="#cancel"] { - padding: 10px 20px; - background-color: transparent; - color: $color_keppel_approx; - margin-bottom: 10px; - border: 1px $color_keppel_approx solid; - border-radius: 4px; - transition: all .3s ease; - margin: 2px; - } - } - - >ul { - display: inline-block; - text-align: right; - - >li { - float: left; - margin: 0 .5em; - } - } - } - - .loading .spinner {} - } - - &.vertical> { - .steps { - display: inline; - float: left; - width: 30%; - - >ul>li { - float: none; - width: 100%; - } - } - - .content { - display: inline; - float: left; - margin: 0 2.5% .5em 2.5%; - width: 65%; - } - - .actions { - display: inline; - float: right; - margin: 0 2.5%; - width: 95%; - - >ul>li { - margin: 0 0 0 1em; - } - } - } -} - -.tabcontrol { - @extend %wizard_tabcontrol; - - a { - outline: 0; - } - - ul { - @extend %extend_2; - - >li { - display: block; - padding: 0; - } - } - - > { - .steps .current-info { - position: absolute; - left: -999em; - } - - .content>.title { - display: none; - } - } -} - -@media(max-width: 600px) { - .wizard { - >.steps { - a { - margin-top: .5em; - - &:hover { - margin-top: .5em; - } - - &:active { - margin-top: .5em; - } - } - - >ul>li { - width: 50%; - } - } - - &.vertical> { - .steps { - display: block; - float: none; - width: 100%; - } - - .actions { - display: block; - float: none; - width: 100%; - } - - .content { - display: block; - float: none; - margin: 0 .5em .5em; - width: auto; - } - } - } -} - -@media(max-width: 480px) { - .wizard>.steps>ul>li { - width: 100%; - } -} - -.wizard-modal { - .modal-body { - overflow: hidden; - max-height: none; - } - - .wizard { - position: relative; - width: 100%; - height: 100%; - - .content { - max-height: 400px; - overflow: auto; - margin: 0px 0px 15px 0px; - } - - .actions { - >ul>li { - margin: 0px; - } - } - } -} \ No newline at end of file diff --git a/dashboardv2/public/ieerror.html b/dashboardv2/public/ieerror.html deleted file mode 100644 index 5e3f7c40c71..00000000000 --- a/dashboardv2/public/ieerror.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - Atlas - - - - - - - - -

    - - - - -
    -
    - -
    -
    -

    Please note that Atlas does not supports old version of Internet Explorer.

    -

    We recommend upgrading to the latest Internet Explorer, Google Chrome, or Firefox.

    -
    -
    - -
    - - - diff --git a/dashboardv2/public/img/atlas_logo.png b/dashboardv2/public/img/atlas_logo.png deleted file mode 100644 index f0203f6f0d9..00000000000 Binary files a/dashboardv2/public/img/atlas_logo.png and /dev/null differ diff --git a/dashboardv2/public/img/atlas_logo.svg b/dashboardv2/public/img/atlas_logo.svg deleted file mode 100644 index 3314cb039e7..00000000000 --- a/dashboardv2/public/img/atlas_logo.svg +++ /dev/null @@ -1,17 +0,0 @@ - -Asset 6 \ No newline at end of file diff --git a/dashboardv2/public/img/atlas_logo_beta.png b/dashboardv2/public/img/atlas_logo_beta.png deleted file mode 100644 index fcd54d4da0d..00000000000 Binary files a/dashboardv2/public/img/atlas_logo_beta.png and /dev/null differ diff --git a/dashboardv2/public/img/atlas_logo_beta.svg b/dashboardv2/public/img/atlas_logo_beta.svg deleted file mode 100644 index 18fe3e9eb67..00000000000 --- a/dashboardv2/public/img/atlas_logo_beta.svg +++ /dev/null @@ -1,17 +0,0 @@ - -Atlas_Logo_Beta \ No newline at end of file diff --git a/dashboardv2/public/img/atlas_monogram.svg b/dashboardv2/public/img/atlas_monogram.svg deleted file mode 100644 index 1bea91b3ddc..00000000000 --- a/dashboardv2/public/img/atlas_monogram.svg +++ /dev/null @@ -1,17 +0,0 @@ - -Atlas_Logo_monogram \ No newline at end of file diff --git a/dashboardv2/public/img/entity-icon/AtlasServer.png b/dashboardv2/public/img/entity-icon/AtlasServer.png deleted file mode 100644 index f24c01794b1..00000000000 Binary files a/dashboardv2/public/img/entity-icon/AtlasServer.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/DataSet.png b/dashboardv2/public/img/entity-icon/DataSet.png deleted file mode 100644 index 5fb37673603..00000000000 Binary files a/dashboardv2/public/img/entity-icon/DataSet.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/avro.png b/dashboardv2/public/img/entity-icon/avro.png deleted file mode 100644 index f1de7f8b82c..00000000000 Binary files a/dashboardv2/public/img/entity-icon/avro.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/aws.png b/dashboardv2/public/img/entity-icon/aws.png deleted file mode 100644 index 8c8f7c504a7..00000000000 Binary files a/dashboardv2/public/img/entity-icon/aws.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/azure.png b/dashboardv2/public/img/entity-icon/azure.png deleted file mode 100644 index 82e1caa49f2..00000000000 Binary files a/dashboardv2/public/img/entity-icon/azure.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/db.png b/dashboardv2/public/img/entity-icon/db.png deleted file mode 100644 index 577d5805fbe..00000000000 Binary files a/dashboardv2/public/img/entity-icon/db.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/AtlasServer.png b/dashboardv2/public/img/entity-icon/disabled/AtlasServer.png deleted file mode 100644 index ab3a1247950..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/AtlasServer.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/DataSet.png b/dashboardv2/public/img/entity-icon/disabled/DataSet.png deleted file mode 100644 index 5ed51de7592..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/DataSet.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/avro.png b/dashboardv2/public/img/entity-icon/disabled/avro.png deleted file mode 100644 index c9a6172cf65..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/avro.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/aws.png b/dashboardv2/public/img/entity-icon/disabled/aws.png deleted file mode 100644 index d9be6f3ea0a..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/aws.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/azure.png b/dashboardv2/public/img/entity-icon/disabled/azure.png deleted file mode 100644 index 720f3ac5915..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/azure.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/db.png b/dashboardv2/public/img/entity-icon/disabled/db.png deleted file mode 100644 index 982c6867a29..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/db.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/falcon.png b/dashboardv2/public/img/entity-icon/disabled/falcon.png deleted file mode 100644 index ef8cd242eb6..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/falcon.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/falcon_feed_creation.png b/dashboardv2/public/img/entity-icon/disabled/falcon_feed_creation.png deleted file mode 100644 index f7404678833..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/falcon_feed_creation.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/falcon_feed_replication.png b/dashboardv2/public/img/entity-icon/disabled/falcon_feed_replication.png deleted file mode 100644 index af492dabe66..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/falcon_feed_replication.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/falcon_process.png b/dashboardv2/public/img/entity-icon/disabled/falcon_process.png deleted file mode 100644 index 075628c5898..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/falcon_process.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/file_system.png b/dashboardv2/public/img/entity-icon/disabled/file_system.png deleted file mode 100644 index 8b4e50416c3..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/file_system.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/flink.png b/dashboardv2/public/img/entity-icon/disabled/flink.png deleted file mode 100644 index af78144be18..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/flink.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/flink_application.png b/dashboardv2/public/img/entity-icon/disabled/flink_application.png deleted file mode 100644 index af78144be18..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/flink_application.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/flink_application_processes.png b/dashboardv2/public/img/entity-icon/disabled/flink_application_processes.png deleted file mode 100644 index 28d4ed91683..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/flink_application_processes.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/flink_process.png b/dashboardv2/public/img/entity-icon/disabled/flink_process.png deleted file mode 100644 index af78144be18..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/flink_process.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/gcp.png b/dashboardv2/public/img/entity-icon/disabled/gcp.png deleted file mode 100644 index e7d83fe36b8..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/gcp.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/hadoop.png b/dashboardv2/public/img/entity-icon/disabled/hadoop.png deleted file mode 100644 index 0334fc7d78e..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/hadoop.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/hbase.png b/dashboardv2/public/img/entity-icon/disabled/hbase.png deleted file mode 100644 index fa6e21427dd..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/hbase.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/hbase_column.png b/dashboardv2/public/img/entity-icon/disabled/hbase_column.png deleted file mode 100644 index ef454267bf4..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/hbase_column.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/hbase_column_family.png b/dashboardv2/public/img/entity-icon/disabled/hbase_column_family.png deleted file mode 100644 index 0182ec3e0f2..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/hbase_column_family.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/hbase_table.png b/dashboardv2/public/img/entity-icon/disabled/hbase_table.png deleted file mode 100644 index 556a10a14d7..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/hbase_table.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/hdfs_path.png b/dashboardv2/public/img/entity-icon/disabled/hdfs_path.png deleted file mode 100644 index 8b4e50416c3..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/hdfs_path.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/hive.png b/dashboardv2/public/img/entity-icon/disabled/hive.png deleted file mode 100644 index 227f5b3a31b..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/hive.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/hive_column.png b/dashboardv2/public/img/entity-icon/disabled/hive_column.png deleted file mode 100644 index 35fbe482343..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/hive_column.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/hive_column_lineage.png b/dashboardv2/public/img/entity-icon/disabled/hive_column_lineage.png deleted file mode 100644 index c08f4b4200c..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/hive_column_lineage.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/hive_db.png b/dashboardv2/public/img/entity-icon/disabled/hive_db.png deleted file mode 100644 index 76b5c3f8c5f..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/hive_db.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/hive_process.png b/dashboardv2/public/img/entity-icon/disabled/hive_process.png deleted file mode 100644 index 5cc6d78c6d7..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/hive_process.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/hive_process_execution.png b/dashboardv2/public/img/entity-icon/disabled/hive_process_execution.png deleted file mode 100644 index ec1be806184..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/hive_process_execution.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/hive_storagedesc.png b/dashboardv2/public/img/entity-icon/disabled/hive_storagedesc.png deleted file mode 100644 index c3930a43f46..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/hive_storagedesc.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/hive_table.png b/dashboardv2/public/img/entity-icon/disabled/hive_table.png deleted file mode 100644 index b22e194d83f..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/hive_table.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/impala.png b/dashboardv2/public/img/entity-icon/disabled/impala.png deleted file mode 100644 index c94be973b71..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/impala.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/impala_column_lineage.png b/dashboardv2/public/img/entity-icon/disabled/impala_column_lineage.png deleted file mode 100755 index 7ef403bc4d2..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/impala_column_lineage.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/impala_process.png b/dashboardv2/public/img/entity-icon/disabled/impala_process.png deleted file mode 100755 index 7ef403bc4d2..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/impala_process.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/jms_topic.png b/dashboardv2/public/img/entity-icon/disabled/jms_topic.png deleted file mode 100644 index 54a02c8f447..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/jms_topic.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/kafka.png b/dashboardv2/public/img/entity-icon/disabled/kafka.png deleted file mode 100644 index ef941d3445f..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/kafka.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/kafka_consumer.png b/dashboardv2/public/img/entity-icon/disabled/kafka_consumer.png deleted file mode 100644 index d7e564f0fa9..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/kafka_consumer.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/kafka_consumer_group.png b/dashboardv2/public/img/entity-icon/disabled/kafka_consumer_group.png deleted file mode 100644 index 1bc9dadfc27..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/kafka_consumer_group.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/kafka_consumer_lineage.png b/dashboardv2/public/img/entity-icon/disabled/kafka_consumer_lineage.png deleted file mode 100644 index 80248e9f078..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/kafka_consumer_lineage.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/kafka_producer.png b/dashboardv2/public/img/entity-icon/disabled/kafka_producer.png deleted file mode 100644 index 372cff48f1d..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/kafka_producer.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/kafka_producer_lineage.png b/dashboardv2/public/img/entity-icon/disabled/kafka_producer_lineage.png deleted file mode 100644 index c312b548077..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/kafka_producer_lineage.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/kafka_topic.png b/dashboardv2/public/img/entity-icon/disabled/kafka_topic.png deleted file mode 100644 index 84cb234161d..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/kafka_topic.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/ozone.png b/dashboardv2/public/img/entity-icon/disabled/ozone.png deleted file mode 100644 index f498c2d149a..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/ozone.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/ozone_bucket.png b/dashboardv2/public/img/entity-icon/disabled/ozone_bucket.png deleted file mode 100644 index 5b0d5d159ef..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/ozone_bucket.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/ozone_key.png b/dashboardv2/public/img/entity-icon/disabled/ozone_key.png deleted file mode 100644 index 4dba49172df..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/ozone_key.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/ozone_volume.png b/dashboardv2/public/img/entity-icon/disabled/ozone_volume.png deleted file mode 100644 index 1e4326b22a3..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/ozone_volume.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/process.png b/dashboardv2/public/img/entity-icon/disabled/process.png deleted file mode 100644 index 88bc1ae7588..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/process.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/rdbms.png b/dashboardv2/public/img/entity-icon/disabled/rdbms.png deleted file mode 100644 index 84f20bae4fa..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/rdbms.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/rdbms_column.png b/dashboardv2/public/img/entity-icon/disabled/rdbms_column.png deleted file mode 100644 index 200a2882161..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/rdbms_column.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/rdbms_db.png b/dashboardv2/public/img/entity-icon/disabled/rdbms_db.png deleted file mode 100644 index 6f1d1690f8d..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/rdbms_db.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/rdbms_table.png b/dashboardv2/public/img/entity-icon/disabled/rdbms_table.png deleted file mode 100644 index e49fc68f848..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/rdbms_table.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/spark.png b/dashboardv2/public/img/entity-icon/disabled/spark.png deleted file mode 100644 index 93f8a4d8608..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/spark.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/spark_process.png b/dashboardv2/public/img/entity-icon/disabled/spark_process.png deleted file mode 100644 index bf191217c19..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/spark_process.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/spark_table.png b/dashboardv2/public/img/entity-icon/disabled/spark_table.png deleted file mode 100644 index 1404026ae4d..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/spark_table.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/sqoop.png b/dashboardv2/public/img/entity-icon/disabled/sqoop.png deleted file mode 100644 index 359b77edf99..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/sqoop.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/sqoop_db.png b/dashboardv2/public/img/entity-icon/disabled/sqoop_db.png deleted file mode 100644 index 970ab9a6bea..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/sqoop_db.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/sqoop_process.png b/dashboardv2/public/img/entity-icon/disabled/sqoop_process.png deleted file mode 100644 index aae4d56092d..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/sqoop_process.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/storm.png b/dashboardv2/public/img/entity-icon/disabled/storm.png deleted file mode 100644 index cab3f7f021a..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/storm.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/storm_bolt.png b/dashboardv2/public/img/entity-icon/disabled/storm_bolt.png deleted file mode 100644 index f35add3ac5e..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/storm_bolt.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/storm_spout.png b/dashboardv2/public/img/entity-icon/disabled/storm_spout.png deleted file mode 100644 index 841375170a3..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/storm_spout.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/storm_topology.png b/dashboardv2/public/img/entity-icon/disabled/storm_topology.png deleted file mode 100644 index 224a2876fb8..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/storm_topology.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/disabled/table.png b/dashboardv2/public/img/entity-icon/disabled/table.png deleted file mode 100644 index de1e5cdff0f..00000000000 Binary files a/dashboardv2/public/img/entity-icon/disabled/table.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/falcon.png b/dashboardv2/public/img/entity-icon/falcon.png deleted file mode 100644 index 14e8234d4f9..00000000000 Binary files a/dashboardv2/public/img/entity-icon/falcon.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/falcon_feed_creation.png b/dashboardv2/public/img/entity-icon/falcon_feed_creation.png deleted file mode 100644 index 955404cdf32..00000000000 Binary files a/dashboardv2/public/img/entity-icon/falcon_feed_creation.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/falcon_feed_replication.png b/dashboardv2/public/img/entity-icon/falcon_feed_replication.png deleted file mode 100644 index 7cbf15ddc8b..00000000000 Binary files a/dashboardv2/public/img/entity-icon/falcon_feed_replication.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/falcon_process.png b/dashboardv2/public/img/entity-icon/falcon_process.png deleted file mode 100644 index baee877a9fb..00000000000 Binary files a/dashboardv2/public/img/entity-icon/falcon_process.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/file_system.png b/dashboardv2/public/img/entity-icon/file_system.png deleted file mode 100644 index 778578690f8..00000000000 Binary files a/dashboardv2/public/img/entity-icon/file_system.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/flink.png b/dashboardv2/public/img/entity-icon/flink.png deleted file mode 100644 index 9a94d12c3c0..00000000000 Binary files a/dashboardv2/public/img/entity-icon/flink.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/flink_application.png b/dashboardv2/public/img/entity-icon/flink_application.png deleted file mode 100644 index 9a94d12c3c0..00000000000 Binary files a/dashboardv2/public/img/entity-icon/flink_application.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/flink_application_processes.png b/dashboardv2/public/img/entity-icon/flink_application_processes.png deleted file mode 100644 index 53237abdac5..00000000000 Binary files a/dashboardv2/public/img/entity-icon/flink_application_processes.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/flink_process.png b/dashboardv2/public/img/entity-icon/flink_process.png deleted file mode 100644 index 9a94d12c3c0..00000000000 Binary files a/dashboardv2/public/img/entity-icon/flink_process.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/gcp.png b/dashboardv2/public/img/entity-icon/gcp.png deleted file mode 100644 index 4740e8dbf24..00000000000 Binary files a/dashboardv2/public/img/entity-icon/gcp.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hadoop.png b/dashboardv2/public/img/entity-icon/hadoop.png deleted file mode 100644 index cceb1f411a1..00000000000 Binary files a/dashboardv2/public/img/entity-icon/hadoop.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hbase.png b/dashboardv2/public/img/entity-icon/hbase.png deleted file mode 100644 index fd657dd169d..00000000000 Binary files a/dashboardv2/public/img/entity-icon/hbase.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hbase_column.png b/dashboardv2/public/img/entity-icon/hbase_column.png deleted file mode 100644 index 9cf9a38872e..00000000000 Binary files a/dashboardv2/public/img/entity-icon/hbase_column.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hbase_column_family.png b/dashboardv2/public/img/entity-icon/hbase_column_family.png deleted file mode 100644 index d89aaae0674..00000000000 Binary files a/dashboardv2/public/img/entity-icon/hbase_column_family.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hbase_table.png b/dashboardv2/public/img/entity-icon/hbase_table.png deleted file mode 100644 index d937443f9d6..00000000000 Binary files a/dashboardv2/public/img/entity-icon/hbase_table.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hdfs_path.png b/dashboardv2/public/img/entity-icon/hdfs_path.png deleted file mode 100644 index 778578690f8..00000000000 Binary files a/dashboardv2/public/img/entity-icon/hdfs_path.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hive.png b/dashboardv2/public/img/entity-icon/hive.png deleted file mode 100644 index 531837d58f0..00000000000 Binary files a/dashboardv2/public/img/entity-icon/hive.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hive_column.png b/dashboardv2/public/img/entity-icon/hive_column.png deleted file mode 100644 index 74753fa9470..00000000000 Binary files a/dashboardv2/public/img/entity-icon/hive_column.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hive_column_lineage.png b/dashboardv2/public/img/entity-icon/hive_column_lineage.png deleted file mode 100644 index 3a85f786b71..00000000000 Binary files a/dashboardv2/public/img/entity-icon/hive_column_lineage.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hive_db.png b/dashboardv2/public/img/entity-icon/hive_db.png deleted file mode 100644 index 216eaeb9dfa..00000000000 Binary files a/dashboardv2/public/img/entity-icon/hive_db.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hive_process.png b/dashboardv2/public/img/entity-icon/hive_process.png deleted file mode 100644 index 4083bcacd85..00000000000 Binary files a/dashboardv2/public/img/entity-icon/hive_process.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hive_process_execution.png b/dashboardv2/public/img/entity-icon/hive_process_execution.png deleted file mode 100644 index 4499724ac77..00000000000 Binary files a/dashboardv2/public/img/entity-icon/hive_process_execution.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hive_storagedesc.png b/dashboardv2/public/img/entity-icon/hive_storagedesc.png deleted file mode 100644 index ef9fd4801ef..00000000000 Binary files a/dashboardv2/public/img/entity-icon/hive_storagedesc.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hive_table.png b/dashboardv2/public/img/entity-icon/hive_table.png deleted file mode 100644 index d2209e8d40d..00000000000 Binary files a/dashboardv2/public/img/entity-icon/hive_table.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/hourglass.svg b/dashboardv2/public/img/entity-icon/hourglass.svg deleted file mode 100644 index aad49788c08..00000000000 --- a/dashboardv2/public/img/entity-icon/hourglass.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/dashboardv2/public/img/entity-icon/impala.png b/dashboardv2/public/img/entity-icon/impala.png deleted file mode 100644 index bd6b29990a6..00000000000 Binary files a/dashboardv2/public/img/entity-icon/impala.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/impala_column_lineage.png b/dashboardv2/public/img/entity-icon/impala_column_lineage.png deleted file mode 100755 index 3980326a1c7..00000000000 Binary files a/dashboardv2/public/img/entity-icon/impala_column_lineage.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/impala_process.png b/dashboardv2/public/img/entity-icon/impala_process.png deleted file mode 100755 index 3980326a1c7..00000000000 Binary files a/dashboardv2/public/img/entity-icon/impala_process.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/jms_topic.png b/dashboardv2/public/img/entity-icon/jms_topic.png deleted file mode 100644 index 4d08bc319e5..00000000000 Binary files a/dashboardv2/public/img/entity-icon/jms_topic.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/kafka.png b/dashboardv2/public/img/entity-icon/kafka.png deleted file mode 100644 index 4985375a9ae..00000000000 Binary files a/dashboardv2/public/img/entity-icon/kafka.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/kafka_consumer.png b/dashboardv2/public/img/entity-icon/kafka_consumer.png deleted file mode 100644 index 5951283ab04..00000000000 Binary files a/dashboardv2/public/img/entity-icon/kafka_consumer.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/kafka_consumer_group.png b/dashboardv2/public/img/entity-icon/kafka_consumer_group.png deleted file mode 100644 index 9b8e9561077..00000000000 Binary files a/dashboardv2/public/img/entity-icon/kafka_consumer_group.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/kafka_consumer_lineage.png b/dashboardv2/public/img/entity-icon/kafka_consumer_lineage.png deleted file mode 100644 index ab103f43bd2..00000000000 Binary files a/dashboardv2/public/img/entity-icon/kafka_consumer_lineage.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/kafka_producer.png b/dashboardv2/public/img/entity-icon/kafka_producer.png deleted file mode 100644 index be4d96b8084..00000000000 Binary files a/dashboardv2/public/img/entity-icon/kafka_producer.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/kafka_producer_lineage.png b/dashboardv2/public/img/entity-icon/kafka_producer_lineage.png deleted file mode 100644 index 48dd90d18b9..00000000000 Binary files a/dashboardv2/public/img/entity-icon/kafka_producer_lineage.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/kafka_topic.png b/dashboardv2/public/img/entity-icon/kafka_topic.png deleted file mode 100644 index 3eae9abf1b1..00000000000 Binary files a/dashboardv2/public/img/entity-icon/kafka_topic.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/ozone.png b/dashboardv2/public/img/entity-icon/ozone.png deleted file mode 100644 index 1b0a9284a2e..00000000000 Binary files a/dashboardv2/public/img/entity-icon/ozone.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/ozone_bucket.png b/dashboardv2/public/img/entity-icon/ozone_bucket.png deleted file mode 100644 index d7a39726b24..00000000000 Binary files a/dashboardv2/public/img/entity-icon/ozone_bucket.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/ozone_key.png b/dashboardv2/public/img/entity-icon/ozone_key.png deleted file mode 100644 index 2e64f837e0b..00000000000 Binary files a/dashboardv2/public/img/entity-icon/ozone_key.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/ozone_volume.png b/dashboardv2/public/img/entity-icon/ozone_volume.png deleted file mode 100644 index b00a41bf441..00000000000 Binary files a/dashboardv2/public/img/entity-icon/ozone_volume.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/process.png b/dashboardv2/public/img/entity-icon/process.png deleted file mode 100644 index 0b01d1b0939..00000000000 Binary files a/dashboardv2/public/img/entity-icon/process.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/rdbms.png b/dashboardv2/public/img/entity-icon/rdbms.png deleted file mode 100644 index f9dfa989554..00000000000 Binary files a/dashboardv2/public/img/entity-icon/rdbms.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/rdbms_column.png b/dashboardv2/public/img/entity-icon/rdbms_column.png deleted file mode 100644 index 8b05f352b7d..00000000000 Binary files a/dashboardv2/public/img/entity-icon/rdbms_column.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/rdbms_db.png b/dashboardv2/public/img/entity-icon/rdbms_db.png deleted file mode 100644 index b9200be8e56..00000000000 Binary files a/dashboardv2/public/img/entity-icon/rdbms_db.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/rdbms_table.png b/dashboardv2/public/img/entity-icon/rdbms_table.png deleted file mode 100644 index 3f6630ffd4d..00000000000 Binary files a/dashboardv2/public/img/entity-icon/rdbms_table.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/spark.png b/dashboardv2/public/img/entity-icon/spark.png deleted file mode 100644 index 27bf2f746d6..00000000000 Binary files a/dashboardv2/public/img/entity-icon/spark.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/spark_process.png b/dashboardv2/public/img/entity-icon/spark_process.png deleted file mode 100644 index 077b0351b31..00000000000 Binary files a/dashboardv2/public/img/entity-icon/spark_process.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/spark_table.png b/dashboardv2/public/img/entity-icon/spark_table.png deleted file mode 100644 index af90c24e694..00000000000 Binary files a/dashboardv2/public/img/entity-icon/spark_table.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/sqoop.png b/dashboardv2/public/img/entity-icon/sqoop.png deleted file mode 100644 index 3cd6345ef79..00000000000 Binary files a/dashboardv2/public/img/entity-icon/sqoop.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/sqoop_db.png b/dashboardv2/public/img/entity-icon/sqoop_db.png deleted file mode 100644 index fe46bc9423a..00000000000 Binary files a/dashboardv2/public/img/entity-icon/sqoop_db.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/sqoop_process.png b/dashboardv2/public/img/entity-icon/sqoop_process.png deleted file mode 100644 index e4757305e43..00000000000 Binary files a/dashboardv2/public/img/entity-icon/sqoop_process.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/storm.png b/dashboardv2/public/img/entity-icon/storm.png deleted file mode 100644 index 4549aa5d8e7..00000000000 Binary files a/dashboardv2/public/img/entity-icon/storm.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/storm_bolt.png b/dashboardv2/public/img/entity-icon/storm_bolt.png deleted file mode 100644 index 86d2f795932..00000000000 Binary files a/dashboardv2/public/img/entity-icon/storm_bolt.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/storm_spout.png b/dashboardv2/public/img/entity-icon/storm_spout.png deleted file mode 100644 index 0d1e1bead14..00000000000 Binary files a/dashboardv2/public/img/entity-icon/storm_spout.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/storm_topology.png b/dashboardv2/public/img/entity-icon/storm_topology.png deleted file mode 100644 index 6f705e0083e..00000000000 Binary files a/dashboardv2/public/img/entity-icon/storm_topology.png and /dev/null differ diff --git a/dashboardv2/public/img/entity-icon/table.png b/dashboardv2/public/img/entity-icon/table.png deleted file mode 100644 index b07049bc1e3..00000000000 Binary files a/dashboardv2/public/img/entity-icon/table.png and /dev/null differ diff --git a/dashboardv2/public/img/favicon.ico b/dashboardv2/public/img/favicon.ico deleted file mode 100644 index 5cd060fd19b..00000000000 Binary files a/dashboardv2/public/img/favicon.ico and /dev/null differ diff --git a/dashboardv2/public/img/loading.gif b/dashboardv2/public/img/loading.gif deleted file mode 100644 index 5b33f7e54f4..00000000000 Binary files a/dashboardv2/public/img/loading.gif and /dev/null differ diff --git a/dashboardv2/public/img/ring.gif b/dashboardv2/public/img/ring.gif deleted file mode 100644 index f18f441785c..00000000000 Binary files a/dashboardv2/public/img/ring.gif and /dev/null differ diff --git a/dashboardv2/public/index.html.tpl b/dashboardv2/public/index.html.tpl deleted file mode 100644 index 55cf2e8cc7f..00000000000 --- a/dashboardv2/public/index.html.tpl +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - Atlas - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    - - - - - - - \ No newline at end of file diff --git a/dashboardv2/public/js/App.js b/dashboardv2/public/js/App.js deleted file mode 100644 index cc5daea0cc1..00000000000 --- a/dashboardv2/public/js/App.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['marionette'], function(Marionette) { - - var App = new Marionette.Application(); - - App.addRegions({ - rHeader: '#header', - rSideNav: '#sideNav-wrapper', - rNContent: '#new-page-wrapper', - rNHeader: '#new-header', - rContent: '#page-wrapper', - rFooter: '#footer' - - }); - - App.addInitializer(function() { - Backbone.history.start(); - }); - - return App; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/collection/BaseCollection.js b/dashboardv2/public/js/collection/BaseCollection.js deleted file mode 100644 index 30f5b76d07e..00000000000 --- a/dashboardv2/public/js/collection/BaseCollection.js +++ /dev/null @@ -1,143 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'utils/Utils', - 'utils/CommonViewFunction', - 'backbone.paginator' -], function(require, Globals, Utils, CommonViewFunction) { - 'use strict'; - - var BaseCollection = Backbone.PageableCollection.extend( - /** @lends BaseCollection.prototype */ - { - /** - * BaseCollection's initialize function - * @augments Backbone.PageableCollection - * @constructs - */ - - initialize: function() { - this.sort_key = 'id'; - }, - comparator: function(key, value) { - key = key.get(this.sort_key); - value = value.get(this.sort_key); - return key > value ? 1 : key < value ? -1 : 0; - }, - sortByKey: function(sortKey) { - this.sort_key = sortKey; - this.sort(); - }, - /** - * state required for the PageableCollection - */ - state: { - firstPage: 0, - pageSize: Globals.settings.PAGE_SIZE - }, - mode: 'client', - /** - * override the parseRecords of PageableCollection for our use - */ - parseRecords: function(resp, options) { - this.responseData = { - dataType: resp.dataType, - query: resp.query, - queryType: resp.queryType, - requestId: resp.requestId - }; - try { - if (!this.modelAttrName) { - throw new Error("this.modelAttrName not defined for " + this); - } - return resp[this.modelAttrName]; - } catch (e) { - console.log(e); - } - }, - - //////////////////////////////////////////////////////////// - // Overriding backbone-pageable page handlers methods // - //////////////////////////////////////////////////////////// - getFirstPage: function(options) { - return this.getPage('first', _.extend({ - reset: true - }, options)); - }, - - getPreviousPage: function(options) { - return this.getPage("prev", _.extend({ - reset: true - }, options)); - }, - - getNextPage: function(options) { - return this.getPage("next", _.extend({ - reset: true - }, options)); - }, - - getLastPage: function(options) { - return this.getPage("last", _.extend({ - reset: true - }, options)); - }, - hasPrevious: function(options) { - return this.hasPreviousPage(); - }, - hasNext: function(options) { - return this.hasNextPage(); - } - ///////////////////////////// - // End overriding methods // - ///////////////////////////// - - }, - /** BaseCollection's Static Attributes */ - { - // Static functions - getTableCols: function(cols, collection, defaultSortDirection) { - var retCols = _.map(cols, function(v, k, l) { - var defaults = collection.constructor.tableCols[k]; - if (!defaults) { - //console.log("Error!! " + k + " not found in collection: " , collection); - defaults = {}; - } - return _.extend({ - 'name': k, - direction: defaultSortDirection ? defaultSortDirection : null, - }, defaults, v); - }); - return retCols; - }, - nonCrudOperation: function(url, requestMethod, options) { - var that = this; - options['beforeSend'] = CommonViewFunction.addRestCsrfCustomHeader; - if (options.data && typeof options.data === "object") { - options.data = JSON.stringify(options.data); - } - return Backbone.sync.call(this, null, this, _.extend({ - url: url, - type: requestMethod - }, options)); - } - }); - return BaseCollection; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/collection/VCommonList.js b/dashboardv2/public/js/collection/VCommonList.js deleted file mode 100644 index d5b0a9ec965..00000000000 --- a/dashboardv2/public/js/collection/VCommonList.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VCommon', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VCommon, UrlLinks) { - 'use strict'; - var VCommonList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.baseURL + '', - - model: VCommon, - - initialize: function() { - this.modelName = 'VCommon'; - this.modelAttrName = ''; - }, - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VCommonList; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/collection/VEntityList.js b/dashboardv2/public/js/collection/VEntityList.js deleted file mode 100644 index 645bc0c20b5..00000000000 --- a/dashboardv2/public/js/collection/VEntityList.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VEntity', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VEntity, UrlLinks) { - 'use strict'; - var VEntityList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.entitiesApiUrl(), - - model: VEntity, - - initialize: function() { - this.modelName = 'VEntity'; - this.modelAttrName = 'entityDefs'; - }, - parseRecords: function(resp, options) { - try { - // if (!this.modelAttrName) { - // throw new Error("this.modelAttrName not defined for " + this); - // } - if (resp.entity && resp.referredEntities) { - var obj = { - entity: resp.entity, - referredEntities: resp.referredEntities - } - return obj; - } else if (resp[this.modelAttrName]) { - return resp[this.modelAttrName]; - } else { - return resp - } - - } catch (e) { - console.log(e); - } - }, - getAdminData: function(options) { - var url = UrlLinks.adminApiUrl(); - options = _.extend({ - contentType: 'application/json', - dataType: 'json' - }, options); - return this.constructor.nonCrudOperation.call(this, url, 'POST', options); - } - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VEntityList; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/collection/VGlossaryList.js b/dashboardv2/public/js/collection/VGlossaryList.js deleted file mode 100644 index 9c4918f2ff2..00000000000 --- a/dashboardv2/public/js/collection/VGlossaryList.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VGlossary', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VGlossary, UrlLinks) { - 'use strict'; - var VGlossaryList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.glossaryApiUrl(), - - model: VGlossary, - - initialize: function() { - this.modelName = 'VGlossary'; - this.modelAttrName = ''; - }, - parseRecords: function(resp, options) { - if (_.isEmpty(this.modelAttrName)) { - return resp; - } else { - return resp[this.modelAttrName] - } - }, - getCategory: function(options) { - var url = UrlLinks.categoryApiUrl({ "guid": options.guid, "related": options.related }), - apiOptions = _.extend({ - contentType: 'application/json', - dataType: 'json' - }, options.ajaxOptions); - return this.constructor.nonCrudOperation.call(this, url, 'GET', apiOptions); - }, - getTerm: function(options) { - var url = UrlLinks.termApiUrl({ "guid": options.guid, "related": options.related }), - apiOptions = _.extend({ - contentType: 'application/json', - dataType: 'json' - }, options.ajaxOptions); - return this.constructor.nonCrudOperation.call(this, url, 'GET', apiOptions); - } - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VGlossaryList; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/collection/VLineageList.js b/dashboardv2/public/js/collection/VLineageList.js deleted file mode 100644 index bda649220ee..00000000000 --- a/dashboardv2/public/js/collection/VLineageList.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VLineage', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VLineage, UrlLinks) { - 'use strict'; - var VLineageList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.baseURL, - - model: VLineage, - - initialize: function() { - this.modelName = 'VLineage'; - this.modelAttrName = 'results'; - }, - getLineage: function(id, options) { - var url = UrlLinks.lineageApiUrl(id); - - options = _.extend({ - contentType: 'application/json', - dataType: 'json' - }, options); - - return this.constructor.nonCrudOperation.call(this, url, 'GET', options); - } - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VLineageList; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/collection/VProfileList.js b/dashboardv2/public/js/collection/VProfileList.js deleted file mode 100644 index 06f0e110f72..00000000000 --- a/dashboardv2/public/js/collection/VProfileList.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VProfile' -], function(require, Globals, BaseCollection, VProfile) { - 'use strict'; - var VProfileList = BaseCollection.extend( - //Prototypal attributes - { - url: Globals.baseURL + '/api/atlas/entities', - - model: VProfile, - - initialize: function() { - this.modelName = 'VProfile'; - this.modelAttrName = 'definition'; - this.bindErrorEvents(); - } - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VProfileList; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/collection/VRelationshipList.js b/dashboardv2/public/js/collection/VRelationshipList.js deleted file mode 100644 index 2fda826be17..00000000000 --- a/dashboardv2/public/js/collection/VRelationshipList.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VRelationship', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VRelationship, UrlLinks) { - 'use strict'; - var VRelationshipList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.baseURL, - - model: VRelationship, - - initialize: function() { - this.modelName = 'VRelationship'; - this.modelAttrName = 'results'; - }, - getRelationship: function(id, options) { - var url = UrlLinks.relationshipApiUrl(id); - - options = _.extend({ - contentType: 'application/json', - dataType: 'json' - }, options); - - return this.constructor.nonCrudOperation.call(this, url, 'GET', options); - } - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VRelationshipList; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/collection/VSchemaList.js b/dashboardv2/public/js/collection/VSchemaList.js deleted file mode 100644 index fceaaa29ae0..00000000000 --- a/dashboardv2/public/js/collection/VSchemaList.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VSchema', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VSchema, UrlLinks) { - 'use strict'; - var VSchemaList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.baseURL, - model: VSchema, - initialize: function() { - this.modelName = 'VSchema'; - this.modelAttrName = 'results'; - }, - parseRecords: function(resp, options) { - try { - if (!this.modelAttrName) { - throw new Error("this.modelAttrName not defined for " + this); - } - this.keyList = resp[this.modelAttrName].dataType.attributeDefinitions; - if (resp[this.modelAttrName].dataType.superTypes) { - if (resp[this.modelAttrName].dataType.superTypes.indexOf("Asset") != -1) { - this.keyList.push({ - "name": "name", - "dataTypeName": "string", - "isComposite": false, - "isIndexable": true, - "isUnique": false, - "multiplicity": {}, - "reverseAttributeName": null - }) - } - } - var arr = []; - resp[this.modelAttrName].rows.forEach(function(d) { - arr.push(d); - }); - return arr; - } catch (e) { - console.log(e); - } - }, - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VSchemaList; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/collection/VSearchList.js b/dashboardv2/public/js/collection/VSearchList.js deleted file mode 100644 index 227d3dc281f..00000000000 --- a/dashboardv2/public/js/collection/VSearchList.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VSearch', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VSearch, UrlLinks) { - 'use strict'; - var VSearchList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.searchApiUrl(), - - model: VSearch, - - initialize: function(options) { - _.extend(this, options); - this.modelName = 'VSearchList'; - this.modelAttrName = ''; - }, - parseRecords: function(resp, options) { - this.queryType = resp.queryType; - this.queryText = resp.queryText; - this.referredEntities = resp.referredEntities; - if (resp.attributes) { - this.dynamicTable = true; - var entities = []; - _.each(resp.attributes.values, function(obj) { - var temp = {}; - _.each(obj, function(val, index) { - var key = resp.attributes.name[index]; - if (key == "__guid") { - key = "guid" - } - temp[key] = val; - }); - entities.push(temp); - }); - return entities; - } else if (resp.entities) { - this.dynamicTable = false; - return resp.entities ? resp.entities : []; - } else { - return []; - } - }, - getExpimpAudit: function(params, options) { - var url = UrlLinks.expimpAudit(params); - - options = _.extend({ - contentType: 'application/json', - dataType: 'json', - }, options); - - return this.constructor.nonCrudOperation.call(this, url, 'GET', options); - }, - getBasicRearchResult: function(options) { - var url = UrlLinks.searchApiUrl('basic'); - - options = _.extend({ - contentType: 'application/json', - dataType: 'json', - }, options); - options.data = JSON.stringify(options.data); - - return this.constructor.nonCrudOperation.call(this, url, 'POST', options); - } - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VSearchList; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/collection/VTagList.js b/dashboardv2/public/js/collection/VTagList.js deleted file mode 100644 index cfbf767009a..00000000000 --- a/dashboardv2/public/js/collection/VTagList.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VTag', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VTag, UrlLinks) { - 'use strict'; - var VTagList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.classificationDefApiUrl(), - model: VTag, - initialize: function() { - this.modelName = 'VTag'; - this.modelAttrName = 'classificationDefs'; - }, - parseRecords: function(resp, options) { - try { - if (!this.modelAttrName) { - throw new Error("this.modelAttrName not defined for " + this); - } - if (resp[this.modelAttrName]) { - return resp[this.modelAttrName]; - } else { - return resp - } - - } catch (e) { - console.log(e); - } - }, - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VTagList; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/LICENSE b/dashboardv2/public/js/external_lib/atlas-lineage/LICENSE deleted file mode 100644 index d6ea1531095..00000000000 --- a/dashboardv2/public/js/external_lib/atlas-lineage/LICENSE +++ /dev/null @@ -1,204 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. - - -======================================================================= \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/dist/index.js b/dashboardv2/public/js/external_lib/atlas-lineage/dist/index.js deleted file mode 100644 index b31ee491136..00000000000 --- a/dashboardv2/public/js/external_lib/atlas-lineage/dist/index.js +++ /dev/null @@ -1 +0,0 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("platform"),require("dagreD3")):"function"==typeof define&&define.amd?define(["platform","dagreD3"],e):"object"==typeof exports?exports.LineageHelper=e(require("platform"),require("dagreD3")):t.LineageHelper=e(t.platform,t.dagreD3)}(window,(function(t,e){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(r,i,function(e){return t[e]}.bind(null,i));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=10)}([,function(e,n){e.exports=t},function(t,n){t.exports=e},,,,,,,function(t,e,n){},function(t,e,n){"use strict";n.r(e),n.d(e,"default",(function(){return Br}));var r=n(2),i=n.n(r);function o(){}var a=function(t){return null==t?o:function(){return this.querySelector(t)}};function s(){return[]}var u=function(t){return null==t?s:function(){return this.querySelectorAll(t)}},l=function(t){return function(){return this.matches(t)}},c=function(t){return new Array(t.length)};function h(t,e){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=e}h.prototype={constructor:h,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,e){return this._parent.insertBefore(t,e)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};function f(t,e,n,r,i,o){for(var a,s=0,u=e.length,l=o.length;se?1:t>=e?0:NaN}var g="http://www.w3.org/1999/xhtml",v={svg:"http://www.w3.org/2000/svg",xhtml:g,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"},y=function(t){var e=t+="",n=e.indexOf(":");return n>=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),v.hasOwnProperty(e)?{space:v[e],local:t}:t};function m(t){return function(){this.removeAttribute(t)}}function w(t){return function(){this.removeAttributeNS(t.space,t.local)}}function b(t,e){return function(){this.setAttribute(t,e)}}function x(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function k(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function E(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}var T=function(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView};function N(t){return function(){this.style.removeProperty(t)}}function O(t,e,n){return function(){this.style.setProperty(t,e,n)}}function S(t,e,n){return function(){var r=e.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}function P(t,e){return t.style.getPropertyValue(e)||T(t).getComputedStyle(t,null).getPropertyValue(e)}function A(t){return function(){delete this[t]}}function M(t,e){return function(){this[t]=e}}function z(t,e){return function(){var n=e.apply(this,arguments);null==n?delete this[t]:this[t]=n}}function j(t){return t.trim().split(/^|\s+/)}function D(t){return t.classList||new B(t)}function B(t){this._node=t,this._names=j(t.getAttribute("class")||"")}function C(t,e){for(var n=D(t),r=-1,i=e.length;++r=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};function q(){this.textContent=""}function U(t){return function(){this.textContent=t}}function F(t){return function(){var e=t.apply(this,arguments);this.textContent=null==e?"":e}}function H(){this.innerHTML=""}function V(t){return function(){this.innerHTML=t}}function X(t){return function(){var e=t.apply(this,arguments);this.innerHTML=null==e?"":e}}function Y(){this.nextSibling&&this.parentNode.appendChild(this)}function Z(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function W(t){return function(){var e=this.ownerDocument,n=this.namespaceURI;return n===g&&e.documentElement.namespaceURI===g?e.createElement(t):e.createElementNS(n,t)}}function K(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}var Q=function(t){var e=y(t);return(e.local?K:W)(e)};function J(){return null}function tt(){var t=this.parentNode;t&&t.removeChild(this)}function et(){var t=this.cloneNode(!1),e=this.parentNode;return e?e.insertBefore(t,this.nextSibling):t}function nt(){var t=this.cloneNode(!0),e=this.parentNode;return e?e.insertBefore(t,this.nextSibling):t}var rt={},it=null;"undefined"!=typeof document&&("onmouseenter"in document.documentElement||(rt={mouseenter:"mouseover",mouseleave:"mouseout"}));function ot(t,e,n){return t=at(t,e,n),function(e){var n=e.relatedTarget;n&&(n===this||8&n.compareDocumentPosition(this))||t.call(this,e)}}function at(t,e,n){return function(r){var i=it;it=r;try{t.call(this,this.__data__,e,n)}finally{it=i}}}function st(t){return t.trim().split(/^|\s+/).map((function(t){var e="",n=t.indexOf(".");return n>=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function ut(t){return function(){var e=this.__on;if(e){for(var n,r=0,i=-1,o=e.length;r=k&&(k=x+1);!(b=_[k])&&++k=0;)(r=i[o])&&(a&&4^r.compareDocumentPosition(a)&&a.parentNode.insertBefore(r,a),a=r);return this},sort:function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=d);for(var n=this._groups,r=n.length,i=new Array(r),o=0;o1?this.each((null==e?N:"function"==typeof e?S:O)(t,e,null==n?"":n)):P(this.node(),t)},property:function(t,e){return arguments.length>1?this.each((null==e?A:"function"==typeof e?z:M)(t,e)):this.node()[t]},classed:function(t,e){var n=j(t+"");if(arguments.length<2){for(var r=D(this.node()),i=-1,o=n.length;++i=0&&(n=t.slice(r+1),t=t.slice(0,r)),t&&!e.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))}function Nt(t,e){for(var n,r=0,i=t.length;r0)for(var n,r,i=new Array(n),o=0;o=0&&e._call.call(null,t),e=e._next;--Ut}()}finally{Ut=0,function(){var t,e,n=Bt,r=1/0;for(;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:Bt=e);Ct=t,ne(r)}(),Vt=0}}function ee(){var t=Yt.now(),e=t-$t;e>1e3&&(Xt-=e,$t=t)}function ne(t){Ut||(Ft&&(Ft=clearTimeout(Ft)),t-Vt>24?(t<1/0&&(Ft=setTimeout(te,t-Yt.now()-Xt)),Ht&&(Ht=clearInterval(Ht))):(Ht||($t=Yt.now(),Ht=setInterval(ee,1e3)),Ut=1,Zt(te)))}Qt.prototype=Jt.prototype={constructor:Qt,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?Wt():+n)+(null==e?0:+e),this._next||Ct===this||(Ct?Ct._next=this:Bt=this,Ct=this),this._call=t,this._time=n,ne()},stop:function(){this._call&&(this._call=null,this._time=1/0,ne())}};var re=function(t,e,n){var r=new Qt;return e=null==e?0:+e,r.restart((function(n){r.stop(),t(n+e)}),e,n),r},ie=St("start","end","cancel","interrupt"),oe=[],ae=function(t,e,n,r,i,o){var a=t.__transition;if(a){if(n in a)return}else t.__transition={};!function(t,e,n){var r,i=t.__transition;function o(u){var l,c,h,f;if(1!==n.state)return s();for(l in i)if((f=i[l]).name===n.name){if(3===f.state)return re(o);4===f.state?(f.state=6,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[l]):+l0)throw new Error("too late; already scheduled");return n}function ue(t,e){var n=le(t,e);if(n.state>3)throw new Error("too late; already running");return n}function le(t,e){var n=t.__transition;if(!n||!(n=n[e]))throw new Error("transition not found");return n}var ce,he,fe,pe,de=function(t,e){var n,r,i,o=t.__transition,a=!0;if(o){for(i in e=null==e?null:e+"",o)(n=o[i]).name===e?(r=n.state>2&&n.state<5,n.state=6,n.timer.stop(),n.on.call(r?"interrupt":"cancel",t,t.__data__,n.index,n.group),delete o[i]):a=!1;a&&delete t.__transition}},ge=function(t,e){return t=+t,e=+e,function(n){return t*(1-n)+e*n}},ve=180/Math.PI,ye={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1},me=function(t,e,n,r,i,o){var a,s,u;return(a=Math.sqrt(t*t+e*e))&&(t/=a,e/=a),(u=t*n+e*r)&&(n-=t*u,r-=e*u),(s=Math.sqrt(n*n+r*r))&&(n/=s,r/=s,u/=s),t*r180?e+=360:e-t>180&&(t+=360),o.push({i:n.push(i(n)+"rotate(",null,r)-2,x:ge(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(o.rotate,a.rotate,s,u),function(t,e,n,o){t!==e?o.push({i:n.push(i(n)+"skewX(",null,r)-2,x:ge(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(o.skewX,a.skewX,s,u),function(t,e,n,r,o,a){if(t!==n||e!==r){var s=o.push(i(o)+"scale(",null,",",null,")");a.push({i:s-4,x:ge(t,n)},{i:s-2,x:ge(e,r)})}else 1===n&&1===r||o.push(i(o)+"scale("+n+","+r+")")}(o.scaleX,o.scaleY,a.scaleX,a.scaleY,s,u),o=a=null,function(t){for(var e,n=-1,r=u.length;++n>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?Fe(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?Fe(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=ze.exec(t))?new Ve(e[1],e[2],e[3],1):(e=je.exec(t))?new Ve(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=De.exec(t))?Fe(e[1],e[2],e[3],e[4]):(e=Be.exec(t))?Fe(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=Ce.exec(t))?We(e[1],e[2]/100,e[3]/100,1):(e=Ie.exec(t))?We(e[1],e[2]/100,e[3]/100,e[4]):Le.hasOwnProperty(t)?Ue(Le[t]):"transparent"===t?new Ve(NaN,NaN,NaN,0):null}function Ue(t){return new Ve(t>>16&255,t>>8&255,255&t,1)}function Fe(t,e,n,r){return r<=0&&(t=e=n=NaN),new Ve(t,e,n,r)}function He(t){return t instanceof Oe||(t=qe(t)),t?new Ve((t=t.rgb()).r,t.g,t.b,t.opacity):new Ve}function $e(t,e,n,r){return 1===arguments.length?He(t):new Ve(t,e,n,null==r?1:r)}function Ve(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function Xe(){return"#"+Ze(this.r)+Ze(this.g)+Ze(this.b)}function Ye(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function Ze(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function We(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new Qe(t,e,n,r)}function Ke(t){if(t instanceof Qe)return new Qe(t.h,t.s,t.l,t.opacity);if(t instanceof Oe||(t=qe(t)),!t)return new Qe;if(t instanceof Qe)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),o=Math.max(e,n,r),a=NaN,s=o-i,u=(o+i)/2;return s?(a=e===o?(n-r)/s+6*(n0&&u<1?0:a,new Qe(a,s,u,t.opacity)}function Qe(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function Je(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}function tn(t,e,n,r,i){var o=t*t,a=o*t;return((1-3*t+3*o-a)*e+(4-6*o+3*a)*n+(1+3*t+3*o-3*a)*r+a*i)/6}Te(Oe,qe,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:Re,formatHex:Re,formatHsl:function(){return Ke(this).formatHsl()},formatRgb:Ge,toString:Ge}),Te(Ve,$e,Ne(Oe,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new Ve(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new Ve(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:Xe,formatHex:Xe,formatRgb:Ye,toString:Ye})),Te(Qe,(function(t,e,n,r){return 1===arguments.length?Ke(t):new Qe(t,e,n,null==r?1:r)}),Ne(Oe,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new Qe(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new Qe(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new Ve(Je(t>=240?t-240:t+120,i,r),Je(t,i,r),Je(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));var en=function(t){return function(){return t}};function nn(t,e){return function(n){return t+n*e}}function rn(t){return 1==(t=+t)?on:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):en(isNaN(e)?n:e)}}function on(t,e){var n=e-t;return n?nn(t,n):en(isNaN(t)?e:t)}var an=function t(e){var n=rn(e);function r(t,e){var r=n((t=$e(t)).r,(e=$e(e)).r),i=n(t.g,e.g),o=n(t.b,e.b),a=on(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=o(e),t.opacity=a(e),t+""}}return r.gamma=t,r}(1);function sn(t){return function(e){var n,r,i=e.length,o=new Array(i),a=new Array(i),s=new Array(i);for(n=0;n=1?(n=1,e-1):Math.floor(n*e),i=t[r],o=t[r+1],a=r>0?t[r-1]:2*i-o,s=ro&&(i=e.slice(o,i),s[a]?s[a]+=i:s[++a]=i),(n=n[0])===(r=r[0])?s[a]?s[a]+=r:s[++a]=r:(s[++a]=null,u.push({i:a,x:ge(n,r)})),o=ln.lastIndex;return o=0&&(t=t.slice(0,e)),!t||"start"===t}))}(e)?se:ue;return function(){var a=o(this,t),s=a.on;s!==r&&(i=(r=s).copy()).on(e,n),a.on=i}}var Sn=yt.prototype.constructor;function Pn(t){return function(){this.style.removeProperty(t)}}function An(t,e,n){return function(r){this.style.setProperty(t,e.call(this,r),n)}}function Mn(t,e,n){var r,i;function o(){var o=e.apply(this,arguments);return o!==i&&(r=(i=o)&&An(t,o,n)),r}return o._value=e,o}function zn(t){return function(e){this.textContent=t.call(this,e)}}function jn(t){var e,n;function r(){var r=t.apply(this,arguments);return r!==n&&(e=(n=r)&&zn(r)),e}return r._value=t,r}var Dn=0;function Bn(t,e,n,r){this._groups=t,this._parents=e,this._name=n,this._id=r}function Cn(){return++Dn}var In=yt.prototype;Bn.prototype=function(t){return yt().transition(t)}.prototype={constructor:Bn,select:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=a(t));for(var r=this._groups,i=r.length,o=new Array(i),s=0;sr?(r+i)/2:Math.min(0,r)||Math.max(0,i),a>o?(o+a)/2:Math.min(0,o)||Math.max(0,a))}var Qn=function(t){return function(){return t}};function Jn(t,e,n,r,i,o,a,s,u,l){this.target=t,this.type=e,this.subject=n,this.identifier=r,this.active=i,this.x=o,this.y=a,this.dx=s,this.dy=u,this._=l}function tr(){return!it.ctrlKey&&!it.button}function er(){return this.parentNode}function nr(t){return null==t?{x:it.x,y:it.y}:t}function rr(){return navigator.maxTouchPoints||"ontouchstart"in this}Jn.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};var ir=function(){var t,e,n,r,i=tr,o=er,a=nr,s=rr,u={},l=St("start","drag","end"),c=0,h=0;function f(t){t.on("mousedown.drag",p).filter(s).on("touchstart.drag",v).on("touchmove.drag",y).on("touchend.drag touchcancel.drag",m).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function p(){if(!r&&i.apply(this,arguments)){var a=_("mouse",o.apply(this,arguments),Gt,this,arguments);a&&(mt(it.view).on("mousemove.drag",d,!0).on("mouseup.drag",g,!0),Mt(it.view),Pt(),n=!1,t=it.clientX,e=it.clientY,a("start"))}}function d(){if(At(),!n){var r=it.clientX-t,i=it.clientY-e;n=r*r+i*i>h}u.mouse("drag")}function g(){mt(it.view).on("mousemove.drag mouseup.drag",null),zt(it.view,n),At(),u.mouse("end")}function v(){if(i.apply(this,arguments)){var t,e,n=it.changedTouches,r=o.apply(this,arguments),a=n.length;for(t=0;t1e-6)if(Math.abs(c*s-u*l)>1e-6&&i){var f=n-o,p=r-a,d=s*s+u*u,g=f*f+p*p,v=Math.sqrt(d),y=Math.sqrt(h),m=i*Math.tan((or-Math.acos((d+h-g)/(2*v*y)))/2),_=m/y,w=m/v;Math.abs(_-1)>1e-6&&(this._+="L"+(t+_*l)+","+(e+_*c)),this._+="A"+i+","+i+",0,0,"+ +(c*f>l*p)+","+(this._x1=t+w*s)+","+(this._y1=e+w*u)}else this._+="L"+(this._x1=t)+","+(this._y1=e);else;},arc:function(t,e,n,r,i,o){t=+t,e=+e,o=!!o;var a=(n=+n)*Math.cos(r),s=n*Math.sin(r),u=t+a,l=e+s,c=1^o,h=o?r-i:i-r;if(n<0)throw new Error("negative radius: "+n);null===this._x1?this._+="M"+u+","+l:(Math.abs(this._x1-u)>1e-6||Math.abs(this._y1-l)>1e-6)&&(this._+="L"+u+","+l),n&&(h<0&&(h=h%ar+ar),h>sr?this._+="A"+n+","+n+",0,1,"+c+","+(t-a)+","+(e-s)+"A"+n+","+n+",0,1,"+c+","+(this._x1=u)+","+(this._y1=l):h>1e-6&&(this._+="A"+n+","+n+",0,"+ +(h>=or)+","+c+","+(this._x1=t+n*Math.cos(i))+","+(this._y1=e+n*Math.sin(i))))},rect:function(t,e,n,r){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)+"h"+ +n+"v"+ +r+"h"+-n+"Z"},toString:function(){return this._}};var cr=lr,hr=function(t){return function(){return t}};function fr(t){this._context=t}fr.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:this._context.lineTo(t,e)}}};var pr=function(t){return new fr(t)};function dr(t){return t[0]}function gr(t){return t[1]}var vr=n(1),yr=n.n(vr),mr={entityStateReadOnly:{ACTIVE:!1,DELETED:!0,STATUS_ACTIVE:!1,STATUS_DELETED:!0}},_r={nodeArrowDistance:24,refreshGraphForSafari:function(t){t.edgeEl.each((function(t){var e=this,n=$(this).find("pattern");setTimeout((function(t){$(e).find("defs").append(n)}),500)}))},refreshGraphForIE:function(t){var e=t.edgePathEl,n=0;e.each((function(t){var e=$(this).find("marker");$(this).find("marker").remove();var r=this;++n,setTimeout((function(t){$(r).find("defs").append(e),0===--n&&(this.$(".fontLoader").hide(),this.$("svg").fadeTo(1e3,1))}),1e3)}))},dragNode:function(t){var e=this,n=t.g,r=t.svg,i=t.guid,o=(t.edgePathEl,{dragmove:function(t,e){var r=this,i=mt(t),o=n.node(e),a=o.x,s=o.y;o.x+=it.dx,o.y+=it.dy,i.attr("transform","translate("+o.x+","+o.y+")");var u=o.x-a,l=o.y-s;n.edges().forEach((function(t){if(t.v==e||t.w==e){var i=n.edge(t.v,t.w);r.translateEdge(i,u,l),mt(i.elem).select("path").attr("d",r.calcPoints(t))}}))},translateEdge:function(t,e,n){t.points.forEach((function(t){t.x=t.x+e,t.y=t.y+n}))},calcPoints:function(t){var e=n.edge(t.v,t.w),r=n.node(t.v),i=n.node(t.w),o=e.points.slice(1,e.points.length-1);e.points.slice(1,e.points.length-1);return o.unshift(this.intersectRect(r,o[0])),o.push(this.intersectRect(i,o[o.length-1])),function(){var t=dr,e=gr,n=hr(!0),r=null,i=pr,o=null;function a(a){var s,u,l,c=a.length,h=!1;for(null==r&&(o=i(l=cr())),s=0;s<=c;++s)!(sMath.abs(a)*c?(s<0&&(c=-c),h=0===s?0:c*a/s,f=c):(a<0&&(l=-l),h=l,f=0===a?0:l*s/a),{x:r+h,y:o+f}}}),a=ir().on("drag",(function(t){o.dragmove.call(o,this,t)})),s=ir().on("drag",(function(t){o.translateEdge(n.edge(t.v,t.w),it.dx,it.dy);var e=n.edge(t.v,t.w);mt(e.elem).select("path").attr("d",o.calcPoints(t))}));a(r.selectAll("g.node")),s(r.selectAll("g.edgePath"))},zoomIn:function(t){var e=t.svg,n=t.scaleFactor,r=void 0===n?1.3:n;this.d3Zoom.scaleBy(e.transition().duration(750),r)},zoomOut:function(t){var e=t.svg,n=t.scaleFactor,r=void 0===n?.8:n;this.d3Zoom.scaleBy(e.transition().duration(750),r)},zoom:function(t){var e=t.svg,n=t.xa,r=t.ya,i=t.scale;e.transition().duration(750).call(this.d3Zoom.transform,Fn.translate(n,r).scale(i))},fitToScreen:function(t){var e=t.svg,n=e.node(),r=n.getBBox(),i=n.parentElement,o=i.clientWidth,a=i.clientHeight,s=r.width,u=r.height,l=r.x+s/2,c=r.y+u/2,h=(h||.95)/Math.max(s/o,u/a),f=o/2-h*l,p=a/2-h*c;this.zoom({svg:e,xa:f,ya:p,scale:h})},centerNode:function(t){var e=t.guid,n=t.g,r=t.svg,i=t.svgGroupEl,o=(t.edgePathEl,t.width),a=t.height,s=t.fitToScreen,u=t.onCenterZoomed,l=t.isSelected;this.d3Zoom=function(){var t,e,n=Vn,r=Xn,i=Kn,o=Zn,a=Wn,s=[0,1/0],u=[[-1/0,-1/0],[1/0,1/0]],l=250,c=It,h=St("start","zoom","end"),f=0;function p(t){t.property("__zoom",Yn).on("wheel.zoom",w).on("mousedown.zoom",b).on("dblclick.zoom",x).filter(a).on("touchstart.zoom",k).on("touchmove.zoom",E).on("touchend.zoom touchcancel.zoom",T).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function d(t,e){return(e=Math.max(s[0],Math.min(s[1],e)))===t.k?t:new Un(e,t.x,t.y)}function g(t,e,n){var r=e[0]-n[0]*t.k,i=e[1]-n[1]*t.k;return r===t.x&&i===t.y?t:new Un(t.k,r,i)}function v(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}function y(t,e,n){t.on("start.zoom",(function(){m(this,arguments).start()})).on("interrupt.zoom end.zoom",(function(){m(this,arguments).end()})).tween("zoom",(function(){var t=this,i=arguments,o=m(t,i),a=r.apply(t,i),s=null==n?v(a):"function"==typeof n?n.apply(t,i):n,u=Math.max(a[1][0]-a[0][0],a[1][1]-a[0][1]),l=t.__zoom,h="function"==typeof e?e.apply(t,i):e,f=c(l.invert(s).concat(u/l.k),h.invert(s).concat(u/h.k));return function(t){if(1===t)t=h;else{var e=f(t),n=u/e[2];t=new Un(n,s[0]-e[0]*n,s[1]-e[1]*n)}o.zoom(null,t)}}))}function m(t,e,n){return!n&&t.__zooming||new _(t,e)}function _(t,e){this.that=t,this.args=e,this.active=0,this.extent=r.apply(t,e),this.taps=0}function w(){if(n.apply(this,arguments)){var t=m(this,arguments),e=this.__zoom,r=Math.max(s[0],Math.min(s[1],e.k*Math.pow(2,o.apply(this,arguments)))),a=Gt(this);if(t.wheel)t.mouse[0][0]===a[0]&&t.mouse[0][1]===a[1]||(t.mouse[1]=e.invert(t.mouse[0]=a)),clearTimeout(t.wheel);else{if(e.k===r)return;t.mouse=[a,e.invert(a)],de(this),t.start()}$n(),t.wheel=setTimeout(l,150),t.zoom("mouse",i(g(d(e,r),t.mouse[0],t.mouse[1]),t.extent,u))}function l(){t.wheel=null,t.end()}}function b(){if(!e&&n.apply(this,arguments)){var t=m(this,arguments,!0),r=mt(it.view).on("mousemove.zoom",l,!0).on("mouseup.zoom",c,!0),o=Gt(this),a=it.clientX,s=it.clientY;Mt(it.view),Hn(),t.mouse=[o,this.__zoom.invert(o)],de(this),t.start()}function l(){if($n(),!t.moved){var e=it.clientX-a,n=it.clientY-s;t.moved=e*e+n*n>f}t.zoom("mouse",i(g(t.that.__zoom,t.mouse[0]=Gt(t.that),t.mouse[1]),t.extent,u))}function c(){r.on("mousemove.zoom mouseup.zoom",null),zt(it.view,t.moved),$n(),t.end()}}function x(){if(n.apply(this,arguments)){var t=this.__zoom,e=Gt(this),o=t.invert(e),a=t.k*(it.shiftKey?.5:2),s=i(g(d(t,a),e,o),r.apply(this,arguments),u);$n(),l>0?mt(this).transition().duration(l).call(y,s,e):mt(this).call(p.transform,s)}}function k(){if(n.apply(this,arguments)){var e,r,i,o,a=it.touches,s=a.length,u=m(this,arguments,it.changedTouches.length===s);for(Hn(),r=0;rg[id='"+e+"']"),h=(this.d3Zoom.scaleExtent([.01,50]).on("zoom",(function(){i.attr("transform",it.transform)})),null),f=null;if(c.empty()){if(s)return void this.fitToScreen({svg:r});h=n.graph().width/2,f=n.graph().height/2}else{var p=c.attr("transform").replace(/[^0-9\-.,]/g,"").split(",");h=p[0],f=p[1]}var d=-(1.2*h-o/2),g=-(1.2*f-a/2);this.zoom({svg:r,xa:d,ya:g,scale:1.2}),l?r.transition().duration(750).call(this.d3Zoom.transform,Fn.translate(d,g).scale(1.2)):r.call(this.d3Zoom.transform,Fn.translate(d,g).scale(1.2)),u&&u({newScale:1.2,newTranslate:[d,g],d3Zoom:this.d3Zoom,selectedNodeEl:c})},getToolTipDirection:function(t){var e=t.el,n=mt("body").node().getBoundingClientRect().width,r=mt(e).node().getBoundingClientRect(),i="e";return n-r.left<330?(i=n-r.left<330&&r.top<400?"sw":"w",n-r.left<330&&r.top>600&&(i="nw")):r.top>600?(i=n-r.left<330&&r.top>600?"nw":"n",r.left<50&&(i="ne")):r.top<400&&(i=r.left<50?"se":"s"),i},onHoverFade:function(t){var e=t.svg,n=t.g,r=t.mouseenter,i=t.nodesToHighlight,o=t.hoveredNode;return function(t){var i=e.selectAll(".node"),a=e.selectAll(".edgePath");if(r){e.classed("hover",!0);var s=n.successors(o),u=n.predecessors(o);t=s.concat(u);i.classed("hover-active-node",(function(e,n,r){return!!function(t,e,n){if(t===n||e&&e.length&&-1!=e.indexOf(n))return!0}(o,t,e)})),a.classed("hover-active-path",(function(t){return!!(t.v===o||t.w===o?1:0)}))}else e.classed("hover",!1),i.classed("hover-active-node",!1),a.classed("hover-active-path",!1)}(i)},getBaseUrl:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:window.location.pathname;return t.replace(/\/[\w-]+.(jsp|html)|\/+$/gi,"")},getEntityIconPath:function(t){var e=t.entityData,n=t.errorUrl,r=t.imgBasePath,i=this.getBaseUrl()+(r||"/img/entity-icon/");if(e){var o=function(t){return i+(mr.entityStateReadOnly[l]?"disabled/"+t:t)},a=function(){return c?mr.entityStateReadOnly[l]?i+"disabled/process.png":i+"process.png":mr.entityStateReadOnly[l]?i+"disabled/table.png":i+"table.png"},s=e.typeName,u=e.serviceType,l=e.status,c=e.isProcess;if(n){if(n.indexOf("table.png")>-1||n.indexOf("process.png")>-1)return null;var h=!(!n||!n.match("entity-icon/"+s+".png|disabled/"+s+".png"));return u&&h?o(u+".png"):a()}return s?o(s+".png"):u?o(u+".png"):a()}},base64Encode:function(t,e){var n=new FileReader;n.addEventListener("load",(function(){return e(n.result)})),n.readAsDataURL(t)},imgShapeRender:function(t,e,n,r){var i=r.dagreD3,o=r.defsEl,a=r.imgBasePath,s=r.guid,u=r.isRankdirToBottom,l=this,c=s,h=this.getEntityIconPath({entityData:n,imgBasePath:a}),f=h.split("/").pop();if(void 0===this.imageObject&&(this.imageObject={}),n.isDeleted&&(f="deleted_"+f),n.id==c)var p=!0;var d=t.append("circle").attr("fill","url(#img_"+f+")").attr("r",u?"30px":"24px").attr("data-stroke",n.id).attr("stroke-width","2px").attr("class","nodeImage "+(p?"currentNode":n.isProcess?"process":"node"));if(p&&d.attr("stroke","#fb4200"),!0===n.isIncomplete){t.attr("class","node isIncomplete show"),t.insert("rect").attr("x","-5").attr("y","-23").attr("width","14").attr("height","16").attr("fill","url(#img_hourglass.svg)").attr("data-stroke",n.id).attr("stroke-width","2px");g({imgName:"hourglass.svg",imageIconPath:"/img/entity-icon/hourglass.svg",leftPosition:"0",topPosition:"0",width:"12",height:"14"})}function g(t){o.select('pattern[id="img_'+t.imgName+'"]').empty()&&o.append("pattern").attr("x","0%").attr("y","0%").attr("patternUnits","objectBoundingBox").attr("id","img_"+t.imgName).attr("width","100%").attr("height","100%").append("image").attr("href",(function(e){var r=this;if(n){!function e(i){var o=i.imagePath,a={url:o,method:"GET",cache:!0};d.attr("data-iconpath",o);var s=new XMLHttpRequest;s.onreadystatechange=function(){if(4===s.readyState)if(200===s.status)"IE"!==yr.a.name?l.base64Encode(this.response,(function(e){l.imageObject[t.imageIconPath]=e,mt(r).attr("xlink:href",e)})):l.imageObject[t.imageIconPath]=o,t.imageIconPath!==d.attr("data-iconpath")&&d.attr("data-iconpathorigin",t.imageIconPath);else if(404===s.status){var i=l.getEntityIconPath({entityData:n,errorUrl:o});if(null===i){var a=mt(r.parentElement);a.select("image").remove(),a.attr("patternContentUnits","objectBoundingBox").append("circle").attr("r","24px").attr("fill","#e8e8e8")}else e({imagePath:i})}},s.responseType="blob",s.open(a.method,a.url,!0),s.send(null)}({imagePath:t.imageIconPath})}})).attr("x",t.leftPosition).attr("y",t.topPosition).attr("width",t.width).attr("height",t.height)}return g({imgName:f,imageIconPath:h,leftPosition:u?"11":"4",topPosition:u?"20":p?"3":"4",width:"40",height:"40"}),n.intersect=function(t){return i.intersect.circle(n,p?l.nodeArrowDistance+3:l.nodeArrowDistance,t)},d},arrowPointRender:function(t,e,n,r,i){var o=i.dagreD3,a=t.node(),s=a?a.parentNode:t;mt(s).select("path.path").attr("marker-end","url(#"+e+")");var u=t.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",8).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",4).attr("markerHeight",4).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z").style("fill",n.styleObj.stroke);o.util.applyStyle(u,n[r+"Style"])},saveSvg:function(t){var e=t.svg,n=t.width,r=t.height,i=t.downloadFileName,o=t.onExportLineage,a=this,s=e.clone(!0).node();setTimeout((function(){"Firefox"===yr.a.name&&(s.setAttribute("width",n),s.setAttribute("height",r));var t=mt("body").append("div");t.classed("hidden-svg",!0),t.node().appendChild(s);var e=mt(".hidden-svg svg");e.select("g").attr("transform","scale(1)"),e.select("foreignObject").remove();var u=150,l=150,c=s.getBBox().width+u,h=s.getBBox().height+l,f=s.getBBox().x,p=s.getBBox().y;s.attributes.viewBox.value=f+","+p+","+c+","+h;var d=document.createElement("canvas");d.id="canvas",d.style.display="none",d.width=1*s.getBBox().width+u,d.height=1*s.getBBox().height+l,mt("body").node().appendChild(d);var g=d.getContext("2d"),v=(new XMLSerializer).serializeToString(s),y=window.URL||window.webkitURL||window;g.fillStyle="#FFFFFF",g.fillRect(0,0,d.width,d.height),g.strokeRect(0,0,d.width,d.height),g.restore();var m=new Image(d.width,d.height),_=new Blob([v],{type:"image/svg+xml;base64"});"Safari"===yr.a.name&&(_=new Blob([v],{type:"image/svg+xml"})),g.drawImage(m,50,50,d.width,d.height);var w=y.createObjectURL(_);m.onload=function(){try{var e=document.createElement("a");e.download=i,document.body.appendChild(e),g.drawImage(m,50,50,d.width,d.height),d.toBlob((function(t){t?(e.href=y.createObjectURL(t),t.size>1e7&&o({status:"failed",message:"The Image size is huge, please open the image in a browser!"}),e.click(),o({status:"Success",message:"Successful"}),"Safari"===yr.a.name&&a.refreshGraphForSafari({edgeEl:a.$("svg g.node")})):o({status:"failed",message:"There was an error in downloading Lineage!"})}),"image/png"),t.remove(),d.remove()}catch(t){o({status:"failed",message:"There was an error in downloading Lineage!"})}},m.src=w}),0)}};function wr(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function br(t){for(var e=1;e0&&void 0!==arguments[0]?arguments[0]:{},i=r.entityData,o=r.errorUrl,a=this.getBaseUrl(window.location.pathname)+Globals.entityImgPath;function s(t){return a+(mr.entityStateReadOnly[e]?"disabled/"+t:t)}function u(){return i.isProcess?mr.entityStateReadOnly[e]?a+"disabled/process.png":a+"process.png":mr.entityStateReadOnly[e]?a+"disabled/table.png":a+"table.png"}if(i&&(n=i.typeName,t=i&&i.serviceType,e=i&&i.status),i){if(o){var l=!(!o||!o.match("entity-icon/"+n+".png|disabled/"+n+".png"));return t&&l?s(t+".png"):u()}return i.typeName?s(i.typeName+".png"):u()}},isProcess:function(t){var e=t.typeName,n=t.superTypes;t.entityDef;return"Process"==e||n.indexOf("Process")>-1},isDeleted:function(t){if(void 0!==t)return mr.entityStateReadOnly[t.status]},isNodeToBeUpdated:function(t,e){var n=e.isProcessHideCheck,r=e.isDeletedEntityHideCheck,i={isProcess:n&&t.isProcess,isDeleted:r&&t.isDeleted};return i.update=i.isProcess||i.isDeleted,i},getServiceType:function(t){var e=t.typeName,n=t.entityDef,r=null;return e&&n&&(r=n.serviceType||null),r},getEntityDef:function(t){var e=t.typeName,n=t.entityDefCollection,r=null;return e&&(r=n.find((function(t){return t.name==e}))),r},getNestedSuperTypes:function(t){var e=t.entityDef,n=t.entityDefCollection,r=new Set;return function t(e,n){e&&e.superTypes&&e.superTypes.length&&e.superTypes.forEach((function(e){r.add(e);var i=n.find((function(t){t.name}));i&&t(i,n)}))}(e,n),Array.from(r)},generateData:function(t){var e=this,n=t.data,r=void 0===n?{}:n,i=t.filterObj,o=t.entityDefCollection,a=t.g,s=t.guid,u=t.setGraphEdge,l=t.setGraphNode;return new Promise((function(t,n){try{var c=r.relations||{},h=r.guidEntityMap||{},f=i.isProcessHideCheck||i.isDeletedEntityHideCheck,p={fill:"none",stroke:"#ffb203",width:3},d=function(t){if(t){if(t.updatedValues)return t;var n=t.displayText?t.displayText:" ",r=Object.assign(t,{shape:"img",updatedValues:!0,label:n.trunc(18),toolTipLabel:n,id:t.guid,isLineage:!0,isIncomplete:t.isIncomplete,entityDef:e.getEntityDef({typeName:t.typeName,entityDefCollection:o})});return r.serviceType=e.getServiceType(r),r.superTypes=e.getNestedSuperTypes(br(br({},r),{},{entityDefCollection:o})),r.isProcess=e.isProcess(r),r.isDeleted=e.isDeleted(r),r}},g=function(t){return"fill:"+t.fill+";stroke:"+t.stroke+";stroke-width:"+t.width},v=function(t,n,r){var i=[];return t.forEach((function(t){if(e.isNodeToBeUpdated(d(h[t]),r).update)if(w[t])i=i.concat(w[t]);else{var n=function t(n,r){if(n&&b[n]){var i=[];return b[n].forEach((function(n){if(e.isNodeToBeUpdated(d(h[n]),r).update){var o=t(n,r);o&&(i=i.concat(o))}else i.push(n)})),i}return null}(t,r);n&&(i=i.concat(n))}else i.push(t)})),i},y=function(t){if(a._nodes[t])return a._nodes[t];var e=d(h[t]);return l(t,e),e},m=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};u(t,e,br({arrowhead:"arrowPoint",curve:bt,style:g(p),styleObj:p},n))},_=function(t,e){y(t),y(e),m(t,e)},w={};if(f){var b=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.relations,n={};return e.forEach((function(t){n[t.fromEntityId]?n[t.fromEntityId].push(t.toEntityId):n[t.fromEntityId]=[t.toEntityId]})),n}(r);Object.keys(b).forEach((function(t){var n=b[t],r=e.isNodeToBeUpdated(d(h[t]),i),o=v(n,0,i);r.update?w[t]?w[t]=w[t].concat(o):w[t]=o:o.forEach((function(e){_(t,e)}))}))}else c.length?c.forEach((function(t){_(t.fromEntityId,t.toEntityId)})):y(s);a._nodes[s]&&(a._nodes[s]&&(a._nodes[s].isLineage=!1),e.findImpactNodeAndUpdateData({guid:s,g:a,setEdge:m,getStyleObjStr:g})),t(a)}catch(t){n(t)}}))},findImpactNodeAndUpdateData:function(t){var e=t.guid,n=t.getStyleObjStr,r=t.g,i=t.setEdge,o={},a={fill:"none",stroke:"#fb4200",width:3};!function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},s=arguments.length>1?arguments[1]:void 0,u=Object.keys(e);u.length&&(o[s]||(o[s]=!0,u.forEach((function(e){r._nodes[e]&&(r._nodes[e].isLineage=!1),i(s,e,{style:n(a),styleObj:a}),t(r._sucs[e],e)}))))}(r._sucs[e],e)}};String.prototype.trunc=String.prototype.trunc||function(t){return this.length>t?this.substr(0,t-1)+"...":this};function Er(){}function Tr(t,e){var n=new Er;if(t instanceof Er)t.each((function(t,e){n.set(e,t)}));else if(Array.isArray(t)){var r,i=-1,o=t.length;if(null==e)for(;++i0&&void 0!==arguments[0]?arguments[0]:{};return n._createGraph(n.options,n.graphOptions,t)},clear:function(t){return n.clear(t)},refresh:function(t){return n.refresh(t)},centerAlign:function(t){return n.centerAlign(t)},exportLineage:function(t){return n.exportLineage(t)},zoomIn:function(t){return n.zoomIn(t)},zoomOut:function(t){return n.zoomOut(t)},zoom:function(t){return n.zoom(t)},fullScreen:function(t){return n.fullScreen(t)},searchNode:function(t){return n.searchNode(t)},displayFullName:function(t){return n.displayFullName(t)},removeNodeSelection:function(t){return n.removeNodeSelection(t)},getGraphOptions:function(){return n.graphOptions},getNode:function(t,e){var r=null;return(r=e?n.actualData[t]:n.g._nodes[t])&&(r=Object.assign({},r)),r},getNodes:function(t,e){var r=null;return(r=e?n.actualData:n.g._nodes)&&(r=Object.assign({},r)),r},setNode:this._setGraphNode,setEdge:this._setGraphEdge},!1===a&&this.init(),this.initReturnObj}var e,n,r;return e=t,(n=[{key:"_updateAllOptions",value:function(t){Object.assign(this.options,t);var e=this.svg.node().getBoundingClientRect();this.graphOptions.width=this.options.width||e.width,this.graphOptions.height=this.options.height||e.height;var n=this.graphOptions,r=n.svg,i=n.width,o=n.height,a=n.guid,s=this.options.fitToScreen;r.select("g").node().removeAttribute("transform"),r.attr("viewBox","0 0 "+i+" "+o).attr("enable-background","new 0 0 "+i+" "+o),this.centerAlign({fitToScreen:s,guid:a})}},{key:"_updateOptions",value:function(t){Object.assign(this.options,{filterObj:{isProcessHideCheck:!1,isDeletedEntityHideCheck:!1}},t)}},{key:"init",value:function(){var t=this.options.data,e=void 0===t?{}:t;e.baseEntityGuid&&(this.guid=e.baseEntityGuid),this._initializeGraph(),this._initGraph()}},{key:"clear",value:function(){this.options.el||(this.svg.remove(),this.svg=null),this.g=null,this.graphOptions={}}},{key:"centerAlign",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=this.svg.select("g"),n=e.selectAll("g.edgePath");_r.centerNode(zr(zr({},this.graphOptions),{},{svgGroupEl:e,edgePathEl:n},t))}},{key:"zoomIn",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};_r.zoomIn(zr(zr({},this.graphOptions),t))}},{key:"zoomOut",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};_r.zoomOut(zr(zr({},this.graphOptions),t))}},{key:"zoom",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};_r.zoom(zr(zr({},this.graphOptions),t))}},{key:"displayFullName",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=this;this.g.nodes().forEach((function(n){var r=e.svg.selectAll("g.nodes>g[id='"+n+"']"),i=e.g.node(n).toolTipLabel;1==t.bLabelFullText?r.select("tspan").text(i):r.select("tspan").text(i.trunc(18))})),this.selectedNode&&this.searchNode({guid:this.selectedNode})}},{key:"refresh",value:function(){this.clear(),this._initializeGraph(),this._initGraph({refresh:!0}),this.selectedNode=""}},{key:"removeNodeSelection",value:function(){this.svg.selectAll("g.node>circle").classed("node-detail-highlight",!1)}},{key:"searchNode",value:function(t){var e=t.guid,n=t.onSearchNode;this.svg.selectAll(".serach-rect").remove(),this.svg.selectAll(".label").attr("stroke","none"),this.selectedNode=e,this.centerAlign({guid:e,onCenterZoomed:function(t){var e=t.selectedNodeEl,r=e.node().getBBox(),i=r.width+10,o=r.x-5;e.select(".label").attr("stroke","#316132"),e.select("circle").classed("wobble",!0),e.insert("rect","circle").attr("class","serach-rect").attr("stroke","#37bb9b").attr("stroke-width","2.5px").attr("fill","none").attr("x",o).attr("y",-27.5).attr("width",i).attr("height",60),n&&"function"==typeof n&&n(t)},isSelected:!0})}},{key:"exportLineage",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.downloadFileName;if(void 0===e){var n=this.g._nodes[this.guid];e=n&&n.attributes?"".concat(n.attributes.qualifiedName||n.attributes.name||"lineage_export",".png"):"export.png"}_r.saveSvg(zr(zr({},this.graphOptions),{},{downloadFileName:e,onExportLineage:function(t){function e(e){return t.apply(this,arguments)}return e.toString=function(){return t.toString()},e}((function(e){t.onExportLineage&&onExportLineage(e)}))}))}},{key:"fullScreen",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.el;if(void 0===e)throw new Error("LineageHelper requires el propety to apply fullScreen class");var n=mt(e);return n.classed("fullscreen-mode")?(n.classed("fullscreen-mode",!1),!1):(n.classed("fullscreen-mode",!0),!0)}},{key:"_getValueFromUser",value:function(t){if(void 0!==t)return"function"==typeof t?t():t}},{key:"_initializeGraph",value:function(){var t=this.options,e=t.width,n=void 0===e?"100%":e,r=t.height,o=void 0===r?"100%":r,a=t.el;this.svg=mt(a),a instanceof SVGElement||(this.svg.selectAll("*").remove(),this.svg=this.svg.append("svg").attr("xmlns","http://www.w3.org/2000/svg").attr(" xmlns:xlink","http://www.w3.org/1999/xlink").attr("version","1.1").attr("width",n).attr("height",o)),this.g=(new i.a.graphlib.Graph).setGraph(Object.assign({nodesep:50,ranksep:90,rankdir:"LR",marginx:20,marginy:20,transition:function(t){return t.transition().duration(500)}},this.options.dagreOptions)).setDefaultEdgeLabel((function(){return{}}));var s=this.svg.node().getBoundingClientRect();this.actualData={},this.graphOptions={svg:this.svg,g:this.g,dagreD3:i.a,guid:this.guid,width:this.options.width||s.width,height:this.options.height||s.height}}},{key:"_initGraph",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.refresh;this.svg&&this.svg.select("g").remove();var r=this.options.filterObj;if(this.options.getFilterObj){var i=this.options.getFilterObj();if(void 0!==i||null!==i){if("object"!==Ar(i))throw new Error("getFilterObj expect return type `object`,`null` or `Undefined`");r=i}}if(!0!==this.options.setDataManually)return void 0===this.options.data||this.options.data&&0===this.options.data.relations.length&&_.isEmpty(this.options.data.guidEntityMap)?(this.options.beforeRender&&this.options.beforeRender(),this.svg.append("text").attr("x","50%").attr("y","50%").attr("alignment-baseline","middle").attr("text-anchor","middle").text("No lineage data found"),void(this.options.afterRender&&this.options.afterRender())):kr.generateData(zr(zr(zr({},this.options),{},{filterObj:r},this.graphOptions),{},{setGraphNode:this._setGraphNode,setGraphEdge:this._setGraphEdge})).then((function(e){t._createGraph(t.options,t.graphOptions,{refresh:n})}))}},{key:"_createGraph",value:function(t,e,n){var r=this,o=t.data,a=void 0===o?{}:o,s=t.imgBasePath,u=t.isShowTooltip,l=t.isShowHoverPath,c=t.onLabelClick,h=t.onPathClick,f=t.onNodeClick,p=t.zoom,d=t.fitToScreen,g=t.getToolTipContent,v=t.toolTipTitle,y=n.refresh;this.options.beforeRender&&this.options.beforeRender(),this.selectedNode="";var m=this,_=e.svg,w=e.g,b=e.width,x=e.height,k=this.options.dagreOptions&&"tb"===this.options.dagreOptions.rankdir;if(_ instanceof yt==0)throw new Error("svg is not initialized or something went wrong while creatig graph instance");if(void 0!==w._nodes&&0!==w._nodes.length){w.nodes().forEach((function(t){var e=w.node(t);e&&(e.rx=e.ry=5)})),_.attr("viewBox","0 0 "+b+" "+x).attr("enable-background","new 0 0 "+b+" "+x);var E=_.append("g"),T=_.append("defs"),N=new i.a.render;N.arrows().arrowPoint=function(){return _r.arrowPointRender.apply(_r,Array.prototype.slice.call(arguments).concat([zr({},e)]))},N.shapes().img=function(){return _r.imgShapeRender.apply(_r,Array.prototype.slice.call(arguments).concat([zr(zr({},e),{},{isRankdirToBottom:k,imgBasePath:m._getValueFromUser(s),defsEl:T})]))};var O=function(){var t=function(){return"n"},e=function(){return[0,0]},n=function(){return" "},r=document.body,i=h(),o=null,a=null,s=null;function u(t){(o=function(t){var e=t.node();return e?"svg"===e.tagName.toLowerCase()?e:e.ownerSVGElement:null}(t))&&(a=o.createSVGPoint(),r.appendChild(i))}u.show=function(){var i=Array.prototype.slice.call(arguments);i[i.length-1]instanceof SVGElement&&(s=i.pop());var o,a=n.apply(this,i),h=e.apply(this,i),p=t.apply(this,i),d=f(),g=c.length,v=document.documentElement.scrollTop||r.scrollTop,y=document.documentElement.scrollLeft||r.scrollLeft;for(d.html(a).style("opacity",1).style("pointer-events","all");g--;)d.classed(c[g],!1);return o=l.get(p).apply(this),d.classed(p,!0).style("top",o.top+h[0]+v+"px").style("left",o.left+h[1]+y+"px"),u},u.hide=function(){return f().style("opacity",0).style("pointer-events","none"),u},u.attr=function(t,e){if(arguments.length<2&&"string"==typeof t)return f().attr(t);var n=Array.prototype.slice.call(arguments);return yt.prototype.attr.apply(f(),n),u},u.style=function(t,e){if(arguments.length<2&&"string"==typeof t)return f().style(t);var n=Array.prototype.slice.call(arguments);return yt.prototype.style.apply(f(),n),u},u.direction=function(e){return arguments.length?(t=null==e?e:d(e),u):t},u.offset=function(t){return arguments.length?(e=null==t?t:d(t),u):e},u.html=function(t){return arguments.length?(n=null==t?t:d(t),u):n},u.rootElement=function(t){return arguments.length?(r=null==t?t:d(t),u):r},u.destroy=function(){return i&&(f().remove(),i=null),u};var l=Nr({n:function(){var t=p(this);return{top:t.n.y-i.offsetHeight,left:t.n.x-i.offsetWidth/2}},s:function(){var t=p(this);return{top:t.s.y,left:t.s.x-i.offsetWidth/2}},e:function(){var t=p(this);return{top:t.e.y-i.offsetHeight/2,left:t.e.x}},w:function(){var t=p(this);return{top:t.w.y-i.offsetHeight/2,left:t.w.x-i.offsetWidth}},nw:function(){var t=p(this);return{top:t.nw.y-i.offsetHeight,left:t.nw.x-i.offsetWidth}},ne:function(){var t=p(this);return{top:t.ne.y-i.offsetHeight,left:t.ne.x}},sw:function(){var t=p(this);return{top:t.sw.y,left:t.sw.x-i.offsetWidth}},se:function(){var t=p(this);return{top:t.se.y,left:t.se.x}}}),c=l.keys();function h(){var t=mt(document.createElement("div"));return t.style("position","absolute").style("top",0).style("opacity",0).style("pointer-events","none").style("box-sizing","border-box"),t.node()}function f(){return null==i&&(i=h(),r.appendChild(i)),mt(i)}function p(t){for(var e=s||t;null==e.getScreenCTM&&null!=e.parentNode;)e=e.parentNode;var n={},r=e.getScreenCTM(),i=e.getBBox(),o=i.width,u=i.height,l=i.x,c=i.y;return a.x=l,a.y=c,n.nw=a.matrixTransform(r),a.x+=o,n.ne=a.matrixTransform(r),a.y+=u,n.se=a.matrixTransform(r),a.x-=o,n.sw=a.matrixTransform(r),a.y-=u/2,n.w=a.matrixTransform(r),a.x+=o,n.e=a.matrixTransform(r),a.x-=o/2,a.y-=u/2,n.n=a.matrixTransform(r),a.y+=u,n.s=a.matrixTransform(r),n}function d(t){return"function"==typeof t?t:function(){return t}}return u}().attr("class","d3-tip").offset([10,0]).html((function(t){if(g&&"function"==typeof g)return g(t,w.node(t));var e=w.node(t),n="";return v?n="
    "+v+"
    ":e.id!==r.guid&&(n="
    "+(e.isLineage?"Lineage":"Impact")+"
    "),n+="
    "+e.toolTipLabel+"
    ",e.typeName&&(n+="
    ("+e.typeName+")
    "),e.queryText&&(n+="
    Query: "+e.queryText+"
    "),"
    "+n+"
    "}));_.call(O),N(E,w),E.selectAll("g.nodes g.label").attr("transform",(function(){return k?"translate(2,-20)":"translate(2,-38)"})).attr("font-size","10px").on("mouseenter",(function(t){it.preventDefault(),mt(this).classed("highlight",!0)})).on("mouseleave",(function(t){it.preventDefault(),mt(this).classed("highlight",!1)})).on("click",(function(t){it.preventDefault(),c&&"function"==typeof c&&c({clickedData:t}),O.hide(t)})),E.selectAll("g.nodes g.node circle").on("mouseenter",(function(t,n,r){if(m.activeNode=!0,this.getScreenCTM().translate(+this.getAttribute("cx"),+this.getAttribute("cy")),m.svg.selectAll(".node").classed("active",!1),mt(this).classed("active",!0),m._getValueFromUser(u)){var i=_r.getToolTipDirection({el:this});O.direction(i).show(t,this)}!1!==m._getValueFromUser(l)&&_r.onHoverFade(zr({opacity:.3,mouseenter:!0,hoveredNode:t},e))})).on("mouseleave",(function(t){m.activeNode=!1;var n=this;setTimeout((function(e){m.activeTip||m.activeNode||(mt(n).classed("active",!1),m._getValueFromUser(u)&&O.hide(t))}),150),!1!==m._getValueFromUser(l)&&_r.onHoverFade(zr({mouseenter:!1,hoveredNode:t},e))})).on("click",(function(t){it.defaultPrevented||(it.preventDefault(),O.hide(t),_.selectAll("g.node>circle").classed("node-detail-highlight",!1),mt(this).classed("node-detail-highlight",!0),f&&"function"==typeof f&&f({clickedData:t,el:this}))}));var S=E.selectAll("g.edgePath");S.selectAll("path.path").on("click",(function(t){if(h&&"function"==typeof h){var e=a.relations.find((function(e){if(e.fromEntityId===t.v&&e.toEntityId===t.w)return!0}));h({pathRelationObj:e,clickedData:t})}})),!1!==p&&_r.centerNode(zr(zr({},e),{},{fitToScreen:d,svgGroupEl:E,edgePathEl:S})),_r.dragNode(zr(zr({},e),{},{edgePathEl:S})),!0!==y&&this._addLegend(),this.options.afterRender&&this.options.afterRender()}else _.html('No relations to display')}},{key:"_addLegend",value:function(){if(!1!==this.options.legends){var t=mt(this.options.legendsEl||this.options.el).insert("div",":first-child").classed("legends",!0),e=t.append("span").style("color","#fb4200");e.append("i").classed("fa fa-circle-o fa-fw",!0),e.append("span").html("Current Entity"),(e=t.append("span").style("color","#686868")).append("i").classed("fa fa-hourglass-half fa-fw",!0),e.append("span").html("In Progress"),(e=t.append("span").style("color","#df9b00")).append("i").classed("fa fa-long-arrow-right fa-fw",!0),e.append("span").html("Lineage"),(e=t.append("span").style("color","#fb4200")).append("i").classed("fa fa-long-arrow-right fa-fw",!0),e.append("span").html("Impact")}}}])&&Dr(e.prototype,n),r&&Dr(e,r),t}()}])})); \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/dist/styles.css b/dashboardv2/public/js/external_lib/atlas-lineage/dist/styles.css deleted file mode 100644 index 2d7f9d9de1a..00000000000 --- a/dashboardv2/public/js/external_lib/atlas-lineage/dist/styles.css +++ /dev/null @@ -1,2 +0,0 @@ -.node{cursor:pointer}.node text{font-size:10px;font-family:sans-serif}.node .label{fill:#868686}.node .label.highlight{cursor:pointer;fill:#4a90e2;text-decoration:underline}.node .label.highlight tspan{font-weight:400}.node circle{-moz-transition:all 0.3s;-webkit-transition:all 0.3s;transition:all 0.3s;stroke-width:1.5px}.node circle.node-detail-highlight{stroke:#4a90e2;stroke-width:2px}.node circle.nodeImage.green:hover{stroke:#ffb203}.node circle.nodeImage.blue:hover{stroke:#4b91e2}.node circle.nodeImage.currentNode{stroke:#fb4200}.node circle.nodeImage:hover{-moz-transform:scale(1.4);-webkit-transform:scale(1.4);transform:scale(1.4)}.node.active circle{-moz-transform:scale(1.4);-webkit-transform:scale(1.4);transform:scale(1.4)}.node.active circle.nodeImage.green{stroke:#ffb203}.node.active circle.nodeImage.blue{stroke:#4b91e2}.legends>span{margin-right:8px;font-family:Source Sans Pro}svg.hover g.node{opacity:0.1 !important}svg.hover g.edgePath{opacity:0 !important}svg.hover g.node.hover-active-node,svg.hover g.edgePath.hover-active-path{opacity:1 !important}.invisible .node circle{transition:all 0s}.edgePath .path{cursor:pointer}.link{fill:none;stroke:#ccc;stroke-width:1.5px}.text-center{text-align:center}.d3-tip{line-height:1;font-weight:bold;padding:12px;background:rgba(0,0,0,0.8);color:#fff;z-index:999;max-width:300px;border-radius:2px}.d3-tip .tip-inner-scroll{overflow:auto;max-height:300px}.d3-tip .tip-inner-scroll h5{margin:7px 0px}.d3-tip:after{box-sizing:border-box;display:inline;font-size:10px;width:100%;line-height:1;color:rgba(0,0,0,0.8);position:absolute}.d3-tip.n:after{content:"\25BC";margin:-1px 0 0 0;top:100%;left:0;text-align:center}.d3-tip.e:after{content:"\25C0";margin:-4px 0 0 0;top:50%;left:-8px}.d3-tip.s:after{content:"\25B2";margin:0 0 1px 0;top:-8px;left:0;text-align:center}.d3-tip.w:after{content:"\25B6";margin:-4px 0 0 -1px;top:50%;left:100%}g.type-TK>rect{fill:#00ffd0}.fullscreen-mode{position:fixed;height:100% !important;top:0;bottom:0;left:0;width:100%;right:0;padding:0 !important;z-index:9999;overflow:hidden !important}.fullscreen-mode .resizeGraph{position:fixed;height:100% !important}.fullscreen-mode .resizeGraph .ui-resizable-handle{display:none}.fullscreen-mode .lineage-box{padding:10px !important}.fullscreen-mode .box-panel{margin:10px !important}@keyframes zoominoutsinglefeatured{0%{transform:scale(1, 1)}50%{transform:scale(1.2, 1.2)}100%{transform:scale(1, 1)}}.wobble{animation:zoominoutsinglefeatured 1s 5}.hidden-svg{visibility:hidden}@-webkit-keyframes blink{from{opacity:0.2}to{opacity:0.5}} - diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/package-lock.json b/dashboardv2/public/js/external_lib/atlas-lineage/package-lock.json deleted file mode 100644 index 69f5a400691..00000000000 --- a/dashboardv2/public/js/external_lib/atlas-lineage/package-lock.json +++ /dev/null @@ -1,5978 +0,0 @@ -{ - "name": "atlas-lineage-module", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/compat-data": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz", - "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==", - "dev": true, - "requires": { - "browserslist": "^4.12.0", - "invariant": "^2.2.4", - "semver": "^5.5.0" - } - }, - "@babel/core": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.4.tgz", - "integrity": "sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.4", - "@babel/helper-module-transforms": "^7.11.0", - "@babel/helpers": "^7.10.4", - "@babel/parser": "^7.11.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.11.0", - "@babel/types": "^7.11.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - } - }, - "@babel/generator": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz", - "integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", - "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", - "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz", - "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.10.4", - "browserslist": "^4.12.0", - "invariant": "^2.2.4", - "levenary": "^1.1.1", - "semver": "^5.5.0" - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz", - "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-member-expression-to-functions": "^7.10.5", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.10.4" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz", - "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-regex": "^7.10.4", - "regexpu-core": "^4.7.0" - } - }, - "@babel/helper-define-map": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", - "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/types": "^7.10.5", - "lodash": "^4.17.19" - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz", - "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", - "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", - "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", - "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-module-transforms": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", - "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-simple-access": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/template": "^7.10.4", - "@babel/types": "^7.11.0", - "lodash": "^4.17.19" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", - "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", - "dev": true - }, - "@babel/helper-regex": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", - "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", - "dev": true, - "requires": { - "lodash": "^4.17.19" - } - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz", - "integrity": "sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-wrap-function": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-replace-supers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", - "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-simple-access": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", - "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", - "dev": true, - "requires": { - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz", - "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz", - "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helpers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", - "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", - "dev": true, - "requires": { - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", - "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", - "dev": true - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", - "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-remap-async-to-generator": "^7.10.4", - "@babel/plugin-syntax-async-generators": "^7.8.0" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz", - "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz", - "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-dynamic-import": "^7.8.0" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz", - "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz", - "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.0" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz", - "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz", - "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz", - "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz", - "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-transform-parameters": "^7.10.4" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz", - "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz", - "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz", - "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz", - "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz", - "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz", - "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz", - "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz", - "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-remap-async-to-generator": "^7.10.4" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz", - "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz", - "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz", - "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-define-map": "^7.10.4", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.10.4", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz", - "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz", - "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz", - "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz", - "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz", - "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz", - "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz", - "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz", - "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz", - "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz", - "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.10.5", - "@babel/helper-plugin-utils": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz", - "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-simple-access": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz", - "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.10.4", - "@babel/helper-module-transforms": "^7.10.5", - "@babel/helper-plugin-utils": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz", - "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz", - "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz", - "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz", - "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz", - "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz", - "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz", - "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.2" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz", - "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz", - "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz", - "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz", - "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-regex": "^7.10.4" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz", - "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz", - "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz", - "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz", - "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/preset-env": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.0.tgz", - "integrity": "sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.11.0", - "@babel/helper-compilation-targets": "^7.10.4", - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-proposal-async-generator-functions": "^7.10.4", - "@babel/plugin-proposal-class-properties": "^7.10.4", - "@babel/plugin-proposal-dynamic-import": "^7.10.4", - "@babel/plugin-proposal-export-namespace-from": "^7.10.4", - "@babel/plugin-proposal-json-strings": "^7.10.4", - "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", - "@babel/plugin-proposal-numeric-separator": "^7.10.4", - "@babel/plugin-proposal-object-rest-spread": "^7.11.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.10.4", - "@babel/plugin-proposal-optional-chaining": "^7.11.0", - "@babel/plugin-proposal-private-methods": "^7.10.4", - "@babel/plugin-proposal-unicode-property-regex": "^7.10.4", - "@babel/plugin-syntax-async-generators": "^7.8.0", - "@babel/plugin-syntax-class-properties": "^7.10.4", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.0", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0", - "@babel/plugin-syntax-top-level-await": "^7.10.4", - "@babel/plugin-transform-arrow-functions": "^7.10.4", - "@babel/plugin-transform-async-to-generator": "^7.10.4", - "@babel/plugin-transform-block-scoped-functions": "^7.10.4", - "@babel/plugin-transform-block-scoping": "^7.10.4", - "@babel/plugin-transform-classes": "^7.10.4", - "@babel/plugin-transform-computed-properties": "^7.10.4", - "@babel/plugin-transform-destructuring": "^7.10.4", - "@babel/plugin-transform-dotall-regex": "^7.10.4", - "@babel/plugin-transform-duplicate-keys": "^7.10.4", - "@babel/plugin-transform-exponentiation-operator": "^7.10.4", - "@babel/plugin-transform-for-of": "^7.10.4", - "@babel/plugin-transform-function-name": "^7.10.4", - "@babel/plugin-transform-literals": "^7.10.4", - "@babel/plugin-transform-member-expression-literals": "^7.10.4", - "@babel/plugin-transform-modules-amd": "^7.10.4", - "@babel/plugin-transform-modules-commonjs": "^7.10.4", - "@babel/plugin-transform-modules-systemjs": "^7.10.4", - "@babel/plugin-transform-modules-umd": "^7.10.4", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4", - "@babel/plugin-transform-new-target": "^7.10.4", - "@babel/plugin-transform-object-super": "^7.10.4", - "@babel/plugin-transform-parameters": "^7.10.4", - "@babel/plugin-transform-property-literals": "^7.10.4", - "@babel/plugin-transform-regenerator": "^7.10.4", - "@babel/plugin-transform-reserved-words": "^7.10.4", - "@babel/plugin-transform-shorthand-properties": "^7.10.4", - "@babel/plugin-transform-spread": "^7.11.0", - "@babel/plugin-transform-sticky-regex": "^7.10.4", - "@babel/plugin-transform-template-literals": "^7.10.4", - "@babel/plugin-transform-typeof-symbol": "^7.10.4", - "@babel/plugin-transform-unicode-escapes": "^7.10.4", - "@babel/plugin-transform-unicode-regex": "^7.10.4", - "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.11.0", - "browserslist": "^4.12.0", - "core-js-compat": "^3.6.2", - "invariant": "^2.2.2", - "levenary": "^1.1.1", - "semver": "^5.5.0" - } - }, - "@babel/preset-modules": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz", - "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/runtime": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", - "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/traverse": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", - "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.0", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.0", - "@babel/types": "^7.11.0", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" - } - }, - "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", - "to-fast-properties": "^2.0.0" - } - }, - "@types/json-schema": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", - "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", - "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", - "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", - "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", - "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", - "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", - "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", - "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", - "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", - "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", - "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", - "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/helper-wasm-section": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-opt": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", - "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", - "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", - "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", - "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/floating-point-hex-parser": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-code-frame": "1.9.0", - "@webassemblyjs/helper-fsm": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", - "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", - "dev": true - }, - "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true, - "optional": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-loader": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", - "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", - "dev": true, - "requires": { - "find-cache-dir": "^2.1.0", - "loader-utils": "^1.4.0", - "mkdirp": "^0.5.3", - "pify": "^4.0.1", - "schema-utils": "^2.6.5" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, - "babel-plugin-syntax-class-properties": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", - "dev": true - }, - "babel-plugin-transform-class-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-plugin-syntax-class-properties": "^6.8.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - } - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - }, - "dependencies": { - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - } - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dev": true, - "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "~1.0.5" - } - }, - "browserslist": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.0.tgz", - "integrity": "sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001111", - "electron-to-chromium": "^1.3.523", - "escalade": "^3.0.2", - "node-releases": "^1.1.60" - } - }, - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, - "cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001118", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001118.tgz", - "integrity": "sha512-RNKPLojZo74a0cP7jFMidQI7nvLER40HgNfgKQEJ2PFm225L0ectUungNQoK3Xk3StQcFbpBPNEvoWD59436Hg==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", - "dev": true - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", - "dev": true - }, - "core-js-compat": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", - "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", - "dev": true, - "requires": { - "browserslist": "^4.8.5", - "semver": "7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true - } - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "css-loader": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", - "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "cssesc": "^3.0.0", - "icss-utils": "^4.1.1", - "loader-utils": "^1.2.3", - "normalize-path": "^3.0.0", - "postcss": "^7.0.32", - "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^3.0.2", - "postcss-modules-scope": "^2.2.0", - "postcss-modules-values": "^3.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^2.7.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "cyclist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", - "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", - "dev": true - }, - "d3": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz", - "integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==", - "requires": { - "d3-array": "1", - "d3-axis": "1", - "d3-brush": "1", - "d3-chord": "1", - "d3-collection": "1", - "d3-color": "1", - "d3-contour": "1", - "d3-dispatch": "1", - "d3-drag": "1", - "d3-dsv": "1", - "d3-ease": "1", - "d3-fetch": "1", - "d3-force": "1", - "d3-format": "1", - "d3-geo": "1", - "d3-hierarchy": "1", - "d3-interpolate": "1", - "d3-path": "1", - "d3-polygon": "1", - "d3-quadtree": "1", - "d3-random": "1", - "d3-scale": "2", - "d3-scale-chromatic": "1", - "d3-selection": "1", - "d3-shape": "1", - "d3-time": "1", - "d3-time-format": "2", - "d3-timer": "1", - "d3-transition": "1", - "d3-voronoi": "1", - "d3-zoom": "1" - } - }, - "d3-array": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", - "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" - }, - "d3-axis": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz", - "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==" - }, - "d3-brush": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz", - "integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "d3-chord": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", - "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", - "requires": { - "d3-array": "1", - "d3-path": "1" - } - }, - "d3-collection": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", - "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==" - }, - "d3-color": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", - "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==" - }, - "d3-contour": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", - "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", - "requires": { - "d3-array": "^1.1.1" - } - }, - "d3-dispatch": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", - "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==" - }, - "d3-drag": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", - "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", - "requires": { - "d3-dispatch": "1", - "d3-selection": "1" - } - }, - "d3-dsv": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", - "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", - "requires": { - "commander": "2", - "iconv-lite": "0.4", - "rw": "1" - } - }, - "d3-ease": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", - "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==" - }, - "d3-fetch": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz", - "integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==", - "requires": { - "d3-dsv": "1" - } - }, - "d3-force": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz", - "integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==", - "requires": { - "d3-collection": "1", - "d3-dispatch": "1", - "d3-quadtree": "1", - "d3-timer": "1" - } - }, - "d3-format": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", - "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==" - }, - "d3-geo": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz", - "integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==", - "requires": { - "d3-array": "1" - } - }, - "d3-hierarchy": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", - "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==" - }, - "d3-interpolate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", - "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", - "requires": { - "d3-color": "1" - } - }, - "d3-path": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" - }, - "d3-polygon": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", - "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==" - }, - "d3-quadtree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", - "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==" - }, - "d3-random": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz", - "integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==" - }, - "d3-scale": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", - "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", - "requires": { - "d3-array": "^1.2.0", - "d3-collection": "1", - "d3-format": "1", - "d3-interpolate": "1", - "d3-time": "1", - "d3-time-format": "2" - } - }, - "d3-scale-chromatic": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz", - "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==", - "requires": { - "d3-color": "1", - "d3-interpolate": "1" - } - }, - "d3-selection": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", - "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==" - }, - "d3-shape": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", - "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", - "requires": { - "d3-path": "1" - } - }, - "d3-time": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", - "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==" - }, - "d3-time-format": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", - "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", - "requires": { - "d3-time": "1" - } - }, - "d3-timer": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", - "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==" - }, - "d3-tip": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/d3-tip/-/d3-tip-0.9.1.tgz", - "integrity": "sha512-EVBfG9d+HnjIoyVXfhpytWxlF59JaobwizqMX9EBXtsFmJytjwHeYiUs74ldHQjE7S9vzfKTx2LCtvUrIbuFYg==", - "requires": { - "d3-collection": "^1.0.4", - "d3-selection": "^1.3.0" - } - }, - "d3-transition": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", - "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", - "requires": { - "d3-color": "1", - "d3-dispatch": "1", - "d3-ease": "1", - "d3-interpolate": "1", - "d3-selection": "^1.1.0", - "d3-timer": "1" - } - }, - "d3-voronoi": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", - "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==" - }, - "d3-zoom": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz", - "integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "dagre": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", - "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", - "requires": { - "graphlib": "^2.1.8", - "lodash": "^4.17.15" - } - }, - "dagre-d3": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz", - "integrity": "sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==", - "requires": { - "d3": "^5.14", - "dagre": "^0.8.5", - "graphlib": "^2.1.8", - "lodash": "^4.17.15" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "electron-to-chromium": { - "version": "1.3.549", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.549.tgz", - "integrity": "sha512-q09qZdginlqDH3+Y1P6ch5UDTW8nZ1ijwMkxFs15J/DAWOwqolIx8HZH1UP0vReByBigk/dPlU22xS1MaZ+kpQ==", - "dev": true - }, - "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", - "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", - "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - }, - "dependencies": { - "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - } - } - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, - "escalade": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", - "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "events": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", - "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", - "dev": true - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "figgy-pudding": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", - "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", - "dev": true - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "requires": { - "global-prefix": "^3.0.0" - }, - "dependencies": { - "global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "requires": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - } - } - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "graphlib": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", - "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", - "requires": { - "lodash": "^4.17.15" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-utils": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", - "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", - "dev": true, - "requires": { - "postcss": "^7.0.14" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true - }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, - "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", - "dev": true, - "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levenary": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", - "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", - "dev": true, - "requires": { - "leven": "^3.1.0" - } - }, - "loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", - "dev": true - }, - "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "mini-css-extract-plugin": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz", - "integrity": "sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "normalize-url": "1.9.1", - "schema-utils": "^1.0.0", - "webpack-sources": "^1.1.0" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - } - } - }, - "node-releases": { - "version": "1.1.60", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", - "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "parallel-transform": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", - "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", - "dev": true, - "requires": { - "cyclist": "^1.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, - "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path": { - "version": "0.12.7", - "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", - "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", - "dev": true, - "requires": { - "process": "^0.11.1", - "util": "^0.10.3" - } - }, - "path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true, - "optional": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "pbkdf2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", - "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "platform": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", - "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-modules-extract-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", - "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", - "dev": true, - "requires": { - "postcss": "^7.0.5" - } - }, - "postcss-modules-local-by-default": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", - "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", - "dev": true, - "requires": { - "icss-utils": "^4.1.1", - "postcss": "^7.0.32", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } - }, - "postcss-modules-scope": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", - "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", - "dev": true, - "requires": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0" - } - }, - "postcss-modules-values": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", - "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", - "dev": true, - "requires": { - "icss-utils": "^4.0.0", - "postcss": "^7.0.6" - } - }, - "postcss-selector-parser": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", - "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", - "dev": true - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, - "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "regenerate": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", - "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", - "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - } - }, - "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", - "dev": true - }, - "regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexpu-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", - "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.2.0", - "regjsgen": "^0.5.1", - "regjsparser": "^0.6.4", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.2.0" - } - }, - "regjsgen": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", - "dev": true - }, - "regjsparser": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", - "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true, - "optional": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "dependencies": { - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - } - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } - }, - "rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sass": { - "version": "1.26.10", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.10.tgz", - "integrity": "sha512-bzN0uvmzfsTvjz0qwccN1sPm2HxxpNI/Xa+7PlUEMS+nQvbyuEK7Y0qFqxlPHhiNHb1Ze8WQJtU31olMObkAMw==", - "dev": true, - "requires": { - "chokidar": ">=2.0.0 <4.0.0" - } - }, - "sass-loader": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz", - "integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "loader-utils": "^1.2.3", - "neo-async": "^2.6.1", - "schema-utils": "^2.6.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true - }, - "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "dev": true, - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "terser-webpack-plugin": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", - "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", - "dev": true, - "requires": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^4.0.0", - "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "timers-browserify": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", - "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", - "dev": true - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", - "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", - "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, - "optional": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "v8-compile-cache": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", - "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", - "dev": true - }, - "vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", - "dev": true - }, - "watchpack": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", - "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", - "dev": true, - "requires": { - "chokidar": "^3.4.1", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0", - "watchpack-chokidar2": "^2.0.0" - } - }, - "watchpack-chokidar2": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", - "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", - "dev": true, - "optional": true, - "requires": { - "chokidar": "^2.1.8" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "optional": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "optional": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "optional": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "optional": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "optional": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "optional": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - } - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "optional": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "optional": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "optional": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "optional": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } - } - }, - "webpack": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz", - "integrity": "sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/wasm-edit": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "acorn": "^6.4.1", - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^4.3.0", - "eslint-scope": "^4.0.3", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.4.0", - "loader-utils": "^1.2.3", - "memory-fs": "^0.4.1", - "micromatch": "^3.1.10", - "mkdirp": "^0.5.3", - "neo-async": "^2.6.1", - "node-libs-browser": "^2.2.1", - "schema-utils": "^1.0.0", - "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.3", - "watchpack": "^1.7.4", - "webpack-sources": "^1.4.1" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "webpack-cli": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz", - "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "cross-spawn": "^6.0.5", - "enhanced-resolve": "^4.1.1", - "findup-sync": "^3.0.0", - "global-modules": "^2.0.0", - "import-local": "^2.0.0", - "interpret": "^1.4.0", - "loader-utils": "^1.4.0", - "supports-color": "^6.1.0", - "v8-compile-cache": "^2.1.1", - "yargs": "^13.3.2" - }, - "dependencies": { - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } -} diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/package.json b/dashboardv2/public/js/external_lib/atlas-lineage/package.json deleted file mode 100644 index 6e03eee3f5a..00000000000 --- a/dashboardv2/public/js/external_lib/atlas-lineage/package.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "atlas-lineage-module", - "version": "1.0.0", - "description": "The module will help to render the lineage graph with the help dagre-d3,d3 js lib", - "main": "dist/index.js", - "scripts": { - "start": "NODE_ENV=development webpack --watch", - "build": "webpack" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/apache/atlas.git" - }, - "keywords": [ - "lineage", - "dagre-d3", - "d3" - ], - "author": "kevalbhatt", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/apache/atlas/issues" - }, - "homepage": "https://github.com/apache/atlas#readme", - "dependencies": { - "d3-tip": "^0.9.1", - "dagre-d3": "^0.6.4", - "platform": "^1.3.5" - }, - "devDependencies": { - "@babel/core": "^7.9.6", - "@babel/preset-env": "^7.9.6", - "babel-loader": "^8.1.0", - "babel-plugin-transform-class-properties": "^6.24.1", - "css-loader": "^3.5.3", - "mini-css-extract-plugin": "^0.9.0", - "path": "^0.12.7", - "sass": "^1.26.5", - "sass-loader": "^8.0.2", - "webpack": "^4.43.0", - "webpack-cli": "^3.3.11" - } -} diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/src/Enums.js b/dashboardv2/public/js/external_lib/atlas-lineage/src/Enums.js deleted file mode 100644 index 2773f124905..00000000000 --- a/dashboardv2/public/js/external_lib/atlas-lineage/src/Enums.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -export default { - entityStateReadOnly: { - ACTIVE: false, - DELETED: true, - STATUS_ACTIVE: false, - STATUS_DELETED: true - } -}; \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/DataUtils.js b/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/DataUtils.js deleted file mode 100644 index 1255eb070f0..00000000000 --- a/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/DataUtils.js +++ /dev/null @@ -1,361 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -import Enums from "../Enums"; -import { curveBasis } from "d3-shape"; - -const DataUtils = { - /** - * [getBaseUrl description] - * @param {[type]} url [description] - * @return {[type]} [description] - */ - getBaseUrl: function(url) { - return url.replace(/\/[\w-]+.(jsp|html)|\/+$/gi, ""); - }, - /** - * [getEntityIconPath description] - * @param {[type]} options.entityData [description] - * @param {Object} options.errorUrl } [description] - * @return {[type]} [description] - */ - getEntityIconPath: function({ entityData, errorUrl } = {}) { - var serviceType, - status, - typeName, - iconBasePath = this.getBaseUrl(window.location.pathname) + Globals.entityImgPath; - if (entityData) { - typeName = entityData.typeName; - serviceType = entityData && entityData.serviceType; - status = entityData && entityData.status; - } - - function getImgPath(imageName) { - return iconBasePath + (Enums.entityStateReadOnly[status] ? "disabled/" + imageName : imageName); - } - - function getDefaultImgPath() { - if (entityData.isProcess) { - if (Enums.entityStateReadOnly[status]) { - return iconBasePath + "disabled/process.png"; - } else { - return iconBasePath + "process.png"; - } - } else { - if (Enums.entityStateReadOnly[status]) { - return iconBasePath + "disabled/table.png"; - } else { - return iconBasePath + "table.png"; - } - } - } - - if (entityData) { - if (errorUrl) { - var isErrorInTypeName = errorUrl && errorUrl.match("entity-icon/" + typeName + ".png|disabled/" + typeName + ".png") ? true : false; - if (serviceType && isErrorInTypeName) { - var imageName = serviceType + ".png"; - return getImgPath(imageName); - } else { - return getDefaultImgPath(); - } - } else if (entityData.typeName) { - var imageName = entityData.typeName + ".png"; - return getImgPath(imageName); - } else { - return getDefaultImgPath(); - } - } - }, - /** - * [isProcess description] - * @param {[type]} options.typeName [description] - * @param {[type]} options.superTypes [description] - * @param {[type]} options.entityDef [description] - * @return {Boolean} [description] - */ - isProcess: function({ typeName, superTypes, entityDef }) { - if (typeName == "Process") { - return true; - } - return superTypes.indexOf("Process") > -1; - }, - /** - * [isDeleted description] - * @param {[type]} node [description] - * @return {Boolean} [description] - */ - isDeleted: function(node) { - if (node === undefined) { - return; - } - return Enums.entityStateReadOnly[node.status]; - }, - isNodeToBeUpdated: function(node, filterObj) { - var isProcessHideCheck = filterObj.isProcessHideCheck, - isDeletedEntityHideCheck = filterObj.isDeletedEntityHideCheck; - var returnObj = { - isProcess: isProcessHideCheck && node.isProcess, - isDeleted: isDeletedEntityHideCheck && node.isDeleted - }; - returnObj["update"] = returnObj.isProcess || returnObj.isDeleted; - return returnObj; - }, - /** - * [getServiceType description] - * @param {[type]} options.typeName [description] - * @param {[type]} options.entityDef [description] - * @return {[type]} [description] - */ - getServiceType: function({ typeName, entityDef }) { - var serviceType = null; - if (typeName) { - if (entityDef) { - serviceType = entityDef.serviceType || null; - } - } - return serviceType; - }, - /** - * [getEntityDef description] - * @param {[type]} options.typeName [description] - * @param {[type]} options.entityDefCollection [description] - * @return {[type]} [description] - */ - getEntityDef: function({ typeName, entityDefCollection }) { - var entityDef = null; - if (typeName) { - entityDef = entityDefCollection.find(function(obj) { - return obj.name == typeName; - }); - } - return entityDef; - }, - /** - * [getNestedSuperTypes description] - * @param {[type]} options.entityDef [description] - * @param {[type]} options.entityDefCollection [description] - * @return {[type]} [description] - */ - getNestedSuperTypes: function({ entityDef, entityDefCollection }) { - var data = entityDef, - collection = entityDefCollection, - superTypes = new Set(); - - var getData = function(data, collection) { - if (data) { - if (data.superTypes && data.superTypes.length) { - data.superTypes.forEach(function(superTypeName) { - superTypes.add(superTypeName); - var collectionData = collection.find(function(obj) { - obj.name === superTypeName; - }); - if (collectionData) { - getData(collectionData, collection); - } - }); - } - } - }; - getData(data, collection); - return Array.from(superTypes); - }, - generateData: function({ data = {}, filterObj, entityDefCollection, g, guid, setGraphEdge, setGraphNode }) { - return new Promise((resolve, reject) => { - try { - var relations = data.relations || {}, - guidEntityMap = data.guidEntityMap || {}, - isHideFilterOn = filterObj.isProcessHideCheck || filterObj.isDeletedEntityHideCheck, - newHashMap = {}, - styleObj = { - fill: "none", - stroke: "#ffb203", - width: 3 - }, - makeNodeData = (relationObj) => { - if (relationObj) { - if (relationObj.updatedValues) { - return relationObj; - } - var obj = Object.assign(relationObj, { - shape: "img", - updatedValues: true, - label: relationObj.displayText.trunc(18), - toolTipLabel: relationObj.displayText, - id: relationObj.guid, - isLineage: true, - isIncomplete: relationObj.isIncomplete, - entityDef: this.getEntityDef({ typeName: relationObj.typeName, entityDefCollection }) - }); - obj["serviceType"] = this.getServiceType(obj); - obj["superTypes"] = this.getNestedSuperTypes({ - ...obj, - entityDefCollection: entityDefCollection - }); - obj["isProcess"] = this.isProcess(obj); - obj["isDeleted"] = this.isDeleted(obj); - return obj; - } - }, - crateLineageRelationshipHashMap = function({ relations } = {}) { - var newHashMap = {}; - relations.forEach(function(obj) { - if (newHashMap[obj.fromEntityId]) { - newHashMap[obj.fromEntityId].push(obj.toEntityId); - } else { - newHashMap[obj.fromEntityId] = [obj.toEntityId]; - } - }); - return newHashMap; - }, - getStyleObjStr = function(styleObj) { - return "fill:" + styleObj.fill + ";stroke:" + styleObj.stroke + ";stroke-width:" + styleObj.width; - }, - getNewToNodeRelationship = (toNodeGuid, filterObj) => { - if (toNodeGuid && relationshipMap[toNodeGuid]) { - var newRelationship = []; - relationshipMap[toNodeGuid].forEach((guid) => { - var nodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[guid]), filterObj); - if (nodeToBeUpdated.update) { - var newRelation = getNewToNodeRelationship(guid, filterObj); - if (newRelation) { - newRelationship = newRelationship.concat(newRelation); - } - } else { - newRelationship.push(guid); - } - }); - return newRelationship; - } else { - return null; - } - }, - getToNodeRelation = (toNodes, fromNodeToBeUpdated, filterObj) => { - var toNodeRelationship = []; - toNodes.forEach((toNodeGuid) => { - var toNodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[toNodeGuid]), filterObj); - if (toNodeToBeUpdated.update) { - // To node need to updated - if (pendingFromRelationship[toNodeGuid]) { - toNodeRelationship = toNodeRelationship.concat(pendingFromRelationship[toNodeGuid]); - } else { - var newToNodeRelationship = getNewToNodeRelationship(toNodeGuid, filterObj); - if (newToNodeRelationship) { - toNodeRelationship = toNodeRelationship.concat(newToNodeRelationship); - } - } - } else { - //when bothe node not to be updated. - toNodeRelationship.push(toNodeGuid); - } - }); - return toNodeRelationship; - }, - setNode = (guid) => { - if (!g._nodes[guid]) { - var nodeData = makeNodeData(guidEntityMap[guid]); - setGraphNode(guid, nodeData); - return nodeData; - } else { - return g._nodes[guid]; - } - }, - setEdge = function(fromNodeGuid, toNodeGuid, opt = {}) { - setGraphEdge(fromNodeGuid, toNodeGuid, { - arrowhead: "arrowPoint", - curve: curveBasis, - style: getStyleObjStr(styleObj), - styleObj: styleObj, - ...opt - }); - }, - setGraphData = function(fromEntityId, toEntityId) { - setNode(fromEntityId); - setNode(toEntityId); - setEdge(fromEntityId, toEntityId); - }, - pendingFromRelationship = {}; - if (isHideFilterOn) { - var relationshipMap = crateLineageRelationshipHashMap(data); - Object.keys(relationshipMap).forEach((fromNodeGuid) => { - var toNodes = relationshipMap[fromNodeGuid], - fromNodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[fromNodeGuid]), filterObj), - toNodeList = getToNodeRelation(toNodes, fromNodeToBeUpdated, filterObj); - if (fromNodeToBeUpdated.update) { - if (pendingFromRelationship[fromNodeGuid]) { - pendingFromRelationship[fromNodeGuid] = pendingFromRelationship[fromNodeGuid].concat(toNodeList); - } else { - pendingFromRelationship[fromNodeGuid] = toNodeList; - } - } else { - toNodeList.forEach(function(toNodeGuid) { - setGraphData(fromNodeGuid, toNodeGuid); - }); - } - }); - } else { - relations.forEach(function(obj) { - setGraphData(obj.fromEntityId, obj.toEntityId); - }); - } - if (g._nodes[guid]) { - if (g._nodes[guid]) { - g._nodes[guid]["isLineage"] = false; - } - this.findImpactNodeAndUpdateData({ - guid, - g, - setEdge, - getStyleObjStr - }); - } - resolve(g); - } catch (e) { - reject(e); - } - }); - }, - findImpactNodeAndUpdateData: function({ guid, getStyleObjStr, g, setEdge }) { - var that = this, - traversedMap = {}, - styleObj = { - fill: "none", - stroke: "#fb4200", - width: 3 - }, - traversed = function(toNodeList = {}, fromNodeGuid) { - let toNodeKeyList = Object.keys(toNodeList); - if (toNodeKeyList.length) { - if (!traversedMap[fromNodeGuid]) { - traversedMap[fromNodeGuid] = true; - toNodeKeyList.forEach(function(toNodeGuid) { - if (g._nodes[toNodeGuid]) { - g._nodes[toNodeGuid]["isLineage"] = false; - } - setEdge(fromNodeGuid, toNodeGuid, { - style: getStyleObjStr(styleObj), - styleObj: styleObj - }); - traversed(g._sucs[toNodeGuid], toNodeGuid); - }); - } - } - }; - traversed(g._sucs[guid], guid); - } -}; -export default DataUtils; \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/LineageUtils.js b/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/LineageUtils.js deleted file mode 100644 index 448a95ae6eb..00000000000 --- a/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/LineageUtils.js +++ /dev/null @@ -1,608 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import { select, event } from "d3-selection"; -import { zoom, zoomIdentity } from "d3-zoom"; -import { drag } from "d3-drag"; -import { line, curveBasis } from "d3-shape"; - -import platform from "platform"; - -import Enums from "../Enums"; - -const LineageUtils = { - /** - * [nodeArrowDistance variable use to define the distance between arrow and node] - * @type {Number} - */ - nodeArrowDistance: 24, - refreshGraphForSafari: function (options) { - var edgePathEl = options.edgeEl, - IEGraphRenderDone = 0; - edgePathEl.each(function (argument) { - var eleRef = this, - childNode = $(this).find("pattern"); - setTimeout(function (argument) { - $(eleRef).find("defs").append(childNode); - }, 500); - }); - }, - refreshGraphForIE: function ({ edgePathEl }) { - var IEGraphRenderDone = 0; - edgePathEl.each(function (argument) { - var childNode = $(this).find("marker"); - $(this).find("marker").remove(); - var eleRef = this; - ++IEGraphRenderDone; - setTimeout(function (argument) { - $(eleRef).find("defs").append(childNode); - --IEGraphRenderDone; - if (IEGraphRenderDone === 0) { - this.$(".fontLoader").hide(); - this.$("svg").fadeTo(1000, 1); - } - }, 1000); - }); - }, - /** - * [dragNode description] - * @param {[type]} options.g [description] - * @param {[type]} options.svg [description] - * @param {[type]} options.guid [description] - * @param {[type]} options.edgePathEl [description] - * @return {[type]} [description] - */ - dragNode: function ({ g, svg, guid, edgePathEl }) { - var dragHelper = { - dragmove: function (el, d) { - var node = select(el), - selectedNode = g.node(d), - prevX = selectedNode.x, - prevY = selectedNode.y; - - selectedNode.x += event.dx; - selectedNode.y += event.dy; - node.attr("transform", "translate(" + selectedNode.x + "," + selectedNode.y + ")"); - - var dx = selectedNode.x - prevX, - dy = selectedNode.y - prevY; - - g.edges().forEach((e) => { - if (e.v == d || e.w == d) { - var edge = g.edge(e.v, e.w); - this.translateEdge(edge, dx, dy); - select(edge.elem).select("path").attr("d", this.calcPoints(e)); - } - }); - //LineageUtils.refreshGraphForIE({ edgePathEl: edgePathEl }); - }, - translateEdge: function (e, dx, dy) { - e.points.forEach(function (p) { - p.x = p.x + dx; - p.y = p.y + dy; - }); - }, - calcPoints: function (e) { - var edge = g.edge(e.v, e.w), - tail = g.node(e.v), - head = g.node(e.w), - points = edge.points.slice(1, edge.points.length - 1), - afterslice = edge.points.slice(1, edge.points.length - 1); - points.unshift(this.intersectRect(tail, points[0])); - points.push(this.intersectRect(head, points[points.length - 1])); - return line() - .x(function (d) { - return d.x; - }) - .y(function (d) { - return d.y; - }) - .curve(curveBasis)(points); - }, - intersectRect: (node, point) => { - var x = node.x, - y = node.y, - dx = point.x - x, - dy = point.y - y, - nodeDistance = guid ? this.nodeArrowDistance + 3 : this.nodeArrowDistance, - w = nodeDistance, - h = nodeDistance, - sx = 0, - sy = 0; - - if (Math.abs(dy) * w > Math.abs(dx) * h) { - // Intersection is top or bottom of rect. - if (dy < 0) { - h = -h; - } - sx = dy === 0 ? 0 : (h * dx) / dy; - sy = h; - } else { - // Intersection is left or right of rect. - if (dx < 0) { - w = -w; - } - sx = w; - sy = dx === 0 ? 0 : (w * dy) / dx; - } - return { - x: x + sx, - y: y + sy - }; - } - }; - var dragNodeHandler = drag().on("drag", function (d) { - dragHelper.dragmove.call(dragHelper, this, d); - }), - dragEdgePathHandler = drag().on("drag", function (d) { - dragHelper.translateEdge(g.edge(d.v, d.w), event.dx, event.dy); - var edgeObj = g.edge(d.v, d.w); - select(edgeObj.elem).select("path").attr("d", dragHelper.calcPoints(d)); - }); - - dragNodeHandler(svg.selectAll("g.node")); - dragEdgePathHandler(svg.selectAll("g.edgePath")); - }, - zoomIn: function ({ svg, scaleFactor = 1.3 }) { - this.d3Zoom.scaleBy(svg.transition().duration(750), scaleFactor); - }, - zoomOut: function ({ svg, scaleFactor = 0.8 }) { - this.d3Zoom.scaleBy(svg.transition().duration(750), scaleFactor); - }, - zoom: function ({ svg, xa, ya, scale }) { - svg.transition().duration(750).call(this.d3Zoom.transform, zoomIdentity.translate(xa, ya).scale(scale)); - }, - fitToScreen: function ({ svg }) { - var node = svg.node(); - var bounds = node.getBBox(); - - var parent = node.parentElement, - fullWidth = parent.clientWidth, - fullHeight = parent.clientHeight; - - var width = bounds.width, - height = bounds.height; - var midX = bounds.x + width / 2, - midY = bounds.y + height / 2; - - var scale = (scale || 0.95) / Math.max(width / fullWidth, height / fullHeight), - xa = fullWidth / 2 - scale * midX, - ya = fullHeight / 2 - scale * midY; - this.zoom({ svg, xa, ya, scale }); - }, - /** - * [centerNode description] - * @param {[type]} options.guid [description] - * @param {[type]} options.g [description] - * @param {[type]} options.svg [description] - * @param {[type]} options.svgGroupEl [description] - * @param {[type]} options.edgePathEl [description] - * @param {[type]} options.width [description] - * @param {[type]} options.height [description] - * @param {[type]} options.onCenterZoomed [description] - * @return {[type]} [description] - */ - centerNode: function ({ guid, g, svg, svgGroupEl, edgePathEl, width, height, fitToScreen, onCenterZoomed }) { - this.d3Zoom = zoom(); - svg.call(this.d3Zoom).on("dblclick.zoom", null); - - // restrict events - - let selectedNodeEl = svg.selectAll("g.nodes>g[id='" + guid + "']"), - zoomListener = this.d3Zoom.scaleExtent([0.01, 50]).on("zoom", function () { - svgGroupEl.attr("transform", event.transform); - }), - x = null, - y = null, - scale = 1.2; - if (selectedNodeEl.empty()) { - if (fitToScreen) { - this.fitToScreen({ svg }); - return; - } else { - x = g.graph().width / 2; - y = g.graph().height / 2; - } - } else { - var matrix = selectedNodeEl - .attr("transform") - .replace(/[^0-9\-.,]/g, "") - .split(","); - // if (platform.name === "IE" || platform.name === "Microsoft Edge") { - // var matrix = selectedNode - // .attr("transform") - // .replace(/[a-z\()]/g, "") - // .split(" "); - // } - x = matrix[0]; - y = matrix[1]; - } - - var xa = -(x * scale - width / 2), - ya = -(y * scale - height / 2); - this.zoom({ svg, xa, ya, scale }); - svg.transition().duration(750).call(this.d3Zoom.transform, zoomIdentity.translate(xa, ya).scale(scale)); - - if (onCenterZoomed) { - onCenterZoomed({ newScale: scale, newTranslate: [xa, ya], d3Zoom: this.d3Zoom, selectedNodeEl }); - } - // if (platform.name === "IE") { - // LineageUtils.refreshGraphForIE({ edgePathEl: edgePathEl }); - // } - }, - /** - * [getToolTipDirection description] - * @param {[type]} options.el [description] - * @return {[type]} [description] - */ - getToolTipDirection: function ({ el }) { - var width = select("body").node().getBoundingClientRect().width, - currentELWidth = select(el).node().getBoundingClientRect(), - direction = "e"; - if (width - currentELWidth.left < 330) { - direction = width - currentELWidth.left < 330 && currentELWidth.top < 400 ? "sw" : "w"; - if (width - currentELWidth.left < 330 && currentELWidth.top > 600) { - direction = "nw"; - } - } else if (currentELWidth.top > 600) { - direction = width - currentELWidth.left < 330 && currentELWidth.top > 600 ? "nw" : "n"; - if (currentELWidth.left < 50) { - direction = "ne"; - } - } else if (currentELWidth.top < 400) { - direction = currentELWidth.left < 50 ? "se" : "s"; - } - return direction; - }, - /** - * [onHoverFade description] - * @param {[type]} options.svg [description] - * @param {[type]} options.g [description] - * @param {[type]} options.mouseenter [description] - * @param {[type]} options.opacity [description] - * @param {[type]} options.nodesToHighlight [description] - * @param {[type]} options.hoveredNode [description] - * @return {[type]} [description] - */ - onHoverFade: function ({ svg, g, mouseenter, nodesToHighlight, hoveredNode }) { - var node = svg.selectAll(".node"), - path = svg.selectAll(".edgePath"), - isConnected = function (a, b, o) { - if (a === o || (b && b.length && b.indexOf(o) != -1)) { - return true; - } - }; - if (mouseenter) { - svg.classed("hover", true); - var nextNode = g.successors(hoveredNode), - previousNode = g.predecessors(hoveredNode), - nodesToHighlight = nextNode.concat(previousNode); - node.classed("hover-active-node", function (currentNode, i, nodes) { - if (isConnected(hoveredNode, nodesToHighlight, currentNode)) { - return true; - } else { - return false; - } - }); - path.classed("hover-active-path", function (c) { - var _thisOpacity = c.v === hoveredNode || c.w === hoveredNode ? 1 : 0; - if (_thisOpacity) { - return true; - } else { - return false; - } - }); - } else { - svg.classed("hover", false); - node.classed("hover-active-node", false); - path.classed("hover-active-path", false); - } - }, - /** - * [getBaseUrl description] - * @param {[type]} path [description] - * @return {[type]} [description] - */ - getBaseUrl: function (url = window.location.pathname) { - return url.replace(/\/[\w-]+.(jsp|html)|\/+$/gi, ""); - }, - getEntityIconPath: function ({ entityData, errorUrl, imgBasePath }) { - var iconBasePath = this.getBaseUrl() + (imgBasePath || "/img/entity-icon/"); - if (entityData) { - let { typeName, serviceType, status, isProcess } = entityData; - - function getImgPath(imageName) { - return iconBasePath + (Enums.entityStateReadOnly[status] ? "disabled/" + imageName : imageName); - } - - function getDefaultImgPath() { - if (isProcess) { - if (Enums.entityStateReadOnly[status]) { - return iconBasePath + "disabled/process.png"; - } else { - return iconBasePath + "process.png"; - } - } else { - if (Enums.entityStateReadOnly[status]) { - return iconBasePath + "disabled/table.png"; - } else { - return iconBasePath + "table.png"; - } - } - } - - if (errorUrl) { - // Check if the default img path has error, if yes then stop recursion. - if (errorUrl.indexOf("table.png") > -1 || errorUrl.indexOf("process.png") > -1) { - return null; - } - var isErrorInTypeName = errorUrl && errorUrl.match("entity-icon/" + typeName + ".png|disabled/" + typeName + ".png") ? true : false; - if (serviceType && isErrorInTypeName) { - var imageName = serviceType + ".png"; - return getImgPath(imageName); - } else { - return getDefaultImgPath(); - } - } else if (typeName) { - var imageName = typeName + ".png"; - return getImgPath(imageName); - } else if (serviceType) { - var imageName = serviceType + ".png"; - return getImgPath(imageName); - } else { - return getDefaultImgPath(); - } - } - }, - base64Encode: function (file, callback) { - const reader = new FileReader(); - reader.addEventListener("load", () => callback(reader.result)); - reader.readAsDataURL(file); - }, - imgShapeRender: function (parent, bbox, node, { dagreD3, defsEl, imgBasePath, guid, isRankdirToBottom }) { - var that = this, - viewGuid = guid, - imageIconPath = this.getEntityIconPath({ entityData: node, imgBasePath }), - imgName = imageIconPath.split("/").pop(); - if (this.imageObject === undefined) { - this.imageObject = {}; - } - if (node.isDeleted) { - imgName = "deleted_" + imgName; - } - if (node.id == viewGuid) { - var currentNode = true; - } - var shapeSvg = parent - .append("circle") - .attr("fill", "url(#img_" + encodeURI(imgName) + ")") - .attr("r", isRankdirToBottom ? "30px" : "24px") - .attr("data-stroke", node.id) - .attr("stroke-width", "2px") - .attr("class", "nodeImage " + (currentNode ? "currentNode" : node.isProcess ? "process" : "node")); - if (currentNode) { - shapeSvg.attr("stroke", "#fb4200"); - } - if (node.isIncomplete === true) { - parent.attr("class", "node isIncomplete show"); - parent - .insert("foreignObject") - .attr("x", "-25") - .attr("y", "-25") - .attr("width", "50") - .attr("height", "50") - .append("xhtml:div") - .insert("i") - .attr("class", "fa fa-hourglass-half"); - } - - if (defsEl.select('pattern[id="img_' + imgName + '"]').empty()) { - defsEl - .append("pattern") - .attr("x", "0%") - .attr("y", "0%") - .attr("patternUnits", "objectBoundingBox") - .attr("id", "img_" + imgName) - .attr("width", "100%") - .attr("height", "100%") - .append("image") - .attr("href", function (d) { - var imgEl = this; - if (node) { - var getImageData = function (options) { - var imagePath = options.imagePath, - ajaxOptions = { - url: imagePath, - method: "GET", - cache: true - }; - - // if (platform.name !== "IE") { - // ajaxOptions["mimeType"] = "text/plain; charset=x-user-defined"; - // } - shapeSvg.attr("data-iconpath", imagePath); - var xhr = new XMLHttpRequest(); - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - if (xhr.status === 200) { - if (platform.name !== "IE") { - that.base64Encode(this.response, (url) => { - that.imageObject[imageIconPath] = url; - select(imgEl).attr("xlink:href", url); - }); - } else { - that.imageObject[imageIconPath] = imagePath; - } - if (imageIconPath !== shapeSvg.attr("data-iconpath")) { - shapeSvg.attr("data-iconpathorigin", imageIconPath); - } - } else if (xhr.status === 404) { - const imgPath = that.getEntityIconPath({ entityData: node, errorUrl: imagePath }); - if (imgPath === null) { - const patternEL = select(imgEl.parentElement); - patternEL.select("image").remove(); - patternEL - .attr("patternContentUnits", "objectBoundingBox") - .append("circle") - .attr("r", "24px") - .attr("fill", "#e8e8e8"); - } else { - getImageData({ - imagePath: imgPath - }); - } - } - } - }; - xhr.responseType = "blob"; - xhr.open(ajaxOptions.method, ajaxOptions.url, true); - xhr.send(null); - }; - getImageData({ - imagePath: imageIconPath - }); - } - }) - .attr("x", isRankdirToBottom ? "11" : "4") - .attr("y", isRankdirToBottom ? "20" : currentNode ? "3" : "4") - .attr("width", "40") - .attr("height", "40"); - } - - node.intersect = function (point) { - return dagreD3.intersect.circle(node, currentNode ? that.nodeArrowDistance + 3 : that.nodeArrowDistance, point); - }; - return shapeSvg; - }, - /** - * [arrowPointRender description] - * @param {[type]} {parent, id, edge, type, viewOptions [description] - * @return {[type]} [description] - */ - arrowPointRender: function (parent, id, edge, type, { dagreD3 }) { - var node = parent.node(), - parentNode = node ? node.parentNode : parent; - select(parentNode) - .select("path.path") - .attr("marker-end", "url(#" + id + ")"); - var marker = parent - .append("marker") - .attr("id", id) - .attr("viewBox", "0 0 10 10") - .attr("refX", 8) - .attr("refY", 5) - .attr("markerUnits", "strokeWidth") - .attr("markerWidth", 4) - .attr("markerHeight", 4) - .attr("orient", "auto"); - - var path = marker.append("path").attr("d", "M 0 0 L 10 5 L 0 10 z").style("fill", edge.styleObj.stroke); - dagreD3.util.applyStyle(path, edge[type + "Style"]); - }, - /** - * [saveSvg description] - * @param {[type]} options.svg [description] - * @param {[type]} options.width [description] - * @param {[type]} options.height [description] - * @param {[type]} options.downloadFileName [description] - * @param {[type]} options.onExportLineage [description] - * @return {[type]} [description] - */ - saveSvg: function ({ svg, width, height, downloadFileName, onExportLineage }) { - var that = this, - svgClone = svg.clone(true).node(), - scaleFactor = 1; - setTimeout(function () { - if (platform.name === "Firefox") { - svgClone.setAttribute("width", width); - svgClone.setAttribute("height", height); - } - const hiddenSvgEl = select("body").append("div"); - hiddenSvgEl.classed("hidden-svg", true); - hiddenSvgEl.node().appendChild(svgClone); - - const svgCloneEl = select(".hidden-svg svg"); - svgCloneEl.select("g").attr("transform", "scale(" + scaleFactor + ")"); - svgCloneEl.select("foreignObject").remove(); - - var canvasOffset = { x: 150, y: 150 }, - setWidth = svgClone.getBBox().width + canvasOffset.x, - setHeight = svgClone.getBBox().height + canvasOffset.y, - xAxis = svgClone.getBBox().x, - yAxis = svgClone.getBBox().y; - svgClone.attributes.viewBox.value = xAxis + "," + yAxis + "," + setWidth + "," + setHeight; - - var canvas = document.createElement("canvas"); - canvas.id = "canvas"; - canvas.style.display = "none"; - canvas.width = svgClone.getBBox().width * scaleFactor + canvasOffset.x; - canvas.height = svgClone.getBBox().height * scaleFactor + canvasOffset.y; - - // Append Canvas in DOM - select("body").node().appendChild(canvas); - - var ctx = canvas.getContext("2d"), - data = new XMLSerializer().serializeToString(svgClone), - DOMURL = window.URL || window.webkitURL || window; - - ctx.fillStyle = "#FFFFFF"; - ctx.fillRect(0, 0, canvas.width, canvas.height); - ctx.strokeRect(0, 0, canvas.width, canvas.height); - ctx.restore(); - - var img = new Image(canvas.width, canvas.height); - var svgBlob = new Blob([data], { type: "image/svg+xml;base64" }); - if (platform.name === "Safari") { - svgBlob = new Blob([data], { type: "image/svg+xml" }); - } - var url = DOMURL.createObjectURL(svgBlob); - - img.onload = function () { - try { - var a = document.createElement("a"); - a.download = downloadFileName; - document.body.appendChild(a); - ctx.drawImage(img, 50, 50, canvas.width, canvas.height); - canvas.toBlob(function (blob) { - if (!blob) { - onExportLineage({ status: "failed", message: "There was an error in downloading Lineage!" }); - return; - } - a.href = DOMURL.createObjectURL(blob); - if (blob.size > 10000000) { - onExportLineage({ status: "failed", message: "The Image size is huge, please open the image in a browser!" }); - } - a.click(); - onExportLineage({ status: "Success", message: "Successful" }); - if (platform.name === "Safari") { - that.refreshGraphForSafari({ - edgeEl: that.$("svg g.node") - }); - } - }, "image/png"); - hiddenSvgEl.remove(); - canvas.remove(); - } catch (err) { - onExportLineage({ status: "failed", message: "There was an error in downloading Lineage!" }); - } - }; - img.src = url; - }, 0); - } -}; -export default LineageUtils; \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/index.js b/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/index.js deleted file mode 100644 index f7153167c24..00000000000 --- a/dashboardv2/public/js/external_lib/atlas-lineage/src/Utils/index.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import LineageUtils from "./LineageUtils"; -import DataUtils from "./DataUtils"; - -String.prototype.trunc = - String.prototype.trunc || - function(n) { - return this.length > n ? this.substr(0, n - 1) + "..." : this; - }; - -export { LineageUtils, DataUtils }; \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/src/index.js b/dashboardv2/public/js/external_lib/atlas-lineage/src/index.js deleted file mode 100644 index 3ceb3d90a90..00000000000 --- a/dashboardv2/public/js/external_lib/atlas-lineage/src/index.js +++ /dev/null @@ -1,655 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import dagreD3 from "dagre-d3"; -import { select, selection, event } from "d3-selection"; -import { curveBasis } from "d3-shape"; -import { LineageUtils, DataUtils } from "./Utils"; -import d3Tip from "d3-tip"; - -import "./styles/style.scss"; - -export default class LineageHelper { - constructor(options) { - this.options = {}; - this._updateOptions(options); - const { el, manualTrigger = false } = this.options; - if (el === undefined) { - throw new Error("LineageHelper requires el propety to render the graph"); - } - this.initReturnObj = { - init: (arg) => this.init(arg), - updateOptions: (options) => this._updateAllOptions(options), - createGraph: (opt = {}) => this._createGraph(this.options, this.graphOptions, opt), - clear: (arg) => this.clear(arg), - refresh: (arg) => this.refresh(arg), - centerAlign: (arg) => this.centerAlign(arg), - exportLineage: (arg) => this.exportLineage(arg), - zoomIn: (arg) => this.zoomIn(arg), - zoomOut: (arg) => this.zoomOut(arg), - zoom: (arg) => this.zoom(arg), - fullScreen: (arg) => this.fullScreen(arg), - searchNode: (arg) => this.searchNode(arg), - removeNodeSelection: (arg) => this.removeNodeSelection(arg), - getGraphOptions: () => this.graphOptions, - getNode: (guid, actual) => { - let rObj = null; - if (actual) { - rObj = this.actualData[guid]; - } else { - rObj = this.g._nodes[guid]; - } - if (rObj) { - rObj = Object.assign({}, rObj); - } - return rObj; - }, - getNodes: (guid, actual) => { - let rObj = null; - if (actual) { - rObj = this.actualData; - } else { - rObj = this.g._nodes; - } - if (rObj) { - rObj = Object.assign({}, rObj); - } - return rObj; - }, - setNode: this._setGraphNode, - setEdge: this._setGraphEdge - }; - if (manualTrigger === false) { - this.init(); - } - return this.initReturnObj; - } - /** - * [updateAllOptions] - * @param {[type]} - * @return {[type]} - */ - _updateAllOptions(options) { - Object.assign(this.options, options); - var svgRect = this.svg.node().getBoundingClientRect(); - this.graphOptions.width = this.options.width || svgRect.width; - this.graphOptions.height = this.options.height || svgRect.height; - const { svg, width, height, guid } = this.graphOptions; - const { fitToScreen } = this.options; - svg.select("g").node().removeAttribute("transform"); - svg.attr("viewBox", "0 0 " + width + " " + height).attr("enable-background", "new 0 0 " + width + " " + height); - this.centerAlign({ fitToScreen, guid }); - } - /** - * [updateOptions get the options from user and appedn add it in this,option context] - * @param {[Object]} options [lib options from user] - * @return {[null]} [null] - */ - _updateOptions(options) { - Object.assign(this.options, { filterObj: { isProcessHideCheck: false, isDeletedEntityHideCheck: false } }, options); - } - /** - * [init Start the graph build process] - * @return {[null]} [null] - */ - init() { - const { data = {} } = this.options; - if (data.baseEntityGuid) { - this.guid = data.baseEntityGuid; - } - // Call the initializeGraph method to initlize dagreD3 graphlib - this._initializeGraph(); - this._initGraph(); - } - /** - * [clear Allows user to clear the graph refrence and dom] - * @return {[type]} [description] - */ - clear() { - if (!this.options.el) { - this.svg.remove(); - this.svg = null; - } - this.g = null; - this.graphOptions = {}; - } - /** - * [centerAlign Allows user to center the lineage position, without rerender] - * @return {[type]} [description] - */ - centerAlign(opt = {}) { - var svgGroupEl = this.svg.select("g"), - edgePathEl = svgGroupEl.selectAll("g.edgePath"); - LineageUtils.centerNode({ - ...this.graphOptions, - svgGroupEl, - edgePathEl, - ...opt - }); - } - /** - * [zoomIn description] - * @return {[type]} [description] - */ - zoomIn(opt = {}) { - LineageUtils.zoomIn({ ...this.graphOptions, ...opt }); - } - /** - * [zoomOut description] - * @return {[type]} [description] - */ - zoomOut(opt = {}) { - LineageUtils.zoomOut({ ...this.graphOptions, ...opt }); - } - /** - * [zoom description] - * @return {[type]} [description] - */ - zoom(opt = {}) { - LineageUtils.zoom({ ...this.graphOptions, ...opt }); - } - /** - * [refresh Allows user to rerender the lineage] - * @return {[type]} [description] - */ - refresh() { - this.clear(); - this._initializeGraph(); - this._initGraph({ refresh: true }); - } - /** - * [removeNodeSelection description] - * @return {[type]} [description] - */ - removeNodeSelection() { - this.svg.selectAll("g.node>circle").classed("node-detail-highlight", false); - } - /** - * [searchNode description] - * @return {[type]} [description] - */ - searchNode({ guid, onSearchNode }) { - this.svg.selectAll(".serach-rect").remove(); - this.centerAlign({ - guid: guid, - onCenterZoomed: function (opts) { - const { selectedNodeEl } = opts; - selectedNodeEl.select(".label").attr("stroke", "#316132"); - selectedNodeEl.select("circle").classed("wobble", true); - selectedNodeEl - .insert("rect", "circle") - .attr("class", "serach-rect") - .attr("x", -50) - .attr("y", -27.5) - .attr("width", 100) - .attr("height", 55); - if (onSearchNode && typeof onSearchNode === "function") { - onSearchNode(opts); - } - } - }); - } - - /** - * [exportLineage description] - * @param {Object} options [description] - * @return {[type]} [description] - */ - exportLineage(options = {}) { - let downloadFileName = options.downloadFileName; - if (downloadFileName === undefined) { - let node = this.g._nodes[this.guid]; - if (node && node.attributes) { - downloadFileName = `${node.attributes.qualifiedName || node.attributes.name || "lineage_export"}.png`; - } else { - downloadFileName = "export.png"; - } - } - - LineageUtils.saveSvg({ - ...this.graphOptions, - downloadFileName: downloadFileName, - onExportLineage: (opt) => { - if (options.onExportLineage) { - onExportLineage(opt); - } - } - }); - } - /** - * [fullScreen description] - * @param {Object} options.el } [description] - * @return {[type]} [description] - */ - fullScreen({ el } = {}) { - if (el === undefined) { - throw new Error("LineageHelper requires el propety to apply fullScreen class"); - } - const fullScreenEl = select(el); - if (fullScreenEl.classed("fullscreen-mode")) { - fullScreenEl.classed("fullscreen-mode", false); - return false; - } else { - fullScreenEl.classed("fullscreen-mode", true); - return true; - } - } - /** - * [_getValueFromUser description] - * @param {[type]} ref [description] - * @return {[type]} [description] - */ - _getValueFromUser(ref) { - if (ref !== undefined) { - if (typeof ref === "function") { - return ref(); - } else { - return ref; - } - } - return; - } - /** - * [initializeGraph initlize the dagreD3 graphlib] - * @return {[null]} [null] - */ - _initializeGraph() { - const { width = "100%", height = "100%", el } = this.options; - - // Append the svg using d3. - this.svg = select(el); - - if (!(el instanceof SVGElement)) { - this.svg.selectAll("*").remove(); - this.svg = this.svg - .append("svg") - .attr("xmlns", "http://www.w3.org/2000/svg") - .attr(" xmlns:xlink", "http://www.w3.org/1999/xlink") - .attr("version", "1.1") - .attr("width", width) - .attr("height", height); - } - // initlize the dagreD3 graphlib - this.g = new dagreD3.graphlib.Graph() - .setGraph( - Object.assign( - { - nodesep: 50, - ranksep: 90, - rankdir: "LR", - marginx: 20, - marginy: 20, - transition: function transition(selection) { - return selection.transition().duration(500); - } - }, - this.options.dagreOptions - ) - ) - .setDefaultEdgeLabel(function () { - return {}; - }); - - // Create graphOptions for common use - var svgRect = this.svg.node().getBoundingClientRect(); - this.actualData = {}; - this.graphOptions = { - svg: this.svg, - g: this.g, - dagreD3: dagreD3, - guid: this.guid, - width: this.options.width || svgRect.width, - height: this.options.height || svgRect.height - }; - } - /** - * [_initGraph description] - * @return {[type]} [description] - */ - _initGraph({ refresh } = {}) { - if (this.svg) { - this.svg.select("g").remove(); - } - let filterObj = this.options.filterObj; - if (this.options.getFilterObj) { - let filterObjVal = this.options.getFilterObj(); - if (filterObjVal !== undefined || filterObjVal !== null) { - if (typeof filterObjVal === "object") { - filterObj = filterObjVal; - } else { - throw new Error("getFilterObj expect return type `object`,`null` or `Undefined`"); - } - } - } - - if (this.options.setDataManually === true) { - return; - } else if (this.options.data === undefined || (this.options.data && this.options.data.relations.length === 0)) { - if (this.options.beforeRender) { - this.options.beforeRender(); - } - this.svg - .append("text") - .attr("x", "50%") - .attr("y", "50%") - .attr("alignment-baseline", "middle") - .attr("text-anchor", "middle") - .text("No lineage data found"); - if (this.options.afterRender) { - this.options.afterRender(); - } - return; - } - - return DataUtils.generateData({ - ...this.options, - filterObj: filterObj, - ...this.graphOptions, - setGraphNode: this._setGraphNode, - setGraphEdge: this._setGraphEdge - }).then((graphObj) => { - this._createGraph(this.options, this.graphOptions, { refresh }); - }); - } - - /** - * [description] - * @param {[type]} guid [description] - * @param {[type]} nodeData [description] - * @return {[type]} [description] - */ - _setGraphNode = (guid, nodeData) => { - this.actualData[guid] = Object.assign({}, nodeData); - this.g.setNode(guid, nodeData); - }; - - /** - * [description] - * @param {[type]} fromGuid [description] - * @param {[type]} toGuid [description] - * @param {[type]} opts [description] - * @return {[type]} [description] - */ - _setGraphEdge = (fromGuid, toGuid, opts) => { - this.g.setEdge(fromGuid, toGuid, { - curve: curveBasis, - ...opts - }); - }; - /** - * [_createGraph description] - * @param {Object} options.data [description] - * @param {Boolean} isShowTooltip [description] - * @param {Boolean} isShowHoverPath [description] - * @param {[type]} onLabelClick [description] - * @param {[type]} onPathClick [description] - * @param {[type]} onNodeClick } [description] - * @param {[type]} graphOptions [description] - * @return {[type]} [description] - */ - _createGraph( - { - data = {}, - imgBasePath, - isShowTooltip, - isShowHoverPath, - onLabelClick, - onPathClick, - onNodeClick, - zoom, - fitToScreen, - getToolTipContent, - toolTipTitle - }, - graphOptions, - { refresh } - ) { - if (this.options.beforeRender) { - this.options.beforeRender(); - } - const that = this, - { svg, g, width, height } = graphOptions, - isRankdirToBottom = this.options.dagreOptions && this.options.dagreOptions.rankdir === "tb"; - - if (svg instanceof selection === false) { - throw new Error("svg is not initialized or something went wrong while creatig graph instance"); - return; - } - if (g._nodes === undefined || g._nodes.length === 0) { - svg.html('No relations to display'); - return; - } - - g.nodes().forEach(function (v) { - var node = g.node(v); - // Round the corners of the nodes - if (node) { - node.rx = node.ry = 5; - } - }); - - svg.attr("viewBox", "0 0 " + width + " " + height).attr("enable-background", "new 0 0 " + width + " " + height); - var svgGroupEl = svg.append("g"); - - // Append defs - var defsEl = svg.append("defs"); - - // Create the renderer - var render = new dagreD3.render(); - // Add our custom arrow (a hollow-point) - render.arrows().arrowPoint = function () { - return LineageUtils.arrowPointRender(...arguments, { ...graphOptions }); - }; - // Render custom img inside shape - render.shapes().img = function () { - return LineageUtils.imgShapeRender(...arguments, { - ...graphOptions, - isRankdirToBottom: isRankdirToBottom, - imgBasePath: that._getValueFromUser(imgBasePath), - defsEl - }); - }; - - var tooltip = d3Tip() - .attr("class", "d3-tip") - .offset([10, 0]) - .html((d) => { - if (getToolTipContent && typeof getToolTipContent === "function") { - return getToolTipContent(d, g.node(d)); - } else { - var value = g.node(d); - var htmlStr = ""; - if (toolTipTitle) { - htmlStr = "
    " + toolTipTitle + "
    "; - } else if (value.id !== this.guid) { - htmlStr = "
    " + (value.isLineage ? "Lineage" : "Impact") + "
    "; - } - - htmlStr += "
    " + value.toolTipLabel + "
    "; - if (value.typeName) { - htmlStr += "
    (" + value.typeName + ")
    "; - } - if (value.queryText) { - htmlStr += "
    Query: " + value.queryText + "
    "; - } - return "
    " + htmlStr + "
    "; - } - }); - - svg.call(tooltip); - - // if (platform.name !== "IE") { - // this.$(".fontLoader").hide(); - // } - - render(svgGroupEl, g); - - //change text postion - svgGroupEl - .selectAll("g.nodes g.label") - .attr("transform", () => { - if (isRankdirToBottom) { - return "translate(2,-20)"; - } - return "translate(2,-35)"; - }) - .on("mouseenter", function (d) { - event.preventDefault(); - select(this).classed("highlight", true); - }) - .on("mouseleave", function (d) { - event.preventDefault(); - select(this).classed("highlight", false); - }) - .on("click", function (d) { - event.preventDefault(); - if (onLabelClick && typeof onLabelClick === "function") { - onLabelClick({ clickedData: d }); - } - tooltip.hide(d); - }); - - svgGroupEl - .selectAll("g.nodes g.node circle") - .on("mouseenter", function (d, index, element) { - that.activeNode = true; - var matrix = this.getScreenCTM().translate(+this.getAttribute("cx"), +this.getAttribute("cy")); - that.svg.selectAll(".node").classed("active", false); - select(this).classed("active", true); - if (that._getValueFromUser(isShowTooltip)) { - var direction = LineageUtils.getToolTipDirection({ el: this }); - tooltip.direction(direction).show(d, this); - } - if (that._getValueFromUser(isShowHoverPath) === false) { - return; - } - LineageUtils.onHoverFade({ - opacity: 0.3, - mouseenter: true, - hoveredNode: d, - ...graphOptions - }); - }) - .on("mouseleave", function (d) { - that.activeNode = false; - var nodeEL = this; - setTimeout(function (argument) { - if (!(that.activeTip || that.activeNode)) { - select(nodeEL).classed("active", false); - if (that._getValueFromUser(isShowTooltip)) { - tooltip.hide(d); - } - } - }, 150); - if (that._getValueFromUser(isShowHoverPath) === false) { - return; - } - LineageUtils.onHoverFade({ - mouseenter: false, - hoveredNode: d, - ...graphOptions - }); - }) - .on("click", function (d) { - if (event.defaultPrevented) return; // ignore drag - event.preventDefault(); - tooltip.hide(d); - svg.selectAll("g.node>circle").classed("node-detail-highlight", false); - select(this).classed("node-detail-highlight", true); - if (onNodeClick && typeof onNodeClick === "function") { - onNodeClick({ clickedData: d, el: this }); - } - }); - - // Bind event on edgePath - var edgePathEl = svgGroupEl.selectAll("g.edgePath"); - edgePathEl.selectAll("path.path").on("click", function (d) { - if (onPathClick && typeof onPathClick === "function") { - var pathRelationObj = data.relations.find(function (obj) { - if (obj.fromEntityId === d.v && obj.toEntityId === d.w) { - return true; - } - }); - onPathClick({ pathRelationObj, clickedData: d }); - } - }); - - // tooltip hover handle to fix node hover conflict - // select("body").on("mouseover", ".d3-tip", function(el) { - // that.activeTip = true; - // }); - // select("body").on("mouseleave", ".d3-tip", function(el) { - // that.activeTip = false; - // svg.selectAll(".node").classed("active", false); - // //tooltip.hide(); - // }); - - // Center the graph - if (zoom !== false) { - LineageUtils.centerNode({ - ...graphOptions, - fitToScreen, - svgGroupEl, - edgePathEl - }); - } - - // if (platform.name === "IE") { - // LineageUtils.refreshGraphForIE({ - // edgeEl: this.$("svg .edgePath") - // }); - // } - - LineageUtils.dragNode({ - ...graphOptions, - edgePathEl - }); - - if (refresh !== true) { - this._addLegend(); - } - - if (this.options.afterRender) { - this.options.afterRender(); - } - } - _addLegend() { - if (this.options.legends === false) { - return; - } - var container = select(this.options.legendsEl || this.options.el) - .insert("div", ":first-child") - .classed("legends", true); - - let span = container.append("span").style("color", "#fb4200"); - span.append("i").classed("fa fa-circle-o fa-fw", true); - span.append("span").html("Current Entity"); - - span = container.append("span").style("color", "#686868"); - span.append("i").classed("fa fa-hourglass-half fa-fw", true); - span.append("span").html("In Progress"); - - span = container.append("span").style("color", "#df9b00"); - span.append("i").classed("fa fa-long-arrow-right fa-fw", true); - span.append("span").html("Lineage"); - - span = container.append("span").style("color", "#fb4200"); - span.append("i").classed("fa fa-long-arrow-right fa-fw", true); - span.append("span").html("Impact"); - } -} \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/src/styles/__varibale.scss b/dashboardv2/public/js/external_lib/atlas-lineage/src/styles/__varibale.scss deleted file mode 100644 index 1fb20d9c056..00000000000 --- a/dashboardv2/public/js/external_lib/atlas-lineage/src/styles/__varibale.scss +++ /dev/null @@ -1,35 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -//fonts -$font_0: Source Sans Pro; -$font_1: sans-serif; - -//Colors - -$white: #fff; -$dark_gray: #666; -$light_gray: #e8e8e8; -$black_80: rgba(0, 0, 0, 0.8); - -$color_mountain_mist_approx: #999; -$color_keppel_approx: #37bb9b; -$color_suva_gray_approx: #868686; -$color_havelock_blue_approx: #4a90e2; -$color_celeste_approx: #ccc; -$color_bright_turquoise_approx: #00ffd0; -$color_jungle_green_approx: #38bb9b; -$delete_link: #bb5838; \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/src/styles/graph.scss b/dashboardv2/public/js/external_lib/atlas-lineage/src/styles/graph.scss deleted file mode 100644 index ab1e82df38c..00000000000 --- a/dashboardv2/public/js/external_lib/atlas-lineage/src/styles/graph.scss +++ /dev/null @@ -1,278 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -/* graph.scss */ - -.node { - cursor: pointer; - - text { - font-size: 10px; - font-family: $font_1; - } - - //transition: opacity 0.3s linear; - - rect { - stroke: $color_mountain_mist_approx; - fill: $white; - stroke-width: 1.5px; - - &.serach-rect { - stroke: $color_keppel_approx; - fill: transparent; - stroke-width: 2.5px; - } - } - - .label { - fill: $color_suva_gray_approx; - - &.highlight { - cursor: pointer; - fill: $color_havelock_blue_approx; - text-decoration: underline; - - tspan { - font-weight: 400; - } - } - } - - circle { - -moz-transition: all 0.3s; - -webkit-transition: all 0.3s; - transition: all 0.3s; - stroke-width: 1.5px; - - &.node-detail-highlight { - stroke: $color_havelock_blue_approx; - stroke-width: 2px; - } - - &.nodeImage { - &.green:hover { - stroke: #ffb203; - } - - &.blue:hover { - stroke: #4b91e2; - } - - &.currentNode { - stroke: #fb4200; - } - - &:hover { - -moz-transform: scale(1.4); - -webkit-transform: scale(1.4); - transform: scale(1.4); - } - } - } - - &.active { - circle { - -moz-transform: scale(1.4); - -webkit-transform: scale(1.4); - transform: scale(1.4); - - &.nodeImage { - &.green { - stroke: #ffb203; - } - - &.blue { - stroke: #4b91e2; - } - } - } - } -} - -.legends { - > span { - margin-right: 8px; - font-family: $font_0; - } -} - -svg.hover { - g.node { - opacity: 0.1 !important; - } - - g.edgePath { - opacity: 0 !important; - } - - g.node.hover-active-node, - g.edgePath.hover-active-path { - opacity: 1 !important; - } -} - -.invisible { - .node circle { - transition: all 0s; - } -} - -.edgePath { - .path { - cursor: pointer; - } -} - -.link { - fill: none; - stroke: $color_celeste_approx; - stroke-width: 1.5px; -} - -.text-center { - text-align: center; -} - -.d3-tip { - line-height: 1; - font-weight: bold; - padding: 12px; - background: $black_80; - color: $white; - z-index: 999; - max-width: 300px; //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 2px; - - .tip-inner-scroll { - overflow: auto; - max-height: 300px; - h5 { - margin: 7px 0px; - } - } - - /* Creates a small triangle extender for the tooltip */ - &:after { - box-sizing: border-box; - display: inline; - font-size: 10px; - width: 100%; - line-height: 1; - color: rgba(0, 0, 0, 0.8); - position: absolute; - } - - /* Nrthward tooltips */ - &.n:after { - content: "\25BC"; - margin: -1px 0 0 0; - top: 100%; - left: 0; - text-align: center; - } - - /* Eastward tooltips */ - &.e:after { - content: "\25C0"; - margin: -4px 0 0 0; - top: 50%; - left: -8px; - } - - /* Southward tooltips */ - &.s:after { - content: "\25B2"; - margin: 0 0 1px 0; - top: -8px; - left: 0; - text-align: center; - } - - /* Westward tooltips */ - &.w:after { - content: "\25B6"; - margin: -4px 0 0 -1px; - top: 50%; - left: 100%; - } -} - -g.type-TK > rect { - fill: $color_bright_turquoise_approx; -} - -.fullscreen-mode { - position: fixed; - height: 100% !important; - top: 0; - bottom: 0; - left: 0; - width: 100%; - right: 0; - padding: 0 !important; - z-index: 9999; - overflow: hidden !important; - - .resizeGraph { - position: fixed; - height: 100% !important; - - .ui-resizable-handle { - display: none; - } - } - - .lineage-box { - padding: 10px !important; - } - - .box-panel { - margin: 10px !important; - } -} - -@keyframes zoominoutsinglefeatured { - 0% { - transform: scale(1, 1); - } - - 50% { - transform: scale(1.2, 1.2); - } - - 100% { - transform: scale(1, 1); - } -} - -.wobble { - animation: zoominoutsinglefeatured 1s 5; -} - -.hidden-svg { - visibility: hidden; -} - -@-webkit-keyframes blink { - from { - opacity: 0.2; - } - - to { - opacity: 0.5; - } -} \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/src/styles/style.scss b/dashboardv2/public/js/external_lib/atlas-lineage/src/styles/style.scss deleted file mode 100644 index 7a7ac77e742..00000000000 --- a/dashboardv2/public/js/external_lib/atlas-lineage/src/styles/style.scss +++ /dev/null @@ -1,19 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -@import "./__varibale.scss"; -@import "./graph.scss"; - diff --git a/dashboardv2/public/js/external_lib/atlas-lineage/webpack.config.js b/dashboardv2/public/js/external_lib/atlas-lineage/webpack.config.js deleted file mode 100644 index 020603f206b..00000000000 --- a/dashboardv2/public/js/external_lib/atlas-lineage/webpack.config.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -const path = require("path"); -const MiniCssExtractPlugin = require("mini-css-extract-plugin"); - -const distPath = path.resolve(__dirname, "dist"); - -const node_env = process.env.NODE_ENV ? process.env.NODE_ENV : 'production'; - -const config = { - mode: node_env, - entry: "./src/index.js", - output: { - library: "LineageHelper", - libraryTarget: "umd", - path: distPath, - filename: "index.js" - }, - plugins: [new MiniCssExtractPlugin({ filename: "styles.css" })], - externals: { - //don't bundle the 'react' npm package with our bundle.js - //but get it from a global 'React' variable - d3: "d3", - "dagre-d3": "dagreD3", - platform: "platform", - dagre: "dagre", - graphlib: "graphlib" - }, - module: { - rules: [ - { - test: /\.m?js$/, - exclude: /(node_modules|bower_components)/, - use: { - loader: "babel-loader", - options: { - presets: ["@babel/preset-env"], - plugins: ["transform-class-properties"] - } - } - }, - { - test: /\.s[ac]ss$/i, - use: [ - MiniCssExtractPlugin.loader, - // Translates CSS into CommonJS - "css-loader", - // Compiles Sass to CSS - "sass-loader" - ] - } - ] - } -}; - -if (process.env.NODE_ENV === "development") { - config.devtool = "inline-source-map"; -} -module.exports = config; \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/backgrid-columnmanager/css/Backgrid.ColumnManager.css b/dashboardv2/public/js/external_lib/backgrid-columnmanager/css/Backgrid.ColumnManager.css deleted file mode 100644 index 89a2446dcf6..00000000000 --- a/dashboardv2/public/js/external_lib/backgrid-columnmanager/css/Backgrid.ColumnManager.css +++ /dev/null @@ -1,114 +0,0 @@ -#control { - margin: 0 0 10px 0; -} - -div.columnmanager-visibilitycontrol { - margin: 0 auto; - position: relative; - width: 50px; -} - -div.columnmanager-visibilitycontrol > button.dropdown-button { - background-image: -moz-linear-gradient(top, #ffffff, #dbdbdb); - background-image: -webkit-gradient(linear,left top,left bottom, - color-stop(0, #ffffff),color-stop(1, #dbdbdb)); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#dbdbdb'); - -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#dbdbdb')"; - border: 1px solid #fff; - -moz-box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.4); - -webkit-box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.4); - box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.4); - text-decoration: none; - text-shadow: #fff 0 1px 0; - color: #597390; - font-weight: bold; -} - -div.columnmanager-visibilitycontrol > button.dropdown-button:hover { - background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); - background-image: -webkit-gradient(linear,left top,left bottom, - color-stop(0, #ffffff),color-stop(1, #eeeeee)); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#eeeeee'); - -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#eeeeee')"; - color: #000; -} - -div.columnmanager-visibilitycontrol > button.dropdown-button:active { - background-image: -moz-linear-gradient(top, #dbdbdb, #ffffff); - background-image: -webkit-gradient(linear,left top,left bottom, - color-stop(0, #dbdbdb),color-stop(1, #ffffff)); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#dbdbdb', EndColorStr='#ffffff'); - -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#dbdbdb', EndColorStr='#ffffff')"; - text-shadow: 0px -1px 0 rgba(255, 255, 255, 0.5); -} - -div.columnmanager-dropdown-container { - cursor: default; - position: absolute; - z-index: 10; - top: 0; - left: 0; - background: #fff; - border: solid 1px #bbb; - -webkit-box-shadow: #999999 0 1px 3px; - -moz-box-shadow: #999999 0 1px 3px; - box-shadow: #999999 0 1px 3px; - width: 200px; - display: none !important; - min-height: 20px; - max-height: 400px; - font-size: 14px; - line-height: 1.1em; - font-weight: normal; - text-align: left; - color: #444; - text-transform: none; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - pointer-events: none; -} - -div.columnmanager-dropdown-container.open { - display: block !important; - pointer-events: auto; -} - -.columnmanager-dropdown-container > li { - list-style-type:none; - padding: 5px 0px 0px 20px; - border-bottom: solid 1px lightgray; - cursor: pointer; -} - -.columnmanager-dropdown-container > li:hover { - background-color: #f0f0f0; -} - -.columnmanager-dropdown-container > li:last-child { - border-bottom: none; -} - -.columnmanager-dropdown-container > li > span.indicator { - width: 20px; - display: inline-block; -} -.columnmanager-dropdown-container > li.visible > span.indicator::before { - content: "✓"; - color: blue; -} - -.columnmanager-dropdown-container > li > span.column-label { - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - display: inline-block; - width: 150px; - } - -th.columnVisibility { - overflow: visible; -} diff --git a/dashboardv2/public/js/external_lib/backgrid-columnmanager/js/Backgrid.ColumnManager.js b/dashboardv2/public/js/external_lib/backgrid-columnmanager/js/Backgrid.ColumnManager.js deleted file mode 100644 index a77852ffe10..00000000000 --- a/dashboardv2/public/js/external_lib/backgrid-columnmanager/js/Backgrid.ColumnManager.js +++ /dev/null @@ -1,960 +0,0 @@ -"use strict"; - -/** - * A column manager for backgrid - * - * @module Backgrid.ColumnManager - */ - -// Dependencies -var _ = require("underscore"); -var $ = require("jquery"); -var Backbone = require("backbone"); -var Backgrid = require("backgrid"); - -/** - * Manages visibility of columns. - * - * @class Backgrid.Extension.ColumnManager ColumnManager - * @constructor - * @param {Backgrid.Columns} columns - * @param {Object} [options] - * @param {number} [options.initialColumnCount] Initial amount of columns to show. Default is null (All visible). - * @param {boolean} [options.trackSize] - * @param {boolean} [options.trackOrder] - * @param {boolean} [options.trackVisibility] - * @param {string} [options.stateChecking] can be "strict" or "loose". - * @param {boolean} [options.saveState] - * @param {string} [options.saveStateKey] Storage key. Must be unique for location. Can be left out if this plugin is only used in one place. - * @param {string} [options.saveStateLocation] Can be "localStorage" (default) or "sessionStorage" (be aware, session stored values are lost when window is closed) - * @param {boolean} [options.loadStateOnInit] - * @param {Array} [state] - */ -Backgrid.Extension.ColumnManager = function (columns, options, state) { - // Bind backbone events - _.extend(this, Backbone.Events); - - // Save options and merge with defaults - var defaults = { - initialColumnsVisible: null, - - // State options - trackSize: true, - trackOrder: true, - trackVisibility: true, - stateChecking: "strict", - saveState: false, - saveStateKey: "", - saveStateLocation: "localStorage", - loadStateOnInit: false - }; - this.options = _.extend({}, defaults, options); - this.state = []; - - // Check if columns is instance of Backgrid.Columns - if (columns instanceof Backgrid.Columns) { - // Save columns - this.columns = columns; - - // Add columnManager to columns (instance) - columns.columnManager = this; - this.addManagerToColumns(); - - // Set state if provided - var storedState = (this.options.loadStateOnInit) ? this.loadState() : false; - if (state && this.checkStateValidity(state)) { - this.setState(state, true); - } - else if (storedState) { - this.setState(storedState, true); - } - else { - // If no initial state is provided, adhere to initial column visibility settings - this.setInitialColumnVisibility(); - - // Set current state - this.setState(this.getStateFromColumns()); - } - - // Listen to column events - if (this.options.trackVisibility || this.options.trackSize || this.options.trackOrder) { - //this.stateUpdateHandler = _.bind(this.stateUpdateHandler, this); - var events = "" + - ((this.options.trackVisibility) ? "change:renderable " : "") + - ((this.options.trackSize) ? "resize " : "") + - ((this.options.trackOrder) ? "ordered" : ""); - this.columns.on(events, _.bind(this.stateUpdateHandler, this)); - } - } - else { - // Issue warning - console.error("Backgrid.ColumnManager: options.columns is not an instance of Backgrid.Columns"); - } -}; - -/** - * Loops over all columns and sets the visibility according to provided options. - * - * @method setInitialColumnVisibility - */ -Backgrid.Extension.ColumnManager.prototype.setInitialColumnVisibility = function () { - var self = this; - - // Loop columns and set renderable property according to settings - var initialColumnsVisible = self.options.initialColumnsVisible; - - if (initialColumnsVisible) { - self.columns.each(function (col, index) { - col.set("renderable", (col.get("alwaysVisible")) ? true : index < initialColumnsVisible); - }); - } -}; - -/** - * Loops over all columns and adds the columnManager instance to VisibilityHeaderCell columns. - * - * @method addManagerToColumns - */ -Backgrid.Extension.ColumnManager.prototype.addManagerToColumns = function () { - var self = this; - - self.columns.each(function (col) { - // Look for header cell - if (col.get("headerCell") === Backgrid.Extension.ColumnManager.ColumnVisibilityHeaderCell) { - col.set("headerCell", col.get("headerCell").extend({ - columnManager: self - })); - } - - if (col.get("headerCell") instanceof Backgrid.Extension.ColumnManager.ColumnVisibilityHeaderCell) { - col.get("headerCell").columnManager = self; - } - }); -}; - -/** - * Convenience function to retrieve a column either directly or by its id. - * Returns false if no column is found. - * - * @method getColumn - * @param {string|number|Backgrid.Column} col - * @return {Backgrid.Column|boolean} - */ -Backgrid.Extension.ColumnManager.prototype.getColumn = function (col) { - // If column is a string or number, try to find a column which has that ID - if (_.isNumber(col) || _.isString(col)) { - col = this.columns.get(col); - } - return (col instanceof Backgrid.Column) ? col : false; -}; - -/** - * Hides a column - * - * @method hidecolumn - * @param {string|number|Backgrid.Column} col - */ -Backgrid.Extension.ColumnManager.prototype.hideColumn = function (col) { - // If column is a valid backgrid column, set the renderable property to false - var column = this.getColumn(col); - if (column) { - column.set("renderable", false); - } -}; - -/** - * Shows a column - * - * @method showColumn - * @param {string|number|Backgrid.Column} col - */ -Backgrid.Extension.ColumnManager.prototype.showColumn = function (col) { - // If column is a valid backgrid column, set the renderable property to true - var column = this.getColumn(col); - if (column) { - column.set("renderable", true); - } -}; - -/** - * Toggles a columns' visibility - * - * @method toggleColumnVisibility - * @param {string|number|Backgrid.Column} col - */ -Backgrid.Extension.ColumnManager.prototype.toggleColumnVisibility = function (col) { - // If column is a valid backgrid column, set the renderable property to true - var column = this.getColumn(col); - if (column) { - if (column.get("renderable")) { - this.hideColumn(column); - } - else { - this.showColumn(column); - } - } -}; - -/** - * Returns the managed column collection - * - * @method getColumnCollection - * @return {Backgrid.Columns} - */ -Backgrid.Extension.ColumnManager.prototype.getColumnCollection = function () { - return this.columns; -}; - -/** - * - * @method setState - * @param {Array} state - * @param {boolean} applyState - * @return {boolean} - */ -Backgrid.Extension.ColumnManager.prototype.setState = function (state, applyState) { - var self = this; - - // Filter state - _.filter(state, function(columnState) { - if (!_.has(columnState, "name")) { - return false; - } - - var column = self.columns.findWhere({ - name: state.name - }); - - return typeof column !== "undefined"; - }); - - // Check if state is valid - if (self.checkStateValidity(state) && state !== self.state) { - // Apply and save state - self.state = state; - self.trigger("state-changed", state); - - if (applyState) { - return self.applyStateToColumns(); - } - else { - return self.saveState(); - } - } - return false; -}; - -/** - * @method getState - * @return {Array} - */ -Backgrid.Extension.ColumnManager.prototype.getState = function () { - return this.state; -}; - -/** - * - * @method checkStateValidity - * @return {boolean} - */ -Backgrid.Extension.ColumnManager.prototype.checkStateValidity = function (state) { - // Has to be array - if (!_.isArray(state) && _.isEmpty(state)) { - return false; - } - - function checkValidityColumnState() { - return _.every(state, function(column) { - var valid = true; - - // We require a name key - if (!_.has(column, "name")) { - valid = false; - } - - // If renderable is set, should be boolean - if (_.has(column, "renderable")) { - if (!_.isBoolean(column.renderable)) { - valid = false; - } - } - - // If displayOrder is set, should be a number - if (_.has(column, "displayOrder")) { - if (!_.isNumber(column.displayOrder)) { - valid = false; - } - } - - // If width is set, should be a number or a string - if (_.has(column, "width")) { - if (!_.isNumber(column.width) && !_.isString(column.width)) { - valid = false; - } - } - - return valid; - }); - } - - // Check if state is valid - if (this.options.stateChecking === "loose") { - // At least we require 'name' keys in every objec - return checkValidityColumnState(); - } - else { - // Strict check - // Requires same length and valid name keys. - if (state.length !== this.columns.length && !checkValidityColumnState()) { - return false; - } - - var columnNameKeys = this.columns.map(function (column) { - return column.get("name"); - }); - - var newStateNameKeys = _.map(state, function (column) { - return column.name; - }); - - return columnNameKeys.sort().toString() === newStateNameKeys.sort().toString(); - } -}; - - -/** - * - * @method loadState - * @return {boolean} - */ -Backgrid.Extension.ColumnManager.prototype.loadState = function () { - // Get state from storage - var state = JSON.parse(this.getStorage().getItem(this.getStorageKey())); - if (this.checkStateValidity(state)) { - return state; - } - return false; -}; - -/** - * - * @method saveState - * @param {boolean} [force] Override save settings. - * @return {boolean} - */ -Backgrid.Extension.ColumnManager.prototype.saveState = function (force) { - if (this.options.saveState || force) { - this.getStorage().setItem(this.getStorageKey(), JSON.stringify(this.state)); - this.trigger("state-saved"); - return true; - } - return false; -}; - -/** - * @method getStorage - * @return {boolean|Storage} - * @private - */ -Backgrid.Extension.ColumnManager.prototype.getStorage = function () { - // Check if storage functionality is available - if (typeof Storage !== "undefined") { - return (this.options.saveStateLocation === "sessionStorage") ? sessionStorage : localStorage; - } - else { - console.error("ColMrg: No storage support detected. State won't be saved."); - return false; - } -}; - -/** - * @method getStorageKey - * @return {string} - * @private - */ -Backgrid.Extension.ColumnManager.prototype.getStorageKey = function () { - return (this.options.saveStateKey) ? "backgrid-colmgr-" + this.options.saveStateKey : "backgrid-colmgr"; -}; - -/** - * @method stateUpdateHandler - * @return {boolean} - * @private - */ -Backgrid.Extension.ColumnManager.prototype.stateUpdateHandler = function () { - var state = this.getStateFromColumns(); - return this.setState(state); -}; - -/** - * @method getStateFromColumn - * @return {Array} - */ -Backgrid.Extension.ColumnManager.prototype.getStateFromColumns = function() { - var self = this; - - // Map state from columns - return this.columns.map(function(column) { - var columnState = { - name: column.get("name") - }; - - if (self.options.trackVisibility) { - columnState.renderable = column.get("renderable"); - } - if (self.options.trackOrder) { - columnState.displayOrder = column.get("displayOrder"); - } - if (self.options.trackSize) { - columnState.width = column.get("width"); - } - return columnState; - }); -}; - -/** - * @method applyStateToColumns - * @private - */ -Backgrid.Extension.ColumnManager.prototype.applyStateToColumns = function () { - var self = this; - - // Loop state - var ordered = false; - _.each(this.state, function(columnState) { - // Find column - var column = self.columns.findWhere({ - name: columnState.name - }); - - if (_.has(columnState, "renderable")) { - column.set("renderable", columnState.renderable); - } - if (_.has(columnState, "width")) { - var oldWidth = column.get("width"); - column.set("width", columnState.width, {silent: true}); - if (oldWidth !== columnState.width) { - column.trigger("resize", column, columnState.width, oldWidth); - } - } - - if (_.has(columnState, "displayOrder")) { - if (columnState.displayOrder !== column.get("displayOrder")) { - ordered = true; - } - column.set("displayOrder", columnState.displayOrder, {silent: true}); - } - }); - - if (ordered) { - self.columns.sort(); - self.columns.trigger("ordered"); - } -}; - -////////////////////////////////////////////// -/////////////// UI Controls ////////////////// -////////////////////////////////////////////// - -/** - * A dropdown item view - * - * @class DropDownItemView - * @extends Backbone.View - */ -var DropDownItemView = Backbone.View.extend({ - className: "columnmanager-dropdown-item", - tagName: "li", - - /** - * @method initialize - * @param {object} opts - * @param {Backgrid.Extension.ColumnManager} opts.columnManager ColumnManager instance. - * @param {Backgrid.Column} opts.column A backgrid column. - */ - initialize: function (opts) { - this.columnManager = opts.columnManager; - this.column = opts.column; - this.template = opts.template; - - _.bindAll(this, "render", "toggleVisibility"); - this.column.on("change:renderable", this.render, this); - this.el.addEventListener("click", this.toggleVisibility, true); - }, - - /** - * @method render - * @return {DropDownItemView} - */ - render: function () { - this.$el.empty(); - - this.$el.append(this.template({ - label: this.column.get("label") - })); - - if (this.column.get("renderable")) { - this.$el.addClass((this.column.get("renderable")) ? "visible" : null); - } - else { - this.$el.removeClass("visible"); - } - - return this; - }, - - /** - * Toggles visibility of column. - * - * @method toggleVisibility - * @param {object} e - */ - toggleVisibility: function (e) { - if (e) { - this.stopPropagation(e); - } - this.columnManager.toggleColumnVisibility(this.column); - }, - - /** - * Convenience function to stop event propagation. - * - * @method stopPropagation - * @param {object} e - * @private - */ - stopPropagation: function (e) { - e.stopPropagation(); - e.stopImmediatePropagation(); - e.preventDefault(); - } -}); - - -/** - * Dropdown view container. - * - * @class DropDownView - * @extends Backbone.view - */ -var DropDownView = Backbone.View.extend({ - /** - * @property className - * @type String - * @default "columnmanager-dropdown-container" - */ - className: "columnmanager-dropdown-container", - - /** - * @method initialize - * @param {object} opts - * @param {Backgrid.Extension.ColumnManager} opts.columnManager ColumnManager instance. - * @param {Backbone.View} opts.DropdownItemView View to be used for the items. - * @param {Function} opts.dropdownItemTemplate - */ - initialize: function (opts) { - this.options = opts; - this.columnManager = opts.columnManager; - this.ItemView = (opts.DropdownItemView instanceof Backbone.View) ? opts.DropdownItemView : DropDownItemView; - this.$dropdownButton = opts.$dropdownButton; - - this.on("dropdown:opened", this.open, this); - this.on("dropdown:closed", this.close, this); - this.columnManager.columns.on("add remove", this.render, this); - }, - - /** - * @method render - * @return {DropDownView} - */ - render: function () { - var view = this; - view.$el.empty(); - - // List all columns - this.columnManager.columns.each(function (col) { - if (!col.get("alwaysVisible")) { - view.$el.append(new view.ItemView({ - column: col, - columnManager: view.columnManager, - template: view.options.dropdownItemTemplate - }).render().el); - } - }); - - return this; - }, - - /** - * Opens the dropdown. - * - * @method open - */ - open: function () { - this.$el.addClass("open"); - - // Get button - var $button = this.$dropdownButton; - - // Align - var align; - if (this.options.align === "auto") { - // Determine what alignment fits - var viewPortWidth = document.body.clientWidth || document.body.clientWidth; - align = (($button.offset().left + this.$el.outerWidth()) > viewPortWidth) ? "left" : "right"; - } - else { - align = (this.options.align === "left" || this.options.align === "right") ? - (this.options.align === "right" ? "right" : "left") : "right"; - } - - var offset; - if (align === "left") { - // Align right by default - offset = $button.offset().left + $button.outerWidth() - this.$el.outerWidth(); - this.$el.css("left", offset + "px"); - } - else { - offset = $button.offset().left; - this.$el.css("left", offset + "px"); - } - - // Height position - var offsetHeight = $button.offset().top + $button.outerHeight(); - this.$el.css("top", offsetHeight + "px"); - }, - - /** - * Closes the dropdown. - * - * @method close - */ - close: function () { - this.$el.removeClass("open"); - } -}); - -/** - * UI control which manages visibility of columns. - * Inspired by: https://github.com/kjantzer/backbonejs-dropdown-view. - * - * @class Backgrid.Extension.ColumnManagerVisibilityControl - * @extends Backbone.View - */ -Backgrid.Extension.ColumnManagerVisibilityControl = Backbone.View.extend({ - /** - * @property tagName - * @type String - * @default "div" - */ - tagName: "div", - - /** - * @property className - * @type String - * @default "columnmanager-visibilitycontrol" - */ - className: "columnmanager-visibilitycontrol", - - /** - * @property defaultEvents - * @type Object - */ - defaultEvents: { - "click": "stopPropagation" - }, - - /** - * @property defaultOpts - * @type Object - */ - defaultOpts: { - width: null, - closeOnEsc: true, - closeOnClick: true, - openOnInit: false, - columnManager: null, - - // Button - buttonTemplate: _.template(""), - - // Container - DropdownView: DropDownView, - dropdownAlign: "auto", - - // Item view - DropdownItemView: DropDownItemView, - dropdownItemTemplate: _.template("<%= label %>") - }, - - /** - * @method initialize - * @param {Object} opts - * @param {Backgrid.Extension.ColumnManager} opts.columnManager ColumnManager instance - */ - initialize: function (opts) { - this.options = _.extend({}, this.defaultOpts, opts); - this.events = _.extend({}, this.defaultEvents, this.events || {}); - this.columnManager = opts.columnManager; - - // Option checking - if (!this.columnManager instanceof Backgrid.Extension.ColumnManager) { - console.error("Backgrid.ColumnManager: options.columns is not an instance of Backgrid.Columns"); - } - - // Bind scope to events - _.bindAll(this, "deferClose", "stopDeferClose", "closeOnEsc", "toggle", "render"); - - // UI events - document.body.addEventListener("click", this.deferClose, true); - this.el.addEventListener("click", this.stopDeferClose, true); - if (this.options.closeOnEsc) { - document.body.addEventListener("keyup", this.closeOnEsc, false); - } - this.el.addEventListener("click", this.toggle, false); - - // Create elements - this.setup(); - - // Listen for dropdown view events indicating to open and/or close - this.view.on("dropdown:close", this.close, this); - this.view.on("dropdown:open", this.open, this); - }, - - /** - * @method delayStart - * @private - */ - delayStart: function () { - clearTimeout(this.closeTimeout); - this.delayTimeout = setTimeout(this.open.bind(this), this.options.delay); - }, - - /** - * @method delayEnd - * @private - */ - delayEnd: function () { - clearTimeout(this.delayTimeout); - this.closeTimeout = setTimeout(this.close.bind(this), 300); - }, - - /** - * @method setup - * @private - */ - setup: function () { - // Override element width - if (this.options.width) { - this.$el.width(this.options.width + "px"); - } - - // Create button element - this.$dropdownButton = $(this.options.buttonTemplate()); - - var viewOptions = { - columnManager: this.columnManager, - DropdownItemView: this.options.DropdownItemView, - dropdownItemTemplate: this.options.dropdownItemTemplate, - align: this.options.dropdownAlign, - $dropdownButton: this.$dropdownButton - }; - - // Check if a different childView has been provided, if not, use default dropdown view - this.view = (this.options.DropdownView instanceof Backbone.View) ? - new this.options.DropdownView(viewOptions) : - new DropDownView(viewOptions); - }, - - /** - * @method setup - */ - render: function () { - this.$el.empty(); - - // Render button - this.$el.append(this.$dropdownButton); - - // Render inner view - this.view.render(); // tell the inner view to render itself - $(document.body).append(this.view.el); - return this; - }, - - /** - * Convenience function to stop event propagation - * - * @method stopPropagation - * @param {object} e - * @private - */ - stopPropagation: function (e) { - e.stopPropagation(); - e.stopImmediatePropagation(); - e.preventDefault(); - }, - - /** - * Toggle the dropdown visibility - * - * @method toggle - * @param {object} [e] - */ - toggle: function (e) { - if (this.isOpen !== true) { - this.open(e); - } - else { - this.close(e); - } - }, - - /** - * Open the dropdown - * - * @method open - * @param {object} [e] - */ - open: function (e) { - clearTimeout(this.closeTimeout); - clearTimeout(this.deferCloseTimeout); - - if (e) { - if (e.stopPropagation) { - e.stopPropagation(); - } - if (e.preventDefault) { - e.preventDefault(); - } - e.cancelBubble = true; - } - - // Don't do anything if already open - if (this.isOpen) { - return; - } - - this.isOpen = true; - this.$el.addClass("open"); - this.trigger("dropdown:opened"); - - // Notify child view - this.view.trigger("dropdown:opened"); - }, - - /** - * Close the dropdown - * - * @method close - * @param {object} [e] - */ - close: function (e) { - // Don't do anything if already closed - if (!this.isOpen) { - return; - } - - this.isOpen = false; - this.$el.removeClass("open"); - this.trigger("dropdown:closed"); - - // Notify child view - this.view.trigger("dropdown:closed"); - }, - - /** - * Close the dropdown on esc - * - * @method closeOnEsc - * @param {object} e - * @private - */ - closeOnEsc: function (e) { - if (e.which === 27) { - this.deferClose(); - } - }, - - /** - * @method deferClose - * @private - */ - deferClose: function () { - this.deferCloseTimeout = setTimeout(this.close.bind(this), 0); - }, - - /** - * @method stopDeferClose - * @private - */ - stopDeferClose: function (e) { - clearTimeout(this.deferCloseTimeout); - }, - - /** - * Clean up this control - * - * @method remove - * @chainable - */ - remove: function () { - // Remove event listeners - document.body.removeEventListener("click", this.deferClose); - this.el.removeEventListener("click", this.stopDeferClose); - if (this.options.closeOnEsc) { - document.body.removeEventListener("keyup", this.closeOnEsc); - } - this.el.removeEventListener("click", this.toggle); - - // Remove DOM element - $(this.view.el).remove(); - - // Invoke original backbone methods - return Backbone.View.prototype.remove.apply(this, arguments); - } -}); - -/** - * Backgrid HeaderCell containing ColumnManagerVisibilityControl - * - * @class Backgrid.Extension.ColumnVisibilityHeaderCell - * @extends Backgrid.HeaderCell - */ - -Backgrid.Extension.ColumnManager.ColumnVisibilityHeaderCell = Backgrid.HeaderCell.extend({ - initialize: function (options) { - Backgrid.HeaderCell.prototype.initialize.apply(this, arguments); - - // Add class - this.$el.addClass(this.column.get("name")); - }, - render: function () { - this.$el.empty(); - - // Add control - var colVisibilityControl = this.colVisibilityControl = new Backgrid.Extension.ColumnManagerVisibilityControl({ - columnManager: this.columnManager - }); - - // Add to header - this.$el.html(colVisibilityControl.render().el); - - this.delegateEvents(); - return this; - }, - - /** - * Clean up this cell. - * - * @method remove - * @chainable - */ - remove: function () { - // Remove UI control - this.colVisibilityControl.remove(); - - // Invoke super - /*eslint no-underscore-dangle:0*/ - return Backgrid.HeaderCell.__super__.remove.apply(this, arguments); - } -}); diff --git a/dashboardv2/public/js/external_lib/es5-shim.min.js b/dashboardv2/public/js/external_lib/es5-shim.min.js deleted file mode 100644 index aa8175b18eb..00000000000 --- a/dashboardv2/public/js/external_lib/es5-shim.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * https://github.com/es-shims/es5-shim - * @license es5-shim Copyright 2009-2015 by contributors, MIT License - * see https://github.com/es-shims/es5-shim/blob/v4.5.7/LICENSE - */ -(function(t,r){"use strict";if(typeof define==="function"&&define.amd){define(r)}else if(typeof exports==="object"){module.exports=r()}else{t.returnExports=r()}})(this,function(){var t=Array;var r=t.prototype;var e=Object;var n=e.prototype;var i=Function;var a=i.prototype;var o=String;var f=o.prototype;var u=Number;var l=u.prototype;var s=r.slice;var c=r.splice;var v=r.push;var h=r.unshift;var p=r.concat;var y=r.join;var d=a.call;var g=a.apply;var w=Math.max;var b=Math.min;var T=n.toString;var m=typeof Symbol==="function"&&typeof Symbol.toStringTag==="symbol";var D;var x=Function.prototype.toString,S=/^\s*class /,O=function isES6ClassFn(t){try{var r=x.call(t);var e=r.replace(/\/\/.*\n/g,"");var n=e.replace(/\/\*[.\s\S]*\*\//g,"");var i=n.replace(/\n/gm," ").replace(/ {2}/g," ");return S.test(i)}catch(a){return false}},E=function tryFunctionObject(t){try{if(O(t)){return false}x.call(t);return true}catch(r){return false}},j="[object Function]",I="[object GeneratorFunction]",D=function isCallable(t){if(!t){return false}if(typeof t!=="function"&&typeof t!=="object"){return false}if(m){return E(t)}if(O(t)){return false}var r=T.call(t);return r===j||r===I};var M;var U=RegExp.prototype.exec,F=function tryRegexExec(t){try{U.call(t);return true}catch(r){return false}},N="[object RegExp]";M=function isRegex(t){if(typeof t!=="object"){return false}return m?F(t):T.call(t)===N};var C;var k=String.prototype.valueOf,R=function tryStringObject(t){try{k.call(t);return true}catch(r){return false}},A="[object String]";C=function isString(t){if(typeof t==="string"){return true}if(typeof t!=="object"){return false}return m?R(t):T.call(t)===A};var P=e.defineProperty&&function(){try{var t={};e.defineProperty(t,"x",{enumerable:false,value:t});for(var r in t){return false}return t.x===t}catch(n){return false}}();var $=function(t){var r;if(P){r=function(t,r,n,i){if(!i&&r in t){return}e.defineProperty(t,r,{configurable:true,enumerable:false,writable:true,value:n})}}else{r=function(t,r,e,n){if(!n&&r in t){return}t[r]=e}}return function defineProperties(e,n,i){for(var a in n){if(t.call(n,a)){r(e,a,n[a],i)}}}}(n.hasOwnProperty);var J=function isPrimitive(t){var r=typeof t;return t===null||r!=="object"&&r!=="function"};var Y=u.isNaN||function(t){return t!==t};var Z={ToInteger:function ToInteger(t){var r=+t;if(Y(r)){r=0}else if(r!==0&&r!==1/0&&r!==-(1/0)){r=(r>0||-1)*Math.floor(Math.abs(r))}return r},ToPrimitive:function ToPrimitive(t){var r,e,n;if(J(t)){return t}e=t.valueOf;if(D(e)){r=e.call(t);if(J(r)){return r}}n=t.toString;if(D(n)){r=n.call(t);if(J(r)){return r}}throw new TypeError},ToObject:function(t){if(t==null){throw new TypeError("can't convert "+t+" to object")}return e(t)},ToUint32:function ToUint32(t){return t>>>0}};var z=function Empty(){};$(a,{bind:function bind(t){var r=this;if(!D(r)){throw new TypeError("Function.prototype.bind called on incompatible "+r)}var n=s.call(arguments,1);var a;var o=function(){if(this instanceof a){var i=g.call(r,this,p.call(n,s.call(arguments)));if(e(i)===i){return i}return this}else{return g.call(r,t,p.call(n,s.call(arguments)))}};var f=w(0,r.length-n.length);var u=[];for(var l=0;l1){a=arguments[1]}if(!D(t)){throw new TypeError("Array.prototype.forEach callback must be a function")}while(++n1){o=arguments[1]}if(!D(r)){throw new TypeError("Array.prototype.map callback must be a function")}for(var f=0;f1){o=arguments[1]}if(!D(t)){throw new TypeError("Array.prototype.filter callback must be a function")}for(var f=0;f1){i=arguments[1]}if(!D(t)){throw new TypeError("Array.prototype.every callback must be a function")}for(var a=0;a1){i=arguments[1]}if(!D(t)){throw new TypeError("Array.prototype.some callback must be a function")}for(var a=0;a=2){a=arguments[1]}else{do{if(i in e){a=e[i++];break}if(++i>=n){throw new TypeError("reduce of empty array with no initial value")}}while(true)}for(;i=2){i=arguments[1]}else{do{if(a in e){i=e[a--];break}if(--a<0){throw new TypeError("reduceRight of empty array with no initial value")}}while(true)}if(a<0){return i}do{if(a in e){i=t(i,e[a],a,r)}}while(a--);return i}},!at);var ot=r.indexOf&&[0,1].indexOf(1,2)!==-1;$(r,{indexOf:function indexOf(t){var r=et&&C(this)?X(this,""):Z.ToObject(this);var e=Z.ToUint32(r.length);if(e===0){return-1}var n=0;if(arguments.length>1){n=Z.ToInteger(arguments[1])}n=n>=0?n:w(0,e+n);for(;n1){n=b(n,Z.ToInteger(arguments[1]))}n=n>=0?n:e-Math.abs(n);for(;n>=0;n--){if(n in r&&t===r[n]){return n}}return-1}},ft);var ut=function(){var t=[1,2];var r=t.splice();return t.length===2&&_(r)&&r.length===0}();$(r,{splice:function splice(t,r){if(arguments.length===0){return[]}else{return c.apply(this,arguments)}}},!ut);var lt=function(){var t={};r.splice.call(t,0,0,1);return t.length===1}();$(r,{splice:function splice(t,r){if(arguments.length===0){return[]}var e=arguments;this.length=w(Z.ToInteger(this.length),0);if(arguments.length>0&&typeof r!=="number"){e=H(arguments);if(e.length<2){K(e,this.length-t)}else{e[1]=Z.ToInteger(r)}}return c.apply(this,e)}},!lt);var st=function(){var r=new t(1e5);r[8]="x";r.splice(1,1);return r.indexOf("x")===7}();var ct=function(){var t=256;var r=[];r[t]="a";r.splice(t+1,0,"b");return r[t]==="a"}();$(r,{splice:function splice(t,r){var e=Z.ToObject(this);var n=[];var i=Z.ToUint32(e.length);var a=Z.ToInteger(t);var f=a<0?w(i+a,0):b(a,i);var u=b(w(Z.ToInteger(r),0),i-f);var l=0;var s;while(ly){delete e[l-1];l-=1}}else if(v>u){l=i-u;while(l>f){s=o(l+u-1);h=o(l+v-1);if(G(e,s)){e[h]=e[s]}else{delete e[h]}l-=1}}l=f;for(var d=0;d=0&&!_(t)&&D(t.callee)};var Ct=Ft(arguments)?Ft:Nt;$(e,{keys:function keys(t){var r=D(t);var e=Ct(t);var n=t!==null&&typeof t==="object";var i=n&&C(t);if(!n&&!r&&!e){throw new TypeError("Object.keys called on a non-object")}var a=[];var f=xt&&r;if(i&&St||e){for(var u=0;u11){return t+1}return t},getMonth:function getMonth(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Bt(this);var r=Ht(this);if(t<0&&r>11){return 0}return r},getDate:function getDate(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Bt(this);var r=Ht(this);var e=Wt(this);if(t<0&&r>11){if(r===12){return e}var n=nr(0,t+1);return n-e+1}return e},getUTCFullYear:function getUTCFullYear(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Lt(this);if(t<0&&Xt(this)>11){return t+1}return t},getUTCMonth:function getUTCMonth(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Lt(this);var r=Xt(this);if(t<0&&r>11){return 0}return r},getUTCDate:function getUTCDate(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Lt(this);var r=Xt(this);var e=qt(this);if(t<0&&r>11){if(r===12){return e}var n=nr(0,t+1);return n-e+1}return e}},Pt);$(Date.prototype,{toUTCString:function toUTCString(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Kt(this);var r=qt(this);var e=Xt(this);var n=Lt(this);var i=Qt(this);var a=Vt(this);var o=_t(this);return rr[t]+", "+(r<10?"0"+r:r)+" "+er[e]+" "+n+" "+(i<10?"0"+i:i)+":"+(a<10?"0"+a:a)+":"+(o<10?"0"+o:o)+" GMT"}},Pt||Yt);$(Date.prototype,{toDateString:function toDateString(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=this.getDay();var r=this.getDate();var e=this.getMonth();var n=this.getFullYear();return rr[t]+" "+er[e]+" "+(r<10?"0"+r:r)+" "+n}},Pt||Zt);if(Pt||zt){Date.prototype.toString=function toString(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=this.getDay();var r=this.getDate();var e=this.getMonth();var n=this.getFullYear();var i=this.getHours();var a=this.getMinutes();var o=this.getSeconds();var f=this.getTimezoneOffset();var u=Math.floor(Math.abs(f)/60);var l=Math.floor(Math.abs(f)%60);return rr[t]+" "+er[e]+" "+(r<10?"0"+r:r)+" "+n+" "+(i<10?"0"+i:i)+":"+(a<10?"0"+a:a)+":"+(o<10?"0"+o:o)+" GMT"+(f>0?"-":"+")+(u<10?"0"+u:u)+(l<10?"0"+l:l)};if(P){e.defineProperty(Date.prototype,"toString",{configurable:true,enumerable:false,writable:true})}}var ir=-621987552e5;var ar="-000001";var or=Date.prototype.toISOString&&new Date(ir).toISOString().indexOf(ar)===-1;var fr=Date.prototype.toISOString&&new Date(-1).toISOString()!=="1969-12-31T23:59:59.999Z";var ur=d.bind(Date.prototype.getTime);$(Date.prototype,{toISOString:function toISOString(){if(!isFinite(this)||!isFinite(ur(this))){throw new RangeError("Date.prototype.toISOString called on non-finite value.")}var t=Lt(this);var r=Xt(this);t+=Math.floor(r/12);r=(r%12+12)%12;var e=[r+1,qt(this),Qt(this),Vt(this),_t(this)];t=(t<0?"-":t>9999?"+":"")+L("00000"+Math.abs(t),0<=t&&t<=9999?-4:-6);for(var n=0;n=7&&l>hr){var p=Math.floor(l/hr)*hr;var y=Math.floor(p/1e3);v+=y;h-=y*1e3}c=s===1&&o(e)===e?new t(r.parse(e)):s>=7?new t(e,n,i,a,f,v,h):s>=6?new t(e,n,i,a,f,v):s>=5?new t(e,n,i,a,f):s>=4?new t(e,n,i,a):s>=3?new t(e,n,i):s>=2?new t(e,n):s>=1?new t(e instanceof t?+e:e):new t}else{c=t.apply(this,arguments)}if(!J(c)){$(c,{constructor:r},true)}return c};var e=new RegExp("^"+"(\\d{4}|[+-]\\d{6})"+"(?:-(\\d{2})"+"(?:-(\\d{2})"+"(?:"+"T(\\d{2})"+":(\\d{2})"+"(?:"+":(\\d{2})"+"(?:(\\.\\d{1,}))?"+")?"+"("+"Z|"+"(?:"+"([-+])"+"(\\d{2})"+":(\\d{2})"+")"+")?)?)?)?"+"$");var n=[0,31,59,90,120,151,181,212,243,273,304,334,365];var i=function dayFromMonth(t,r){var e=r>1?1:0;return n[r]+Math.floor((t-1969+e)/4)-Math.floor((t-1901+e)/100)+Math.floor((t-1601+e)/400)+365*(t-1970)};var a=function toUTC(r){var e=0;var n=r;if(pr&&n>hr){var i=Math.floor(n/hr)*hr;var a=Math.floor(i/1e3);e+=a;n-=a*1e3}return u(new t(1970,0,1,0,0,e,n))};for(var f in t){if(G(t,f)){r[f]=t[f]}}$(r,{now:t.now,UTC:t.UTC},true);r.prototype=t.prototype;$(r.prototype,{constructor:r},true);var l=function parse(r){var n=e.exec(r);if(n){var o=u(n[1]),f=u(n[2]||1)-1,l=u(n[3]||1)-1,s=u(n[4]||0),c=u(n[5]||0),v=u(n[6]||0),h=Math.floor(u(n[7]||0)*1e3),p=Boolean(n[4]&&!n[8]),y=n[9]==="-"?1:-1,d=u(n[10]||0),g=u(n[11]||0),w;var b=c>0||v>0||h>0;if(s<(b?24:25)&&c<60&&v<60&&h<1e3&&f>-1&&f<12&&d<24&&g<60&&l>-1&&l=0){e+=dr.data[r];dr.data[r]=Math.floor(e/t);e=e%t*dr.base}},numToString:function numToString(){var t=dr.size;var r="";while(--t>=0){if(r!==""||t===0||dr.data[t]!==0){var e=o(dr.data[t]);if(r===""){r=e}else{r+=L("0000000",0,7-e.length)+e}}}return r},pow:function pow(t,r,e){return r===0?e:r%2===1?pow(t,r-1,e*t):pow(t*t,r/2,e)},log:function log(t){var r=0;var e=t;while(e>=4096){r+=12;e/=4096}while(e>=2){r+=1;e/=2}return r}};var gr=function toFixed(t){var r,e,n,i,a,f,l,s;r=u(t);r=Y(r)?0:Math.floor(r);if(r<0||r>20){throw new RangeError("Number.toFixed called with invalid number of decimals")}e=u(this);if(Y(e)){return"NaN"}if(e<=-1e21||e>=1e21){return o(e)}n="";if(e<0){n="-";e=-e}i="0";if(e>1e-21){a=dr.log(e*dr.pow(2,69,1))-69;f=a<0?e*dr.pow(2,-a,1):e/dr.pow(2,a,1);f*=4503599627370496;a=52-a;if(a>0){dr.multiply(0,f);l=r;while(l>=7){dr.multiply(1e7,0);l-=7}dr.multiply(dr.pow(10,l,1),0);l=a-1;while(l>=23){dr.divide(1<<23);l-=23}dr.divide(1<0){s=i.length;if(s<=r){i=n+L("0.0000000000000000000",0,r-s+2)+i}else{i=n+L(i,0,s-r)+"."+L(i,s-r)}}else{i=n+i}return i};$(l,{toFixed:gr},yr);var wr=function(){try{return 1..toPrecision(undefined)==="1"}catch(t){return true}}();var br=l.toPrecision;$(l,{toPrecision:function toPrecision(t){return typeof t==="undefined"?br.call(this):br.call(this,t)}},wr);if("ab".split(/(?:ab)*/).length!==2||".".split(/(.?)(.?)/).length!==4||"tesst".split(/(s)*/)[1]==="t"||"test".split(/(?:)/,-1).length!==4||"".split(/.?/).length||".".split(/()()/).length>1){(function(){var t=typeof/()??/.exec("")[1]==="undefined";var r=Math.pow(2,32)-1;f.split=function(e,n){var i=String(this);if(typeof e==="undefined"&&n===0){return[]}if(!M(e)){return X(this,e,n)}var a=[];var o=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),f=0,u,l,s,c;var h=new RegExp(e.source,o+"g");if(!t){u=new RegExp("^"+h.source+"$(?!\\s)",o)}var p=typeof n==="undefined"?r:Z.ToUint32(n);l=h.exec(i);while(l){s=l.index+l[0].length;if(s>f){K(a,L(i,f,l.index));if(!t&&l.length>1){l[0].replace(u,function(){for(var t=1;t1&&l.index=p){break}}if(h.lastIndex===l.index){h.lastIndex++}l=h.exec(i)}if(f===i.length){if(c||!h.test("")){K(a,"")}}else{K(a,L(i,f))}return a.length>p?H(a,0,p):a}})()}else if("0".split(void 0,0).length){f.split=function split(t,r){if(typeof t==="undefined"&&r===0){return[]}return X(this,t,r)}}var Tr=f.replace;var mr=function(){var t=[];"x".replace(/x(.)?/g,function(r,e){K(t,e)});return t.length===1&&typeof t[0]==="undefined"}();if(!mr){f.replace=function replace(t,r){var e=D(r);var n=M(t)&&/\)[*?]/.test(t.source);if(!e||!n){return Tr.call(this,t,r)}else{var i=function(e){var n=arguments.length;var i=t.lastIndex;t.lastIndex=0;var a=t.exec(e)||[];t.lastIndex=i;K(a,arguments[n-2],arguments[n-1]);return r.apply(this,a)};return Tr.call(this,t,i)}}}var Dr=f.substr;var xr="".substr&&"0b".substr(-1)!=="b";$(f,{substr:function substr(t,r){var e=t;if(t<0){e=w(this.length+t,0)}return Dr.call(this,e,r)}},xr);var Sr=" \n\x0B\f\r \xa0\u1680\u180e\u2000\u2001\u2002\u2003"+"\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028"+"\u2029\ufeff";var Or="\u200b";var Er="["+Sr+"]";var jr=new RegExp("^"+Er+Er+"*");var Ir=new RegExp(Er+Er+"*$");var Mr=f.trim&&(Sr.trim()||!Or.trim());$(f,{trim:function trim(){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}return o(this).replace(jr,"").replace(Ir,"")}},Mr);var Ur=d.bind(String.prototype.trim);var Fr=f.lastIndexOf&&"abc\u3042\u3044".lastIndexOf("\u3042\u3044",2)!==-1;$(f,{lastIndexOf:function lastIndexOf(t){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}var r=o(this);var e=o(t);var n=arguments.length>1?u(arguments[1]):NaN;var i=Y(n)?Infinity:Z.ToInteger(n);var a=b(w(i,0),r.length);var f=e.length;var l=a+f;while(l>0){l=w(0,l-f);var s=q(L(r,l,a+f),e);if(s!==-1){return l+s}}return-1}},Fr);var Nr=f.lastIndexOf;$(f,{lastIndexOf:function lastIndexOf(t){return Nr.apply(this,arguments)}},f.lastIndexOf.length!==1);if(parseInt(Sr+"08")!==8||parseInt(Sr+"0x16")!==22){parseInt=function(t){var r=/^[\-+]?0[xX]/;return function parseInt(e,n){var i=Ur(e);var a=u(n)||(r.test(i)?16:10);return t(i,a)}}(parseInt)}if(1/parseFloat("-0")!==-Infinity){parseFloat=function(t){return function parseFloat(r){var e=Ur(r);var n=t(e);return n===0&&L(e,0,1)==="-"?-0:n}}(parseFloat)}if(String(new RangeError("test"))!=="RangeError: test"){var Cr=function toString(){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}var t=this.name;if(typeof t==="undefined"){t="Error"}else if(typeof t!=="string"){t=o(t)}var r=this.message;if(typeof r==="undefined"){r=""}else if(typeof r!=="string"){r=o(r)}if(!t){return r}if(!r){return t}return t+": "+r};Error.prototype.toString=Cr}if(P){var kr=function(t,r){if(Q(t,r)){var e=Object.getOwnPropertyDescriptor(t,r);e.enumerable=false;Object.defineProperty(t,r,e)}};kr(Error.prototype,"message");if(Error.prototype.message!==""){Error.prototype.message=""}kr(Error.prototype,"name")}if(String(/a/gim)!=="/a/gim"){var Rr=function toString(){var t="/"+this.source+"/";if(this.global){t+="g"}if(this.ignoreCase){t+="i"}if(this.multiline){t+="m"}return t};RegExp.prototype.toString=Rr}}); -//# sourceMappingURL=es5-shim.map \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.eot b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.eot deleted file mode 100644 index abb86d98a84..00000000000 Binary files a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.eot and /dev/null differ diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.svg b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.svg deleted file mode 100644 index 3fda041c6e7..00000000000 --- a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.svg +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.ttf b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.ttf deleted file mode 100644 index 3e4e263ba99..00000000000 Binary files a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.ttf and /dev/null differ diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff deleted file mode 100644 index ce91d12bf4f..00000000000 Binary files a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff and /dev/null differ diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff2 b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff2 deleted file mode 100644 index 8935ab54a86..00000000000 Binary files a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff2 and /dev/null differ diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.eot b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.eot deleted file mode 100644 index 74c1bb40c1a..00000000000 Binary files a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.eot and /dev/null differ diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.svg b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.svg deleted file mode 100644 index 0b6b6ab6667..00000000000 --- a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.svg +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.ttf b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.ttf deleted file mode 100644 index 773089dd0d3..00000000000 Binary files a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.ttf and /dev/null differ diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff deleted file mode 100644 index 832c960d698..00000000000 Binary files a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff and /dev/null differ diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff2 b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff2 deleted file mode 100644 index 8922fdc678d..00000000000 Binary files a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff2 and /dev/null differ diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.eot b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.eot deleted file mode 100644 index 8af53738f25..00000000000 Binary files a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.eot and /dev/null differ diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.svg b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.svg deleted file mode 100644 index 64f90f599b5..00000000000 --- a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.svg +++ /dev/null @@ -1,344 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.ttf b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.ttf deleted file mode 100644 index c603136aa7e..00000000000 Binary files a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.ttf and /dev/null differ diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff deleted file mode 100644 index 600602a44b6..00000000000 Binary files a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff and /dev/null differ diff --git a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff2 b/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff2 deleted file mode 100644 index 88ef1301221..00000000000 Binary files a/dashboardv2/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff2 and /dev/null differ diff --git a/dashboardv2/public/js/external_lib/idealTimeout/store.min.js b/dashboardv2/public/js/external_lib/idealTimeout/store.min.js deleted file mode 100644 index 7334a7e724b..00000000000 --- a/dashboardv2/public/js/external_lib/idealTimeout/store.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/* Copyright (c) 2010-2013 Marcus Westin */ -"use strict";(function(e,t){typeof define=="function"&&define.amd?define([],t):typeof exports=="object"?module.exports=t():e.store=t()})(this,function(){function o(){try{return r in t&&t[r]}catch(e){return!1}}var e={},t=window,n=t.document,r="localStorage",i="script",s;e.disabled=!1,e.version="1.3.17",e.set=function(e,t){},e.get=function(e,t){},e.has=function(t){return e.get(t)!==undefined},e.remove=function(e){},e.clear=function(){},e.transact=function(t,n,r){r==null&&(r=n,n=null),n==null&&(n={});var i=e.get(t,n);r(i),e.set(t,i)},e.getAll=function(){},e.forEach=function(){},e.serialize=function(e){return JSON.stringify(e)},e.deserialize=function(e){if(typeof e!="string")return undefined;try{return JSON.parse(e)}catch(t){return e||undefined}};if(o())s=t[r],e.set=function(t,n){return n===undefined?e.remove(t):(s.setItem(t,e.serialize(n)),n)},e.get=function(t,n){var r=e.deserialize(s.getItem(t));return r===undefined?n:r},e.remove=function(e){s.removeItem(e)},e.clear=function(){s.clear()},e.getAll=function(){var t={};return e.forEach(function(e,n){t[e]=n}),t},e.forEach=function(t){for(var n=0;ndocument.w=window'),a.close(),u=a.w.frames[0].document,s=u.createElement("div")}catch(f){s=n.createElement("div"),u=n.body}var l=function(t){return function(){var n=Array.prototype.slice.call(arguments,0);n.unshift(s),u.appendChild(s),s.addBehavior("#default#userData"),s.load(r);var i=t.apply(e,n);return u.removeChild(s),i}},c=new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]","g"),h=function(e){return e.replace(/^d/,"___$&").replace(c,"___")};e.set=l(function(t,n,i){return n=h(n),i===undefined?e.remove(n):(t.setAttribute(n,e.serialize(i)),t.save(r),i)}),e.get=l(function(t,n,r){n=h(n);var i=e.deserialize(t.getAttribute(n));return i===undefined?r:i}),e.remove=l(function(e,t){t=h(t),e.removeAttribute(t),e.save(r)}),e.clear=l(function(e){var t=e.XMLDocument.documentElement.attributes;e.load(r);while(t.length)e.removeAttribute(t[0].name);e.save(r)}),e.getAll=function(t){var n={};return e.forEach(function(e,t){n[e]=t}),n},e.forEach=l(function(t,n){var r=t.XMLDocument.documentElement.attributes;for(var i=0,s;s=r[i];++i)n(s.name,e.deserialize(t.getAttribute(s.name)))})}try{var p="__storejs__";e.set(p,p),e.get(p)!=p&&(e.disabled=!0),e.remove(p)}catch(f){e.disabled=!0}return e.enabled=!e.disabled,e}) \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/jquery-ui/jquery-ui.min.css b/dashboardv2/public/js/external_lib/jquery-ui/jquery-ui.min.css deleted file mode 100644 index 83e8d60277f..00000000000 --- a/dashboardv2/public/js/external_lib/jquery-ui/jquery-ui.min.css +++ /dev/null @@ -1,7 +0,0 @@ -/*! jQuery UI - v1.12.1 - 2019-07-04 -* http://jqueryui.com -* Includes: draggable.css, core.css, resizable.css, autocomplete.css, menu.css, theme.css -* To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=base&cornerRadiusShadow=8px&offsetLeftShadow=0px&offsetTopShadow=0px&thicknessShadow=5px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=666666&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=aaaaaa&iconColorError=cc0000&fcError=5f3f3f&borderColorError=f1a899&bgTextureError=flat&bgColorError=fddfdf&iconColorHighlight=777620&fcHighlight=777620&borderColorHighlight=dad55e&bgTextureHighlight=flat&bgColorHighlight=fffa90&iconColorActive=ffffff&fcActive=ffffff&borderColorActive=003eff&bgTextureActive=flat&bgColorActive=007fff&iconColorHover=555555&fcHover=2b2b2b&borderColorHover=cccccc&bgTextureHover=flat&bgColorHover=ededed&iconColorDefault=777777&fcDefault=454545&borderColorDefault=c5c5c5&bgTextureDefault=flat&bgColorDefault=f6f6f6&iconColorContent=444444&fcContent=333333&borderColorContent=dddddd&bgTextureContent=flat&bgColorContent=ffffff&iconColorHeader=444444&fcHeader=333333&borderColorHeader=dddddd&bgTextureHeader=flat&bgColorHeader=e9e9e9&cornerRadius=3px&fwDefault=normal&fsDefault=1em&ffDefault=Arial%2CHelvetica%2Csans-serif -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-widget{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #c5c5c5}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #ddd;background:#e9e9e9;color:#333;font-weight:bold}.ui-widget-header a{color:#333}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#2b2b2b;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #003eff;background:#007fff;font-weight:normal;color:#fff}.ui-icon-background,.ui-state-active .ui-icon-background{border:#003eff;background-color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #dad55e;background:#fffa90;color:#777620}.ui-state-checked{border:1px solid #dad55e;background:#fffa90}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#777620}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_555555_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_777620_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cc0000_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_777777_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:0 0 5px #666;box-shadow:0 0 5px #666} \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/jquery-ui/jquery-ui.min.js b/dashboardv2/public/js/external_lib/jquery-ui/jquery-ui.min.js deleted file mode 100644 index e0f2255ad76..00000000000 --- a/dashboardv2/public/js/external_lib/jquery-ui/jquery-ui.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/*! jQuery UI - v1.12.1 - 2019-07-04 -* http://jqueryui.com -* Includes: widget.js, position.js, data.js, disable-selection.js, keycode.js, labels.js, scroll-parent.js, unique-id.js, widgets/draggable.js, widgets/resizable.js, widgets/autocomplete.js, widgets/menu.js, widgets/mouse.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){t.ui=t.ui||{},t.ui.version="1.12.1";var e=0,i=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},l=e.split(".")[0];e=e.split(".")[1];var h=l+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][h.toLowerCase()]=function(e){return!!t.data(e,h)},t[l]=t[l]||{},n=t[l][e],o=t[l][e]=function(t,e){return this._createWidget?(arguments.length&&this._createWidget(t,e),void 0):new o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return t.isFunction(s)?(r[e]=function(){function t(){return i.prototype[e].apply(this,arguments)}function n(t){return i.prototype[e].apply(this,t)}return function(){var e,i=this._super,o=this._superApply;return this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void 0):(r[e]=s,void 0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:l,widgetName:e,widgetFullName:h}),n?(t.each(n._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var s,n,o=i.call(arguments,1),a=0,r=o.length;r>a;a++)for(s in o[a])n=o[a][s],o[a].hasOwnProperty(s)&&void 0!==n&&(e[s]=t.isPlainObject(n)?t.isPlainObject(e[s])?t.widget.extend({},e[s],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,s){var n=s.prototype.widgetFullName||e;t.fn[e]=function(o){var a="string"==typeof o,r=i.call(arguments,1),l=this;return a?this.length||"instance"!==o?this.each(function(){var i,s=t.data(this,n);return"instance"===o?(l=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void 0!==i?(l=i&&i.jquery?l.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+o+"'")}):l=void 0:(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new s(o,this))})),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
    ",options:{classes:{},disabled:!1,create:null},_createWidget:function(i,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=e++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var l=s.match(/^([\w:-]*)\s*(.*)$/),h=l[1]+o.eventNamespace,c=l[2];c?n.on(h,c,r):i.on(h,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,function(){function e(t,e,i){return[parseFloat(t[0])*(u.test(t[0])?e/100:1),parseFloat(t[1])*(u.test(t[1])?i/100:1)]}function i(e,i){return parseInt(t.css(e,i),10)||0}function s(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}var n,o=Math.max,a=Math.abs,r=/left|center|right/,l=/top|center|bottom/,h=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,d=t.fn.position;t.position={scrollbarWidth:function(){if(void 0!==n)return n;var e,i,s=t("
    "),o=s.children()[0];return t("body").append(s),e=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,e===i&&(i=s[0].clientWidth),s.remove(),n=e-i},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.widthi?"left":e>0?"right":"center",vertical:0>r?"top":s>0?"bottom":"middle"};h>p&&p>a(e+i)&&(u.horizontal="center"),c>f&&f>a(s+r)&&(u.vertical="middle"),u.important=o(a(e),a(i))>o(a(s),a(r))?"horizontal":"vertical",n.using.call(this,t,u)}),l.offset(t.extend(D,{using:r}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,l=n-r,h=r+e.collisionWidth-a-n;e.collisionWidth>a?l>0&&0>=h?(i=t.left+l+e.collisionWidth-a-n,t.left+=l-i):t.left=h>0&&0>=l?n:l>h?n+a-e.collisionWidth:n:l>0?t.left+=l:h>0?t.left-=h:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,l=n-r,h=r+e.collisionHeight-a-n;e.collisionHeight>a?l>0&&0>=h?(i=t.top+l+e.collisionHeight-a-n,t.top+=l-i):t.top=h>0&&0>=l?n:l>h?n+a-e.collisionHeight:n:l>0?t.top+=l:h>0?t.top-=h:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,o=n.offset.left+n.scrollLeft,r=n.width,l=n.isWindow?n.scrollLeft:n.offset.left,h=t.left-e.collisionPosition.marginLeft,c=h-l,u=h+e.collisionWidth-r-l,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-r-o,(0>i||a(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-l,(s>0||u>a(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,o=n.offset.top+n.scrollTop,r=n.height,l=n.isWindow?n.scrollTop:n.offset.top,h=t.top-e.collisionPosition.marginTop,c=h-l,u=h+e.collisionHeight-r-l,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,g=-2*e.offset[1];0>c?(s=t.top+p+f+g+e.collisionHeight-r-o,(0>s||a(c)>s)&&(t.top+=p+f+g)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+g-l,(i>0||u>a(i))&&(t.top+=p+f+g))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}}}(),t.ui.position,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.extend({disableSelection:function(){var t="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}}(),enableSelection:function(){return this.off(".ui-disableSelection")}}),t.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},t.ui.escapeSelector=function(){var t=/([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;return function(e){return e.replace(t,"\\$1")}}(),t.fn.labels=function(){var e,i,s,n,o;return this[0].labels&&this[0].labels.length?this.pushStack(this[0].labels):(n=this.eq(0).parents("label"),s=this.attr("id"),s&&(e=this.eq(0).parents().last(),o=e.add(e.length?e.siblings():this.siblings()),i="label[for='"+t.ui.escapeSelector(s)+"']",n=n.add(o.find(i).addBack(i))),this.pushStack(n))},t.fn.scrollParent=function(e){var i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var e=t(this);return s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.fn.extend({uniqueId:function(){var t=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++t)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&t(this).removeAttr("id")})}}),t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var s=!1;t(document).on("mouseup",function(){s=!1}),t.widget("ui.mouse",{version:"1.12.1",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!s){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var i=this,n=1===e.which,o="string"==typeof this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return n&&!o&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return i._mouseMove(t)},this._mouseUpDelegate=function(t){return i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),s=!0,!0)):!0}},_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,s=!1,e.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.ui.plugin={add:function(e,i,s){var n,o=t.ui[e].prototype;for(n in s)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([i,s[n]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;o.length>n;n++)t.options[o[n][0]]&&o[n][1].apply(t.element,i)}},t.ui.safeActiveElement=function(t){var e;try{e=t.activeElement}catch(i){e=t.body}return e||(e=t.body),e.nodeName||(e=t.body),e},t.ui.safeBlur=function(e){e&&"body"!==e.nodeName.toLowerCase()&&t(e).trigger("blur")},t.widget("ui.draggable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this._addClass("ui-draggable"),this._setHandleClassName(),this._mouseInit()},_setOption:function(t,e){this._super(t,e),"handle"===t&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void 0):(this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(e){var i=this.options;return this.helper||i.disabled||t(e.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(e),this.handle?(this._blurActiveElement(e),this._blockFrames(i.iframeFix===!0?"iframe":i.iframeFix),!0):!1)},_blockFrames:function(e){this.iframeBlocks=this.document.find(e).map(function(){var e=t(this);return t("
    ").css("position","absolute").appendTo(e.parent()).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()).offset(e.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(e){var i=t.ui.safeActiveElement(this.document[0]),s=t(e.target);s.closest(i).length||t.ui.safeBlur(i)},_mouseStart:function(e){var i=this.options;return this.helper=this._createHelper(e),this._addClass(this.helper,"ui-draggable-dragging"),this._cacheHelperProportions(),t.ui.ddmanager&&(t.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return"fixed"===t(this).css("position")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(e),this.originalPosition=this.position=this._generatePosition(e,!1),this.originalPageX=e.pageX,this.originalPageY=e.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",e)===!1?(this._clear(),!1):(this._cacheHelperProportions(),t.ui.ddmanager&&!i.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this._mouseDrag(e,!0),t.ui.ddmanager&&t.ui.ddmanager.dragStart(this,e),!0)},_refreshOffsets:function(t){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:t.pageX-this.offset.left,top:t.pageY-this.offset.top}},_mouseDrag:function(e,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(e,!0),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",e,s)===!1)return this._mouseUp(new t.Event("mouseup",e)),!1;this.position=s.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),!1},_mouseStop:function(e){var i=this,s=!1;return t.ui.ddmanager&&!this.options.dropBehaviour&&(s=t.ui.ddmanager.drop(this,e)),this.dropped&&(s=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||t.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?t(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",e)!==!1&&i._clear()}):this._trigger("stop",e)!==!1&&this._clear(),!1},_mouseUp:function(e){return this._unblockFrames(),t.ui.ddmanager&&t.ui.ddmanager.dragStop(this,e),this.handleElement.is(e.target)&&this.element.trigger("focus"),t.ui.mouse.prototype._mouseUp.call(this,e)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp(new t.Event("mouseup",{target:this.element[0]})):this._clear(),this},_getHandle:function(e){return this.options.handle?!!t(e.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this._addClass(this.handleElement,"ui-draggable-handle")},_removeHandleClassName:function(){this._removeClass(this.handleElement,"ui-draggable-handle")},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper),n=s?t(i.helper.apply(this.element[0],[e])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return n.parents("body").length||n.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&n[0]===this.element[0]&&this._setPositionRelative(),n[0]===this.element[0]||/(fixed|absolute)/.test(n.css("position"))||n.css("position","absolute"),n},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_isRootNode:function(t){return/(html|body)/i.test(t.tagName)||t===this.document[0]},_getParentOffset:function(){var e=this.offsetParent.offset(),i=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==i&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var t=this.element.position(),e=this._isRootNode(this.scrollParent[0]);return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+(e?0:this.scrollParent.scrollTop()),left:t.left-(parseInt(this.helper.css("left"),10)||0)+(e?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options,o=this.document[0];return this.relativeContainer=null,n.containment?"window"===n.containment?(this.containment=[t(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,t(window).scrollLeft()+t(window).width()-this.helperProportions.width-this.margins.left,t(window).scrollTop()+(t(window).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===n.containment?(this.containment=[0,0,t(o).width()-this.helperProportions.width-this.margins.left,(t(o).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):n.containment.constructor===Array?(this.containment=n.containment,void 0):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=t(n.containment),s=i[0],s&&(e=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(e?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0)},_convertPositionTo:function(t,e){e||(e=this.position);var i="absolute"===t?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:e.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:e.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(t,e){var i,s,n,o,a=this.options,r=this._isRootNode(this.scrollParent[0]),l=t.pageX,h=t.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),e&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,t.pageX-this.offset.click.lefti[2]&&(l=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(h=i[3]+this.offset.click.top)),a.grid&&(n=a.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/a.grid[1])*a.grid[1]:this.originalPageY,h=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-a.grid[1]:n+a.grid[1]:n,o=a.grid[0]?this.originalPageX+Math.round((l-this.originalPageX)/a.grid[0])*a.grid[0]:this.originalPageX,l=i?o-this.offset.click.left>=i[0]||o-this.offset.click.left>i[2]?o:o-this.offset.click.left>=i[0]?o-a.grid[0]:o+a.grid[0]:o),"y"===a.axis&&(l=this.originalPageX),"x"===a.axis&&(h=this.originalPageY)),{top:h-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:l-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this._removeClass(this.helper,"ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_trigger:function(e,i,s){return s=s||this._uiHash(),t.ui.plugin.call(this,e,[i,s,this],!0),/^(drag|start|stop)/.test(e)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),t.Widget.prototype._trigger.call(this,e,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),t.ui.plugin.add("draggable","connectToSortable",{start:function(e,i,s){var n=t.extend({},i,{item:s.element});s.sortables=[],t(s.options.connectToSortable).each(function(){var i=t(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",e,n))})},stop:function(e,i,s){var n=t.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,t.each(s.sortables,function(){var t=this;t.isOver?(t.isOver=0,s.cancelHelperRemoval=!0,t.cancelHelperRemoval=!1,t._storedCSS={position:t.placeholder.css("position"),top:t.placeholder.css("top"),left:t.placeholder.css("left")},t._mouseStop(e),t.options.helper=t.options._helper):(t.cancelHelperRemoval=!0,t._trigger("deactivate",e,n))})},drag:function(e,i,s){t.each(s.sortables,function(){var n=!1,o=this;o.positionAbs=s.positionAbs,o.helperProportions=s.helperProportions,o.offset.click=s.offset.click,o._intersectsWith(o.containerCache)&&(n=!0,t.each(s.sortables,function(){return this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==o&&this._intersectsWith(this.containerCache)&&t.contains(o.element[0],this.element[0])&&(n=!1),n})),n?(o.isOver||(o.isOver=1,s._parent=i.helper.parent(),o.currentItem=i.helper.appendTo(o.element).data("ui-sortable-item",!0),o.options._helper=o.options.helper,o.options.helper=function(){return i.helper[0]},e.target=o.currentItem[0],o._mouseCapture(e,!0),o._mouseStart(e,!0,!0),o.offset.click.top=s.offset.click.top,o.offset.click.left=s.offset.click.left,o.offset.parent.left-=s.offset.parent.left-o.offset.parent.left,o.offset.parent.top-=s.offset.parent.top-o.offset.parent.top,s._trigger("toSortable",e),s.dropped=o.element,t.each(s.sortables,function(){this.refreshPositions() -}),s.currentItem=s.element,o.fromOutside=s),o.currentItem&&(o._mouseDrag(e),i.position=o.position)):o.isOver&&(o.isOver=0,o.cancelHelperRemoval=!0,o.options._revert=o.options.revert,o.options.revert=!1,o._trigger("out",e,o._uiHash(o)),o._mouseStop(e,!0),o.options.revert=o.options._revert,o.options.helper=o.options._helper,o.placeholder&&o.placeholder.remove(),i.helper.appendTo(s._parent),s._refreshOffsets(e),i.position=s._generatePosition(e,!0),s._trigger("fromSortable",e),s.dropped=!1,t.each(s.sortables,function(){this.refreshPositions()}))})}}),t.ui.plugin.add("draggable","cursor",{start:function(e,i,s){var n=t("body"),o=s.options;n.css("cursor")&&(o._cursor=n.css("cursor")),n.css("cursor",o.cursor)},stop:function(e,i,s){var n=s.options;n._cursor&&t("body").css("cursor",n._cursor)}}),t.ui.plugin.add("draggable","opacity",{start:function(e,i,s){var n=t(i.helper),o=s.options;n.css("opacity")&&(o._opacity=n.css("opacity")),n.css("opacity",o.opacity)},stop:function(e,i,s){var n=s.options;n._opacity&&t(i.helper).css("opacity",n._opacity)}}),t.ui.plugin.add("draggable","scroll",{start:function(t,e,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(e,i,s){var n=s.options,o=!1,a=s.scrollParentNotHidden[0],r=s.document[0];a!==r&&"HTML"!==a.tagName?(n.axis&&"x"===n.axis||(s.overflowOffset.top+a.offsetHeight-e.pageY=0;d--)l=s.snapElements[d].left-s.margins.left,h=l+s.snapElements[d].width,c=s.snapElements[d].top-s.margins.top,u=c+s.snapElements[d].height,l-g>_||m>h+g||c-g>b||v>u+g||!t.contains(s.snapElements[d].item.ownerDocument,s.snapElements[d].item)?(s.snapElements[d].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,e,t.extend(s._uiHash(),{snapItem:s.snapElements[d].item})),s.snapElements[d].snapping=!1):("inner"!==f.snapMode&&(n=g>=Math.abs(c-b),o=g>=Math.abs(u-v),a=g>=Math.abs(l-_),r=g>=Math.abs(h-m),n&&(i.position.top=s._convertPositionTo("relative",{top:c-s.helperProportions.height,left:0}).top),o&&(i.position.top=s._convertPositionTo("relative",{top:u,left:0}).top),a&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h}).left)),p=n||o||a||r,"outer"!==f.snapMode&&(n=g>=Math.abs(c-v),o=g>=Math.abs(u-b),a=g>=Math.abs(l-m),r=g>=Math.abs(h-_),n&&(i.position.top=s._convertPositionTo("relative",{top:c,left:0}).top),o&&(i.position.top=s._convertPositionTo("relative",{top:u-s.helperProportions.height,left:0}).top),a&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h-s.helperProportions.width}).left)),!s.snapElements[d].snapping&&(n||o||a||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,e,t.extend(s._uiHash(),{snapItem:s.snapElements[d].item})),s.snapElements[d].snapping=n||o||a||r||p)}}),t.ui.plugin.add("draggable","stack",{start:function(e,i,s){var n,o=s.options,a=t.makeArray(t(o.stack)).sort(function(e,i){return(parseInt(t(e).css("zIndex"),10)||0)-(parseInt(t(i).css("zIndex"),10)||0)});a.length&&(n=parseInt(t(a[0]).css("zIndex"),10)||0,t(a).each(function(e){t(this).css("zIndex",n+e)}),this.css("zIndex",n+a.length))}}),t.ui.plugin.add("draggable","zIndex",{start:function(e,i,s){var n=t(i.helper),o=s.options;n.css("zIndex")&&(o._zIndex=n.css("zIndex")),n.css("zIndex",o.zIndex)},stop:function(e,i,s){var n=s.options;n._zIndex&&t(i.helper).css("zIndex",n._zIndex)}}),t.ui.draggable,t.widget("ui.resizable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,classes:{"ui-resizable-se":"ui-icon ui-icon-gripsmall-diagonal-se"},containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(t){return parseFloat(t)||0},_isNumber:function(t){return!isNaN(parseFloat(t))},_hasScroll:function(e,i){if("hidden"===t(e).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return e[s]>0?!0:(e[s]=1,n=e[s]>0,e[s]=0,n)},_create:function(){var e,i=this.options,s=this;this._addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!i.aspectRatio,aspectRatio:i.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:i.helper||i.ghost||i.animate?i.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(t("
    ").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,e={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(e),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(e),this._proportionallyResize()),this._setupHandles(),i.autoHide&&t(this.element).on("mouseenter",function(){i.disabled||(s._removeClass("ui-resizable-autohide"),s._handles.show())}).on("mouseleave",function(){i.disabled||s.resizing||(s._addClass("ui-resizable-autohide"),s._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeData("resizable").removeData("ui-resizable").off(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;default:}},_setupHandles:function(){var e,i,s,n,o,a=this.options,r=this;if(this.handles=a.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=t(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),s=this.handles.split(","),this.handles={},i=0;s.length>i;i++)e=t.trim(s[i]),n="ui-resizable-"+e,o=t("
    "),this._addClass(o,"ui-resizable-handle "+n),o.css({zIndex:a.zIndex}),this.handles[e]=".ui-resizable-"+e,this.element.append(o);this._renderAxis=function(e){var i,s,n,o;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=t(this.handles[i]),this._on(this.handles[i],{mousedown:r._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=t(this.handles[i],this.element),o=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,o),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){r.resizing||(this.className&&(o=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),r.axis=o&&o[1]?o[1]:"se")}),a.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._handles.remove()},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(e){var i,s,n,o=this.options,a=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),o.containment&&(i+=t(o.containment).scrollLeft()||0,s+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:a.width(),height:a.height()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:e.pageX,top:e.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===n?this.axis+"-resize":n),this._addClass("ui-resizable-resizing"),this._propagate("start",e),!0},_mouseDrag:function(e){var i,s,n=this.originalMousePosition,o=this.axis,a=e.pageX-n.left||0,r=e.pageY-n.top||0,l=this._change[o];return this._updatePrevProperties(),l?(i=l.apply(this,[e,a,r]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",e,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,o,a,r,l,h=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:c.sizeDiff.height,o=s?0:c.sizeDiff.width,a={width:c.helper.width()-o,height:c.helper.height()-n},r=parseFloat(c.element.css("left"))+(c.position.left-c.originalPosition.left)||null,l=parseFloat(c.element.css("top"))+(c.position.top-c.originalPosition.top)||null,h.animate||this.element.css(t.extend(a,{top:l,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!h.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s,n,o,a=this.options;o={minWidth:this._isNumber(a.minWidth)?a.minWidth:0,maxWidth:this._isNumber(a.maxWidth)?a.maxWidth:1/0,minHeight:this._isNumber(a.minHeight)?a.minHeight:0,maxHeight:this._isNumber(a.maxHeight)?a.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,s=o.minWidth/this.aspectRatio,i=o.maxHeight*this.aspectRatio,n=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),s>o.minHeight&&(o.minHeight=s),o.maxWidth>i&&(o.maxWidth=i),o.maxHeight>n&&(o.maxHeight=n)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),this._isNumber(t.left)&&(this.position.left=t.left),this._isNumber(t.top)&&(this.position.top=t.top),this._isNumber(t.height)&&(this.size.height=t.height),this._isNumber(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,i=this.size,s=this.axis;return this._isNumber(t.height)?t.width=t.height*this.aspectRatio:this._isNumber(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===s&&(t.left=e.left+(i.width-t.width),t.top=null),"nw"===s&&(t.top=e.top+(i.height-t.height),t.left=e.left+(i.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,i=this.axis,s=this._isNumber(t.width)&&e.maxWidth&&e.maxWidtht.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalSize.width,l=this.originalPosition.top+this.originalSize.height,h=/sw|nw|w/.test(i),c=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&h&&(t.left=r-e.minWidth),s&&h&&(t.left=r-e.maxWidth),a&&c&&(t.top=l-e.minHeight),n&&c&&(t.top=l-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];4>e;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;this._proportionallyResizeElements.length>e;e++)t=this._proportionallyResizeElements[e],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(t)),t.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("
    "),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,o=n.length&&/textarea/i.test(n[0].nodeName),a=o&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=o?0:i.sizeDiff.width,l={width:i.size.width-r,height:i.size.height-a},h=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,c=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(l,c&&h?{top:c,left:h}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var e,i,s,n,o,a,r,l=t(this).resizable("instance"),h=l.options,c=l.element,u=h.containment,d=u instanceof t?u.get(0):/parent/.test(u)?c.parent().get(0):u;d&&(l.containerElement=t(d),/document/.test(u)||u===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(e=t(d),i=[],t(["Top","Right","Left","Bottom"]).each(function(t,s){i[t]=l._num(e.css("padding"+s))}),l.containerOffset=e.offset(),l.containerPosition=e.position(),l.containerSize={height:e.innerHeight()-i[3],width:e.innerWidth()-i[1]},s=l.containerOffset,n=l.containerSize.height,o=l.containerSize.width,a=l._hasScroll(d,"left")?d.scrollWidth:o,r=l._hasScroll(d)?d.scrollHeight:n,l.parentData={element:d,left:s.left,top:s.top,width:a,height:r}))},resize:function(e){var i,s,n,o,a=t(this).resizable("instance"),r=a.options,l=a.containerOffset,h=a.position,c=a._aspectRatio||e.shiftKey,u={top:0,left:0},d=a.containerElement,p=!0;d[0]!==document&&/static/.test(d.css("position"))&&(u=l),h.left<(a._helper?l.left:0)&&(a.size.width=a.size.width+(a._helper?a.position.left-l.left:a.position.left-u.left),c&&(a.size.height=a.size.width/a.aspectRatio,p=!1),a.position.left=r.helper?l.left:0),h.top<(a._helper?l.top:0)&&(a.size.height=a.size.height+(a._helper?a.position.top-l.top:a.position.top),c&&(a.size.width=a.size.height*a.aspectRatio,p=!1),a.position.top=a._helper?l.top:0),n=a.containerElement.get(0)===a.element.parent().get(0),o=/relative|absolute/.test(a.containerElement.css("position")),n&&o?(a.offset.left=a.parentData.left+a.position.left,a.offset.top=a.parentData.top+a.position.top):(a.offset.left=a.element.offset().left,a.offset.top=a.element.offset().top),i=Math.abs(a.sizeDiff.width+(a._helper?a.offset.left-u.left:a.offset.left-l.left)),s=Math.abs(a.sizeDiff.height+(a._helper?a.offset.top-u.top:a.offset.top-l.top)),i+a.size.width>=a.parentData.width&&(a.size.width=a.parentData.width-i,c&&(a.size.height=a.size.width/a.aspectRatio,p=!1)),s+a.size.height>=a.parentData.height&&(a.size.height=a.parentData.height-s,c&&(a.size.width=a.size.height*a.aspectRatio,p=!1)),p||(a.position.left=a.prevPosition.left,a.position.top=a.prevPosition.top,a.size.width=a.prevSize.width,a.size.height=a.prevSize.height)},stop:function(){var e=t(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.containerPosition,o=e.containerElement,a=t(e.helper),r=a.offset(),l=a.outerWidth()-e.sizeDiff.width,h=a.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:l,height:h}),e._helper&&!i.animate&&/static/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:l,height:h})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).resizable("instance"),i=e.options;t(i.alsoResize).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseFloat(e.width()),height:parseFloat(e.height()),left:parseFloat(e.css("left")),top:parseFloat(e.css("top"))})})},resize:function(e,i){var s=t(this).resizable("instance"),n=s.options,o=s.originalSize,a=s.originalPosition,r={height:s.size.height-o.height||0,width:s.size.width-o.width||0,top:s.position.top-a.top||0,left:s.position.left-a.left||0};t(n.alsoResize).each(function(){var e=t(this),s=t(this).data("ui-resizable-alsoresize"),n={},o=e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(s[e]||0)+(r[e]||0);i&&i>=0&&(n[e]=i||null)}),e.css(n)})},stop:function(){t(this).removeData("ui-resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).resizable("instance"),i=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:i.height,width:i.width,margin:0,left:0,top:0}),e._addClass(e.ghost,"ui-resizable-ghost"),t.uiBackCompat!==!1&&"string"==typeof e.options.ghost&&e.ghost.addClass(this.options.ghost),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).resizable("instance");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).resizable("instance");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e,i=t(this).resizable("instance"),s=i.options,n=i.size,o=i.originalSize,a=i.originalPosition,r=i.axis,l="number"==typeof s.grid?[s.grid,s.grid]:s.grid,h=l[0]||1,c=l[1]||1,u=Math.round((n.width-o.width)/h)*h,d=Math.round((n.height-o.height)/c)*c,p=o.width+u,f=o.height+d,g=s.maxWidth&&p>s.maxWidth,m=s.maxHeight&&f>s.maxHeight,_=s.minWidth&&s.minWidth>p,v=s.minHeight&&s.minHeight>f;s.grid=l,_&&(p+=h),v&&(f+=c),g&&(p-=h),m&&(f-=c),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=a.top-d):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=a.left-u):((0>=f-c||0>=p-h)&&(e=i._getPaddingPlusBorderDimensions(this)),f-c>0?(i.size.height=f,i.position.top=a.top-d):(f=c-e.height,i.size.height=f,i.position.top=a.top+o.height-f),p-h>0?(i.size.width=p,i.position.left=a.left-u):(p=h-e.width,i.size.width=p,i.position.left=a.left+o.width-p))}}),t.ui.resizable,t.widget("ui.menu",{version:"1.12.1",defaultElement:"
      ",delay:300,options:{icons:{submenu:"ui-icon-caret-1-e"},items:"> *",menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().attr({role:this.options.role,tabIndex:0}),this._addClass("ui-menu","ui-widget ui-widget-content"),this._on({"mousedown .ui-menu-item":function(t){t.preventDefault()},"click .ui-menu-item":function(e){var i=t(e.target),s=t(t.ui.safeActiveElement(this.document[0]));!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.select(e),e.isPropagationStopped()||(this.mouseHandled=!0),i.has(".ui-menu").length?this.expand(e):!this.element.is(":focus")&&s.closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(e){if(!this.previousFilter){var i=t(e.target).closest(".ui-menu-item"),s=t(e.currentTarget);i[0]===s[0]&&(this._removeClass(s.siblings().children(".ui-state-active"),null,"ui-state-active"),this.focus(e,s))}},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this.element.find(this.options.items).eq(0);e||this.focus(t,i)},blur:function(e){this._delay(function(){var i=!t.contains(this.element[0],t.ui.safeActiveElement(this.document[0]));i&&this.collapseAll(e)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){this._closeOnDocumentClick(t)&&this.collapseAll(t),this.mouseHandled=!1}})},_destroy:function(){var e=this.element.find(".ui-menu-item").removeAttr("role aria-disabled"),i=e.children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled tabIndex").removeUniqueId().show(),i.children().each(function(){var e=t(this);e.data("ui-menu-submenu-caret")&&e.remove()})},_keydown:function(e){var i,s,n,o,a=!0;switch(e.keyCode){case t.ui.keyCode.PAGE_UP:this.previousPage(e);break;case t.ui.keyCode.PAGE_DOWN:this.nextPage(e);break;case t.ui.keyCode.HOME:this._move("first","first",e);break;case t.ui.keyCode.END:this._move("last","last",e);break;case t.ui.keyCode.UP:this.previous(e);break;case t.ui.keyCode.DOWN:this.next(e);break;case t.ui.keyCode.LEFT:this.collapse(e);break;case t.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(e);break;case t.ui.keyCode.ENTER:case t.ui.keyCode.SPACE:this._activate(e);break;case t.ui.keyCode.ESCAPE:this.collapse(e);break;default:a=!1,s=this.previousFilter||"",o=!1,n=e.keyCode>=96&&105>=e.keyCode?""+(e.keyCode-96):String.fromCharCode(e.keyCode),clearTimeout(this.filterTimer),n===s?o=!0:n=s+n,i=this._filterMenuItems(n),i=o&&-1!==i.index(this.active.next())?this.active.nextAll(".ui-menu-item"):i,i.length||(n=String.fromCharCode(e.keyCode),i=this._filterMenuItems(n)),i.length?(this.focus(e,i),this.previousFilter=n,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}a&&e.preventDefault()},_activate:function(t){this.active&&!this.active.is(".ui-state-disabled")&&(this.active.children("[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var e,i,s,n,o,a=this,r=this.options.icons.submenu,l=this.element.find(this.options.menus);this._toggleClass("ui-menu-icons",null,!!this.element.find(".ui-icon").length),s=l.filter(":not(.ui-menu)").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var e=t(this),i=e.prev(),s=t("").data("ui-menu-submenu-caret",!0);a._addClass(s,"ui-menu-icon","ui-icon "+r),i.attr("aria-haspopup","true").prepend(s),e.attr("aria-labelledby",i.attr("id"))}),this._addClass(s,"ui-menu","ui-widget ui-widget-content ui-front"),e=l.add(this.element),i=e.find(this.options.items),i.not(".ui-menu-item").each(function(){var e=t(this);a._isDivider(e)&&a._addClass(e,"ui-menu-divider","ui-widget-content")}),n=i.not(".ui-menu-item, .ui-menu-divider"),o=n.children().not(".ui-menu").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),this._addClass(n,"ui-menu-item")._addClass(o,"ui-menu-item-wrapper"),i.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!t.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){if("icons"===t){var i=this.element.find(".ui-menu-icon");this._removeClass(i,null,this.options.icons.submenu)._addClass(i,null,e.submenu)}this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t+""),this._toggleClass(null,"ui-state-disabled",!!t)},focus:function(t,e){var i,s,n;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),s=this.active.children(".ui-menu-item-wrapper"),this._addClass(s,null,"ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),n=this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper"),this._addClass(n,null,"ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=e.children(".ui-menu"),i.length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(e){var i,s,n,o,a,r;this._hasScroll()&&(i=parseFloat(t.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(t.css(this.activeMenu[0],"paddingTop"))||0,n=e.offset().top-this.activeMenu.offset().top-i-s,o=this.activeMenu.scrollTop(),a=this.activeMenu.height(),r=e.outerHeight(),0>n?this.activeMenu.scrollTop(o+n):n+r>a&&this.activeMenu.scrollTop(o+n-a+r))},blur:function(t,e){e||clearTimeout(this.timer),this.active&&(this._removeClass(this.active.children(".ui-menu-item-wrapper"),null,"ui-state-active"),this._trigger("blur",t,{item:this.active}),this.active=null)},_startOpening:function(t){clearTimeout(this.timer),"true"===t.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(t)},this.delay))},_open:function(e){var i=t.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(e.parents(".ui-menu")).hide().attr("aria-hidden","true"),e.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(e,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:t(e&&e.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(e),this._removeClass(s.find(".ui-state-active"),null,"ui-state-active"),this.activeMenu=s},this.delay)},_close:function(t){t||(t=this.active?this.active.parent():this.element),t.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false")},_closeOnDocumentClick:function(e){return!t(e.target).closest(".ui-menu").length},_isDivider:function(t){return!/[^\-\u2014\u2013\s]/.test(t.text())},collapse:function(t){var e=this.active&&this.active.parent().closest(".ui-menu-item",this.element);e&&e.length&&(this._close(),this.focus(t,e))},expand:function(t){var e=this.active&&this.active.children(".ui-menu ").find(this.options.items).first();e&&e.length&&(this._open(e.parent()),this._delay(function(){this.focus(t,e)}))},next:function(t){this._move("next","first",t)},previous:function(t){this._move("prev","last",t)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(t,e,i){var s;this.active&&(s="first"===t||"last"===t?this.active["first"===t?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[t+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.find(this.options.items)[e]()),this.focus(i,s)},nextPage:function(e){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=t(this),0>i.offset().top-s-n}),this.focus(e,i)):this.focus(e,this.activeMenu.find(this.options.items)[this.active?"last":"first"]())),void 0):(this.next(e),void 0)},previousPage:function(e){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=t(this),i.offset().top-s+n>0 -}),this.focus(e,i)):this.focus(e,this.activeMenu.find(this.options.items).first())),void 0):(this.next(e),void 0)},_hasScroll:function(){return this.element.outerHeight()",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,_create:function(){var e,i,s,n=this.element[0].nodeName.toLowerCase(),o="textarea"===n,a="input"===n;this.isMultiLine=o||!a&&this._isContentEditable(this.element),this.valueMethod=this.element[o||a?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return e=!0,s=!0,i=!0,void 0;e=!1,s=!1,i=!1;var o=t.ui.keyCode;switch(n.keyCode){case o.PAGE_UP:e=!0,this._move("previousPage",n);break;case o.PAGE_DOWN:e=!0,this._move("nextPage",n);break;case o.UP:e=!0,this._keyEvent("previous",n);break;case o.DOWN:e=!0,this._keyEvent("next",n);break;case o.ENTER:this.menu.active&&(e=!0,n.preventDefault(),this.menu.select(n));break;case o.TAB:this.menu.active&&this.menu.select(n);break;case o.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(e)return e=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),void 0;if(!i){var n=t.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(t){return s?(s=!1,t.preventDefault(),void 0):(this._searchTimeout(t),void 0)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(clearTimeout(this.searching),this.close(t),this._change(t),void 0)}}),this._initSource(),this.menu=t("
        ").appendTo(this._appendTo()).menu({role:null}).hide().menu("instance"),this._addClass(this.menu.element,"ui-autocomplete","ui-front"),this._on(this.menu.element,{mousedown:function(e){e.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,this.element[0]!==t.ui.safeActiveElement(this.document[0])&&this.element.trigger("focus")})},menufocus:function(e,i){var s,n;return this.isNewMenu&&(this.isNewMenu=!1,e.originalEvent&&/^mouse/.test(e.originalEvent.type))?(this.menu.blur(),this.document.one("mousemove",function(){t(e.target).trigger(e.originalEvent)}),void 0):(n=i.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",e,{item:n})&&e.originalEvent&&/^key/.test(e.originalEvent.type)&&this._value(n.value),s=i.item.attr("aria-label")||n.value,s&&t.trim(s).length&&(this.liveRegion.children().hide(),t("
        ").text(s).appendTo(this.liveRegion)),void 0)},menuselect:function(e,i){var s=i.item.data("ui-autocomplete-item"),n=this.previous;this.element[0]!==t.ui.safeActiveElement(this.document[0])&&(this.element.trigger("focus"),this.previous=n,this._delay(function(){this.previous=n,this.selectedItem=s})),!1!==this._trigger("select",e,{item:s})&&this._value(s.value),this.term=this._value(),this.close(e),this.selectedItem=s}}),this.liveRegion=t("
        ",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(t,e){this._super(t,e),"source"===t&&this._initSource(),"appendTo"===t&&this.menu.element.appendTo(this._appendTo()),"disabled"===t&&e&&this.xhr&&this.xhr.abort()},_isEventTargetInWidget:function(e){var i=this.menu.element[0];return e.target===this.element[0]||e.target===i||t.contains(i,e.target)},_closeOnClickOutside:function(t){this._isEventTargetInWidget(t)||this.close()},_appendTo:function(){var e=this.options.appendTo;return e&&(e=e.jquery||e.nodeType?t(e):this.document.find(e).eq(0)),e&&e[0]||(e=this.element.closest(".ui-front, dialog")),e.length||(e=this.document[0].body),e},_initSource:function(){var e,i,s=this;t.isArray(this.options.source)?(e=this.options.source,this.source=function(i,s){s(t.ui.autocomplete.filter(e,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(e,n){s.xhr&&s.xhr.abort(),s.xhr=t.ajax({url:i,data:e,dataType:"json",success:function(t){n(t)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(t){clearTimeout(this.searching),this.searching=this._delay(function(){var e=this.term===this._value(),i=this.menu.element.is(":visible"),s=t.altKey||t.ctrlKey||t.metaKey||t.shiftKey;(!e||e&&!i&&!s)&&(this.selectedItem=null,this.search(null,t))},this.options.delay)},search:function(t,e){return t=null!=t?t:this._value(),this.term=this._value(),t.length").append(t("
        ").text(i.label)).appendTo(e)},_move:function(t,e){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(t)||this.menu.isLastItem()&&/^next/.test(t)?(this.isMultiLine||this._value(this.term),this.menu.blur(),void 0):(this.menu[t](e),void 0):(this.search(null,e),void 0)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(t,e){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(t,e),e.preventDefault())},_isContentEditable:function(t){if(!t.length)return!1;var e=t.prop("contentEditable");return"inherit"===e?this._isContentEditable(t.parent()):"true"===e}}),t.extend(t.ui.autocomplete,{escapeRegex:function(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(e,i){var s=RegExp(t.ui.autocomplete.escapeRegex(i),"i");return t.grep(e,function(t){return s.test(t.label||t.value||t)})}}),t.widget("ui.autocomplete",t.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(t){return t+(t>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var i;this._superApply(arguments),this.options.disabled||this.cancelSearch||(i=e&&e.length?this.options.messages.results(e.length):this.options.messages.noResults,this.liveRegion.children().hide(),t("
        ").text(i).appendTo(this.liveRegion))}}),t.ui.autocomplete;var n="ui-effects-",o="ui-effects-style",a="ui-effects-animated",r=t;t.effects={effect:{}},function(t,e){function i(t,e,i){var s=u[e.type]||{};return null==t?i||!e.def?null:e.def:(t=s.floor?~~t:parseFloat(t),isNaN(t)?e.def:s.mod?(t+s.mod)%s.mod:0>t?0:t>s.max?s.max:t)}function s(i){var s=h(),n=s._rgba=[];return i=i.toLowerCase(),f(l,function(t,o){var a,r=o.re.exec(i),l=r&&o.parse(r),h=o.space||"rgba";return l?(a=s[h](l),s[c[h].cache]=a[c[h].cache],n=s._rgba=a._rgba,!1):e}),n.length?("0,0,0,0"===n.join()&&t.extend(n,o.transparent),s):o[i]}function n(t,e,i){return i=(i+1)%1,1>6*i?t+6*(e-t)*i:1>2*i?e:2>3*i?t+6*(e-t)*(2/3-i):t}var o,a="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,l=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[t[1],t[2],t[3],t[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[2.55*t[1],2.55*t[2],2.55*t[3],t[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(t){return[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(t){return[parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(t){return[t[1],t[2]/100,t[3]/100,t[4]]}}],h=t.Color=function(e,i,s,n){return new t.Color.fn.parse(e,i,s,n)},c={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},u={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},d=h.support={},p=t("

        ")[0],f=t.each;p.style.cssText="background-color:rgba(1,1,1,.5)",d.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(c,function(t,e){e.cache="_"+t,e.props.alpha={idx:3,type:"percent",def:1}}),h.fn=t.extend(h.prototype,{parse:function(n,a,r,l){if(n===e)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=t(n).css(a),a=e);var u=this,d=t.type(n),p=this._rgba=[];return a!==e&&(n=[n,a,r,l],d="array"),"string"===d?this.parse(s(n)||o._default):"array"===d?(f(c.rgba.props,function(t,e){p[e.idx]=i(n[e.idx],e)}),this):"object"===d?(n instanceof h?f(c,function(t,e){n[e.cache]&&(u[e.cache]=n[e.cache].slice())}):f(c,function(e,s){var o=s.cache;f(s.props,function(t,e){if(!u[o]&&s.to){if("alpha"===t||null==n[t])return;u[o]=s.to(u._rgba)}u[o][e.idx]=i(n[t],e,!0)}),u[o]&&0>t.inArray(null,u[o].slice(0,3))&&(u[o][3]=1,s.from&&(u._rgba=s.from(u[o])))}),this):e},is:function(t){var i=h(t),s=!0,n=this;return f(c,function(t,o){var a,r=i[o.cache];return r&&(a=n[o.cache]||o.to&&o.to(n._rgba)||[],f(o.props,function(t,i){return null!=r[i.idx]?s=r[i.idx]===a[i.idx]:e})),s}),s},_space:function(){var t=[],e=this;return f(c,function(i,s){e[s.cache]&&t.push(i)}),t.pop()},transition:function(t,e){var s=h(t),n=s._space(),o=c[n],a=0===this.alpha()?h("transparent"):this,r=a[o.cache]||o.to(a._rgba),l=r.slice();return s=s[o.cache],f(o.props,function(t,n){var o=n.idx,a=r[o],h=s[o],c=u[n.type]||{};null!==h&&(null===a?l[o]=h:(c.mod&&(h-a>c.mod/2?a+=c.mod:a-h>c.mod/2&&(a-=c.mod)),l[o]=i((h-a)*e+a,n)))}),this[n](l)},blend:function(e){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=h(e)._rgba;return h(t.map(i,function(t,e){return(1-s)*n[e]+s*t}))},toRgbaString:function(){var e="rgba(",i=t.map(this._rgba,function(t,e){return null==t?e>2?1:0:t});return 1===i[3]&&(i.pop(),e="rgb("),e+i.join()+")"},toHslaString:function(){var e="hsla(",i=t.map(this.hsla(),function(t,e){return null==t&&(t=e>2?1:0),e&&3>e&&(t=Math.round(100*t)+"%"),t});return 1===i[3]&&(i.pop(),e="hsl("),e+i.join()+")"},toHexString:function(e){var i=this._rgba.slice(),s=i.pop();return e&&i.push(~~(255*s)),"#"+t.map(i,function(t){return t=(t||0).toString(16),1===t.length?"0"+t:t}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),h.fn.parse.prototype=h.fn,c.hsla.to=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e,i,s=t[0]/255,n=t[1]/255,o=t[2]/255,a=t[3],r=Math.max(s,n,o),l=Math.min(s,n,o),h=r-l,c=r+l,u=.5*c;return e=l===r?0:s===r?60*(n-o)/h+360:n===r?60*(o-s)/h+120:60*(s-n)/h+240,i=0===h?0:.5>=u?h/c:h/(2-c),[Math.round(e)%360,i,u,null==a?1:a]},c.hsla.from=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e=t[0]/360,i=t[1],s=t[2],o=t[3],a=.5>=s?s*(1+i):s+i-s*i,r=2*s-a;return[Math.round(255*n(r,a,e+1/3)),Math.round(255*n(r,a,e)),Math.round(255*n(r,a,e-1/3)),o]},f(c,function(s,n){var o=n.props,a=n.cache,l=n.to,c=n.from;h.fn[s]=function(s){if(l&&!this[a]&&(this[a]=l(this._rgba)),s===e)return this[a].slice();var n,r=t.type(s),u="array"===r||"object"===r?s:arguments,d=this[a].slice();return f(o,function(t,e){var s=u["object"===r?t:e.idx];null==s&&(s=d[e.idx]),d[e.idx]=i(s,e)}),c?(n=h(c(d)),n[a]=d,n):h(d)},f(o,function(e,i){h.fn[e]||(h.fn[e]=function(n){var o,a=t.type(n),l="alpha"===e?this._hsla?"hsla":"rgba":s,h=this[l](),c=h[i.idx];return"undefined"===a?c:("function"===a&&(n=n.call(this,c),a=t.type(n)),null==n&&i.empty?this:("string"===a&&(o=r.exec(n),o&&(n=c+parseFloat(o[2])*("+"===o[1]?1:-1))),h[i.idx]=n,this[l](h)))})})}),h.hook=function(e){var i=e.split(" ");f(i,function(e,i){t.cssHooks[i]={set:function(e,n){var o,a,r="";if("transparent"!==n&&("string"!==t.type(n)||(o=s(n)))){if(n=h(o||n),!d.rgba&&1!==n._rgba[3]){for(a="backgroundColor"===i?e.parentNode:e;(""===r||"transparent"===r)&&a&&a.style;)try{r=t.css(a,"backgroundColor"),a=a.parentNode}catch(l){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{e.style[i]=n}catch(l){}}},t.fx.step[i]=function(e){e.colorInit||(e.start=h(e.elem,i),e.end=h(e.end),e.colorInit=!0),t.cssHooks[i].set(e.elem,e.start.transition(e.end,e.pos))}})},h.hook(a),t.cssHooks.borderColor={expand:function(t){var e={};return f(["Top","Right","Bottom","Left"],function(i,s){e["border"+s+"Color"]=t}),e}},o=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(r),function(){function e(e){var i,s,n=e.ownerDocument.defaultView?e.ownerDocument.defaultView.getComputedStyle(e,null):e.currentStyle,o={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(o[t.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(o[i]=n[i]);return o}function i(e,i){var s,o,a={};for(s in i)o=i[s],e[s]!==o&&(n[s]||(t.fx.step[s]||!isNaN(parseFloat(o)))&&(a[s]=o));return a}var s=["add","remove","toggle"],n={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};t.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(e,i){t.fx.step[i]=function(t){("none"!==t.end&&!t.setAttr||1===t.pos&&!t.setAttr)&&(r.style(t.elem,i,t.end),t.setAttr=!0)}}),t.fn.addBack||(t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.effects.animateClass=function(n,o,a,r){var l=t.speed(o,a,r);return this.queue(function(){var o,a=t(this),r=a.attr("class")||"",h=l.children?a.find("*").addBack():a;h=h.map(function(){var i=t(this);return{el:i,start:e(this)}}),o=function(){t.each(s,function(t,e){n[e]&&a[e+"Class"](n[e])})},o(),h=h.map(function(){return this.end=e(this.el[0]),this.diff=i(this.start,this.end),this}),a.attr("class",r),h=h.map(function(){var e=this,i=t.Deferred(),s=t.extend({},l,{queue:!1,complete:function(){i.resolve(e)}});return this.el.animate(this.diff,s),i.promise()}),t.when.apply(t,h.get()).done(function(){o(),t.each(arguments,function(){var e=this.el;t.each(this.diff,function(t){e.css(t,"")})}),l.complete.call(a[0])})})},t.fn.extend({addClass:function(e){return function(i,s,n,o){return s?t.effects.animateClass.call(this,{add:i},s,n,o):e.apply(this,arguments)}}(t.fn.addClass),removeClass:function(e){return function(i,s,n,o){return arguments.length>1?t.effects.animateClass.call(this,{remove:i},s,n,o):e.apply(this,arguments)}}(t.fn.removeClass),toggleClass:function(e){return function(i,s,n,o,a){return"boolean"==typeof s||void 0===s?n?t.effects.animateClass.call(this,s?{add:i}:{remove:i},n,o,a):e.apply(this,arguments):t.effects.animateClass.call(this,{toggle:i},s,n,o)}}(t.fn.toggleClass),switchClass:function(e,i,s,n,o){return t.effects.animateClass.call(this,{add:i,remove:e},s,n,o)}})}(),function(){function e(e,i,s,n){return t.isPlainObject(e)&&(i=e,e=e.effect),e={effect:e},null==i&&(i={}),t.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||t.fx.speeds[i])&&(n=s,s=i,i={}),t.isFunction(s)&&(n=s,s=null),i&&t.extend(e,i),s=s||i.duration,e.duration=t.fx.off?0:"number"==typeof s?s:s in t.fx.speeds?t.fx.speeds[s]:t.fx.speeds._default,e.complete=n||i.complete,e}function i(e){return!e||"number"==typeof e||t.fx.speeds[e]?!0:"string"!=typeof e||t.effects.effect[e]?t.isFunction(e)?!0:"object"!=typeof e||e.effect?!1:!0:!0}function s(t,e){var i=e.outerWidth(),s=e.outerHeight(),n=/^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/,o=n.exec(t)||["",0,i,s,0];return{top:parseFloat(o[1])||0,right:"auto"===o[2]?i:parseFloat(o[2]),bottom:"auto"===o[3]?s:parseFloat(o[3]),left:parseFloat(o[4])||0}}t.expr&&t.expr.filters&&t.expr.filters.animated&&(t.expr.filters.animated=function(e){return function(i){return!!t(i).data(a)||e(i)}}(t.expr.filters.animated)),t.uiBackCompat!==!1&&t.extend(t.effects,{save:function(t,e){for(var i=0,s=e.length;s>i;i++)null!==e[i]&&t.data(n+e[i],t[0].style[e[i]])},restore:function(t,e){for(var i,s=0,o=e.length;o>s;s++)null!==e[s]&&(i=t.data(n+e[s]),t.css(e[s],i))},setMode:function(t,e){return"toggle"===e&&(e=t.is(":hidden")?"show":"hide"),e},createWrapper:function(e){if(e.parent().is(".ui-effects-wrapper"))return e.parent();var i={width:e.outerWidth(!0),height:e.outerHeight(!0),"float":e.css("float")},s=t("

        ").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:e.width(),height:e.height()},o=document.activeElement;try{o.id}catch(a){o=document.body}return e.wrap(s),(e[0]===o||t.contains(e[0],o))&&t(o).trigger("focus"),s=e.parent(),"static"===e.css("position")?(s.css({position:"relative"}),e.css({position:"relative"})):(t.extend(i,{position:e.css("position"),zIndex:e.css("z-index")}),t.each(["top","left","bottom","right"],function(t,s){i[s]=e.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),e.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),e.css(n),s.css(i).show()},removeWrapper:function(e){var i=document.activeElement;return e.parent().is(".ui-effects-wrapper")&&(e.parent().replaceWith(e),(e[0]===i||t.contains(e[0],i))&&t(i).trigger("focus")),e}}),t.extend(t.effects,{version:"1.12.1",define:function(e,i,s){return s||(s=i,i="effect"),t.effects.effect[e]=s,t.effects.effect[e].mode=i,s},scaledDimensions:function(t,e,i){if(0===e)return{height:0,width:0,outerHeight:0,outerWidth:0};var s="horizontal"!==i?(e||100)/100:1,n="vertical"!==i?(e||100)/100:1;return{height:t.height()*n,width:t.width()*s,outerHeight:t.outerHeight()*n,outerWidth:t.outerWidth()*s}},clipToBox:function(t){return{width:t.clip.right-t.clip.left,height:t.clip.bottom-t.clip.top,left:t.clip.left,top:t.clip.top}},unshift:function(t,e,i){var s=t.queue();e>1&&s.splice.apply(s,[1,0].concat(s.splice(e,i))),t.dequeue()},saveStyle:function(t){t.data(o,t[0].style.cssText)},restoreStyle:function(t){t[0].style.cssText=t.data(o)||"",t.removeData(o)},mode:function(t,e){var i=t.is(":hidden");return"toggle"===e&&(e=i?"show":"hide"),(i?"hide"===e:"show"===e)&&(e="none"),e},getBaseline:function(t,e){var i,s;switch(t[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=t[0]/e.height}switch(t[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=t[1]/e.width}return{x:s,y:i}},createPlaceholder:function(e){var i,s=e.css("position"),o=e.position();return e.css({marginTop:e.css("marginTop"),marginBottom:e.css("marginBottom"),marginLeft:e.css("marginLeft"),marginRight:e.css("marginRight")}).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()),/^(static|relative)/.test(s)&&(s="absolute",i=t("<"+e[0].nodeName+">").insertAfter(e).css({display:/^(inline|ruby)/.test(e.css("display"))?"inline-block":"block",visibility:"hidden",marginTop:e.css("marginTop"),marginBottom:e.css("marginBottom"),marginLeft:e.css("marginLeft"),marginRight:e.css("marginRight"),"float":e.css("float")}).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()).addClass("ui-effects-placeholder"),e.data(n+"placeholder",i)),e.css({position:s,left:o.left,top:o.top}),i},removePlaceholder:function(t){var e=n+"placeholder",i=t.data(e);i&&(i.remove(),t.removeData(e))},cleanUp:function(e){t.effects.restoreStyle(e),t.effects.removePlaceholder(e)},setTransition:function(e,i,s,n){return n=n||{},t.each(i,function(t,i){var o=e.cssUnit(i);o[0]>0&&(n[i]=o[0]*s+o[1])}),n}}),t.fn.extend({effect:function(){function i(e){function i(){l.removeData(a),t.effects.cleanUp(l),"hide"===s.mode&&l.hide(),r()}function r(){t.isFunction(h)&&h.call(l[0]),t.isFunction(e)&&e()}var l=t(this);s.mode=u.shift(),t.uiBackCompat===!1||o?"none"===s.mode?(l[c](),r()):n.call(l[0],s,i):(l.is(":hidden")?"hide"===c:"show"===c)?(l[c](),r()):n.call(l[0],s,r)}var s=e.apply(this,arguments),n=t.effects.effect[s.effect],o=n.mode,r=s.queue,l=r||"fx",h=s.complete,c=s.mode,u=[],d=function(e){var i=t(this),s=t.effects.mode(i,c)||o;i.data(a,!0),u.push(s),o&&("show"===s||s===o&&"hide"===s)&&i.show(),o&&"none"===s||t.effects.saveStyle(i),t.isFunction(e)&&e()};return t.fx.off||!n?c?this[c](s.duration,h):this.each(function(){h&&h.call(this)}):r===!1?this.each(d).each(i):this.queue(l,d).queue(l,i)},show:function(t){return function(s){if(i(s))return t.apply(this,arguments);var n=e.apply(this,arguments);return n.mode="show",this.effect.call(this,n)}}(t.fn.show),hide:function(t){return function(s){if(i(s))return t.apply(this,arguments);var n=e.apply(this,arguments);return n.mode="hide",this.effect.call(this,n)}}(t.fn.hide),toggle:function(t){return function(s){if(i(s)||"boolean"==typeof s)return t.apply(this,arguments);var n=e.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)}}(t.fn.toggle),cssUnit:function(e){var i=this.css(e),s=[];return t.each(["em","px","%","pt"],function(t,e){i.indexOf(e)>0&&(s=[parseFloat(i),e])}),s},cssClip:function(t){return t?this.css("clip","rect("+t.top+"px "+t.right+"px "+t.bottom+"px "+t.left+"px)"):s(this.css("clip"),this)},transfer:function(e,i){var s=t(this),n=t(e.to),o="fixed"===n.css("position"),a=t("body"),r=o?a.scrollTop():0,l=o?a.scrollLeft():0,h=n.offset(),c={top:h.top-r,left:h.left-l,height:n.innerHeight(),width:n.innerWidth()},u=s.offset(),d=t("
        ").appendTo("body").addClass(e.className).css({top:u.top-r,left:u.left-l,height:s.innerHeight(),width:s.innerWidth(),position:o?"fixed":"absolute"}).animate(c,e.duration,e.easing,function(){d.remove(),t.isFunction(i)&&i()})}}),t.fx.step.clip=function(e){e.clipInit||(e.start=t(e.elem).cssClip(),"string"==typeof e.end&&(e.end=s(e.end,e.elem)),e.clipInit=!0),t(e.elem).cssClip({top:e.pos*(e.end.top-e.start.top)+e.start.top,right:e.pos*(e.end.right-e.start.right)+e.start.right,bottom:e.pos*(e.end.bottom-e.start.bottom)+e.start.bottom,left:e.pos*(e.end.left-e.start.left)+e.start.left})}}(),function(){var e={};t.each(["Quad","Cubic","Quart","Quint","Expo"],function(t,i){e[i]=function(e){return Math.pow(e,t+2)}}),t.extend(e,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;((e=Math.pow(2,--i))-1)/11>t;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),t.each(e,function(e,i){t.easing["easeIn"+e]=i,t.easing["easeOut"+e]=function(t){return 1-i(1-t)},t.easing["easeInOut"+e]=function(t){return.5>t?i(2*t)/2:1-i(-2*t+2)/2}})}();var l=t.effects;t.effects.define("blind","hide",function(e,i){var s={up:["bottom","top"],vertical:["bottom","top"],down:["top","bottom"],left:["right","left"],horizontal:["right","left"],right:["left","right"]},n=t(this),o=e.direction||"up",a=n.cssClip(),r={clip:t.extend({},a)},l=t.effects.createPlaceholder(n);r.clip[s[o][0]]=r.clip[s[o][1]],"show"===e.mode&&(n.cssClip(r.clip),l&&l.css(t.effects.clipToBox(r)),r.clip=a),l&&l.animate(t.effects.clipToBox(r),e.duration,e.easing),n.animate(r,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("bounce",function(e,i){var s,n,o,a=t(this),r=e.mode,l="hide"===r,h="show"===r,c=e.direction||"up",u=e.distance,d=e.times||5,p=2*d+(h||l?1:0),f=e.duration/p,g=e.easing,m="up"===c||"down"===c?"top":"left",_="up"===c||"left"===c,v=0,b=a.queue().length;for(t.effects.createPlaceholder(a),o=a.css(m),u||(u=a["top"===m?"outerHeight":"outerWidth"]()/3),h&&(n={opacity:1},n[m]=o,a.css("opacity",0).css(m,_?2*-u:2*u).animate(n,f,g)),l&&(u/=Math.pow(2,d-1)),n={},n[m]=o;d>v;v++)s={},s[m]=(_?"-=":"+=")+u,a.animate(s,f,g).animate(n,f,g),u=l?2*u:u/2;l&&(s={opacity:0},s[m]=(_?"-=":"+=")+u,a.animate(s,f,g)),a.queue(i),t.effects.unshift(a,b,p+1)}),t.effects.define("clip","hide",function(e,i){var s,n={},o=t(this),a=e.direction||"vertical",r="both"===a,l=r||"horizontal"===a,h=r||"vertical"===a;s=o.cssClip(),n.clip={top:h?(s.bottom-s.top)/2:s.top,right:l?(s.right-s.left)/2:s.right,bottom:h?(s.bottom-s.top)/2:s.bottom,left:l?(s.right-s.left)/2:s.left},t.effects.createPlaceholder(o),"show"===e.mode&&(o.cssClip(n.clip),n.clip=s),o.animate(n,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("drop","hide",function(e,i){var s,n=t(this),o=e.mode,a="show"===o,r=e.direction||"left",l="up"===r||"down"===r?"top":"left",h="up"===r||"left"===r?"-=":"+=",c="+="===h?"-=":"+=",u={opacity:0};t.effects.createPlaceholder(n),s=e.distance||n["top"===l?"outerHeight":"outerWidth"](!0)/2,u[l]=h+s,a&&(n.css(u),u[l]=c+s,u.opacity=1),n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("explode","hide",function(e,i){function s(){b.push(this),b.length===u*d&&n()}function n(){p.css({visibility:"visible"}),t(b).remove(),i()}var o,a,r,l,h,c,u=e.pieces?Math.round(Math.sqrt(e.pieces)):3,d=u,p=t(this),f=e.mode,g="show"===f,m=p.show().css("visibility","hidden").offset(),_=Math.ceil(p.outerWidth()/d),v=Math.ceil(p.outerHeight()/u),b=[];for(o=0;u>o;o++)for(l=m.top+o*v,c=o-(u-1)/2,a=0;d>a;a++)r=m.left+a*_,h=a-(d-1)/2,p.clone().appendTo("body").wrap("
        ").css({position:"absolute",visibility:"visible",left:-a*_,top:-o*v}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:_,height:v,left:r+(g?h*_:0),top:l+(g?c*v:0),opacity:g?0:1}).animate({left:r+(g?0:h*_),top:l+(g?0:c*v),opacity:g?1:0},e.duration||500,e.easing,s)}),t.effects.define("fade","toggle",function(e,i){var s="show"===e.mode;t(this).css("opacity",s?0:1).animate({opacity:s?1:0},{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("fold","hide",function(e,i){var s=t(this),n=e.mode,o="show"===n,a="hide"===n,r=e.size||15,l=/([0-9]+)%/.exec(r),h=!!e.horizFirst,c=h?["right","bottom"]:["bottom","right"],u=e.duration/2,d=t.effects.createPlaceholder(s),p=s.cssClip(),f={clip:t.extend({},p)},g={clip:t.extend({},p)},m=[p[c[0]],p[c[1]]],_=s.queue().length;l&&(r=parseInt(l[1],10)/100*m[a?0:1]),f.clip[c[0]]=r,g.clip[c[0]]=r,g.clip[c[1]]=0,o&&(s.cssClip(g.clip),d&&d.css(t.effects.clipToBox(g)),g.clip=p),s.queue(function(i){d&&d.animate(t.effects.clipToBox(f),u,e.easing).animate(t.effects.clipToBox(g),u,e.easing),i()}).animate(f,u,e.easing).animate(g,u,e.easing).queue(i),t.effects.unshift(s,_,4)}),t.effects.define("highlight","show",function(e,i){var s=t(this),n={backgroundColor:s.css("backgroundColor")};"hide"===e.mode&&(n.opacity=0),t.effects.saveStyle(s),s.css({backgroundImage:"none",backgroundColor:e.color||"#ffff99"}).animate(n,{queue:!1,duration:e.duration,easing:e.easing,complete:i})}),t.effects.define("size",function(e,i){var s,n,o,a=t(this),r=["fontSize"],l=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],h=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],c=e.mode,u="effect"!==c,d=e.scale||"both",p=e.origin||["middle","center"],f=a.css("position"),g=a.position(),m=t.effects.scaledDimensions(a),_=e.from||m,v=e.to||t.effects.scaledDimensions(a,0);t.effects.createPlaceholder(a),"show"===c&&(o=_,_=v,v=o),n={from:{y:_.height/m.height,x:_.width/m.width},to:{y:v.height/m.height,x:v.width/m.width}},("box"===d||"both"===d)&&(n.from.y!==n.to.y&&(_=t.effects.setTransition(a,l,n.from.y,_),v=t.effects.setTransition(a,l,n.to.y,v)),n.from.x!==n.to.x&&(_=t.effects.setTransition(a,h,n.from.x,_),v=t.effects.setTransition(a,h,n.to.x,v))),("content"===d||"both"===d)&&n.from.y!==n.to.y&&(_=t.effects.setTransition(a,r,n.from.y,_),v=t.effects.setTransition(a,r,n.to.y,v)),p&&(s=t.effects.getBaseline(p,m),_.top=(m.outerHeight-_.outerHeight)*s.y+g.top,_.left=(m.outerWidth-_.outerWidth)*s.x+g.left,v.top=(m.outerHeight-v.outerHeight)*s.y+g.top,v.left=(m.outerWidth-v.outerWidth)*s.x+g.left),a.css(_),("content"===d||"both"===d)&&(l=l.concat(["marginTop","marginBottom"]).concat(r),h=h.concat(["marginLeft","marginRight"]),a.find("*[width]").each(function(){var i=t(this),s=t.effects.scaledDimensions(i),o={height:s.height*n.from.y,width:s.width*n.from.x,outerHeight:s.outerHeight*n.from.y,outerWidth:s.outerWidth*n.from.x},a={height:s.height*n.to.y,width:s.width*n.to.x,outerHeight:s.height*n.to.y,outerWidth:s.width*n.to.x};n.from.y!==n.to.y&&(o=t.effects.setTransition(i,l,n.from.y,o),a=t.effects.setTransition(i,l,n.to.y,a)),n.from.x!==n.to.x&&(o=t.effects.setTransition(i,h,n.from.x,o),a=t.effects.setTransition(i,h,n.to.x,a)),u&&t.effects.saveStyle(i),i.css(o),i.animate(a,e.duration,e.easing,function(){u&&t.effects.restoreStyle(i)})})),a.animate(v,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){var e=a.offset();0===v.opacity&&a.css("opacity",_.opacity),u||(a.css("position","static"===f?"relative":f).offset(e),t.effects.saveStyle(a)),i()}})}),t.effects.define("scale",function(e,i){var s=t(this),n=e.mode,o=parseInt(e.percent,10)||(0===parseInt(e.percent,10)?0:"effect"!==n?0:100),a=t.extend(!0,{from:t.effects.scaledDimensions(s),to:t.effects.scaledDimensions(s,o,e.direction||"both"),origin:e.origin||["middle","center"]},e);e.fade&&(a.from.opacity=1,a.to.opacity=0),t.effects.effect.size.call(this,a,i) -}),t.effects.define("puff","hide",function(e,i){var s=t.extend(!0,{},e,{fade:!0,percent:parseInt(e.percent,10)||150});t.effects.effect.scale.call(this,s,i)}),t.effects.define("pulsate","show",function(e,i){var s=t(this),n=e.mode,o="show"===n,a="hide"===n,r=o||a,l=2*(e.times||5)+(r?1:0),h=e.duration/l,c=0,u=1,d=s.queue().length;for((o||!s.is(":visible"))&&(s.css("opacity",0).show(),c=1);l>u;u++)s.animate({opacity:c},h,e.easing),c=1-c;s.animate({opacity:c},h,e.easing),s.queue(i),t.effects.unshift(s,d,l+1)}),t.effects.define("shake",function(e,i){var s=1,n=t(this),o=e.direction||"left",a=e.distance||20,r=e.times||3,l=2*r+1,h=Math.round(e.duration/l),c="up"===o||"down"===o?"top":"left",u="up"===o||"left"===o,d={},p={},f={},g=n.queue().length;for(t.effects.createPlaceholder(n),d[c]=(u?"-=":"+=")+a,p[c]=(u?"+=":"-=")+2*a,f[c]=(u?"-=":"+=")+2*a,n.animate(d,h,e.easing);r>s;s++)n.animate(p,h,e.easing).animate(f,h,e.easing);n.animate(p,h,e.easing).animate(d,h/2,e.easing).queue(i),t.effects.unshift(n,g,l+1)}),t.effects.define("slide","show",function(e,i){var s,n,o=t(this),a={up:["bottom","top"],down:["top","bottom"],left:["right","left"],right:["left","right"]},r=e.mode,l=e.direction||"left",h="up"===l||"down"===l?"top":"left",c="up"===l||"left"===l,u=e.distance||o["top"===h?"outerHeight":"outerWidth"](!0),d={};t.effects.createPlaceholder(o),s=o.cssClip(),n=o.position()[h],d[h]=(c?-1:1)*u+n,d.clip=o.cssClip(),d.clip[a[l][1]]=d.clip[a[l][0]],"show"===r&&(o.cssClip(d.clip),o.css(h,d[h]),d.clip=s,d[h]=n),o.animate(d,{queue:!1,duration:e.duration,easing:e.easing,complete:i})});var l;t.uiBackCompat!==!1&&(l=t.effects.define("transfer",function(e,i){t(this).transfer(e,i)}))}); \ No newline at end of file diff --git a/dashboardv2/public/js/external_lib/pnotify/pnotify.custom.min.css b/dashboardv2/public/js/external_lib/pnotify/pnotify.custom.min.css deleted file mode 100644 index 1c26861fd1a..00000000000 --- a/dashboardv2/public/js/external_lib/pnotify/pnotify.custom.min.css +++ /dev/null @@ -1,10 +0,0 @@ -/*! -Author : Hunter Perrin -Version : 3.2.0 -Link : http://sciactive.com/pnotify/ -*/.ui-pnotify{top:36px;right:36px;position:absolute;height:auto;z-index:2}body>.ui-pnotify{position:fixed;z-index:100040}.ui-pnotify-modal-overlay{background-color:rgba(0,0,0,.4);top:0;left:0;position:absolute;height:100%;width:100%;z-index:1}body>.ui-pnotify-modal-overlay{position:fixed;z-index:100039}.ui-pnotify.ui-pnotify-in{display:block!important}.ui-pnotify.ui-pnotify-move{transition:left .5s ease,top .5s ease,right .5s ease,bottom .5s ease}.ui-pnotify.ui-pnotify-fade-slow{transition:opacity .4s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-slow.ui-pnotify.ui-pnotify-move{transition:opacity .4s linear,left .5s ease,top .5s ease,right .5s ease,bottom .5s ease}.ui-pnotify.ui-pnotify-fade-normal{transition:opacity .25s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-normal.ui-pnotify.ui-pnotify-move{transition:opacity .25s linear,left .5s ease,top .5s ease,right .5s ease,bottom .5s ease}.ui-pnotify.ui-pnotify-fade-fast{transition:opacity .1s linear;opacity:0}.ui-pnotify.ui-pnotify-fade-fast.ui-pnotify.ui-pnotify-move{transition:opacity .1s linear,left .5s ease,top .5s ease,right .5s ease,bottom .5s ease}.ui-pnotify.ui-pnotify-fade-in{opacity:1}.ui-pnotify .ui-pnotify-shadow{-webkit-box-shadow:0 6px 28px 0 rgba(0,0,0,.1);-moz-box-shadow:0 6px 28px 0 rgba(0,0,0,.1);box-shadow:0 6px 28px 0 rgba(0,0,0,.1)}.ui-pnotify-container{background-position:0 0;padding:.8em;height:100%;margin:0}.ui-pnotify-container:after{content:" ";visibility:hidden;display:block;height:0;clear:both}.ui-pnotify-container.ui-pnotify-sharp{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.ui-pnotify-title{display:block;margin-bottom:.4em;margin-top:0}.ui-pnotify-text{display:block}.ui-pnotify-icon,.ui-pnotify-icon span{display:block;float:left;margin-right:.2em}.ui-pnotify.stack-bottomleft,.ui-pnotify.stack-topleft{left:25px;right:auto}.ui-pnotify.stack-bottomleft,.ui-pnotify.stack-bottomright{bottom:25px;top:auto}.ui-pnotify.stack-modal{left:50%;right:auto;margin-left:-150px} -.brighttheme{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.brighttheme.ui-pnotify-container{padding:18px}.brighttheme .ui-pnotify-title{margin-bottom:12px}.brighttheme-notice{background-color:#ffffa2;border:0 solid #ff0;color:#4f4f00}.brighttheme-info{background-color:#8fcedd;border:0 solid #0286a5;color:#012831}.brighttheme-success{background-color:#aff29a;border:0 solid #35db00;color:#104300}.brighttheme-error{background-color:#ffaba2;background-image:repeating-linear-gradient(135deg,transparent,transparent 35px,rgba(255,255,255,.3) 35px,rgba(255,255,255,.3) 70px);border:0 solid #ff1800;color:#4f0800}.brighttheme-icon-closer,.brighttheme-icon-info,.brighttheme-icon-notice,.brighttheme-icon-sticker,.brighttheme-icon-success{position:relative;width:16px;height:16px;font-size:12px;font-weight:700;line-height:16px;font-family:"Courier New",Courier,monospace;border-radius:50%}.brighttheme-icon-closer:after,.brighttheme-icon-info:after,.brighttheme-icon-notice:after,.brighttheme-icon-sticker:after,.brighttheme-icon-success:after{position:absolute;top:0;left:4px}.brighttheme-icon-notice{background-color:#2e2e00;color:#ffffa2;margin-top:2px}.brighttheme-icon-notice:after{content:"!"}.brighttheme-icon-info{background-color:#012831;color:#8fcedd;margin-top:2px}.brighttheme-icon-info:after{content:"i"}.brighttheme-icon-success{background-color:#104300;color:#aff29a;margin-top:2px}.brighttheme-icon-success:after{content:"\002713"}.brighttheme-icon-error{position:relative;width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-bottom:16px solid #2e0400;font-size:0;line-height:0;color:#ffaba2;margin-top:1px}.brighttheme-icon-error:after{position:absolute;top:1px;left:-4px;font-size:12px;font-weight:700;line-height:16px;font-family:"Courier New",Courier,monospace;content:"!"}.brighttheme-icon-closer,.brighttheme-icon-sticker{display:inline-block}.brighttheme-icon-closer:after{top:-4px;content:"\002715"}.brighttheme-icon-sticker:after{top:-5px;content:"\01D1BC";-moz-transform:rotate(-90deg);-webkit-transform:rotate(-90deg);-o-transform:rotate(-90deg);-ms-transform:rotate(-90deg);transform:rotate(-90deg)}.brighttheme-icon-sticker.brighttheme-icon-stuck:after{-moz-transform:rotate(180deg);-webkit-transform:rotate(180deg);-o-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.brighttheme .ui-pnotify-action-bar{padding-top:12px}.brighttheme .ui-pnotify-action-bar input,.brighttheme .ui-pnotify-action-bar textarea{display:block;width:100%;margin-bottom:12px!important}.brighttheme .ui-pnotify-action-button{text-transform:uppercase;font-weight:700;padding:4px 8px;border:none;background:0 0}.brighttheme .ui-pnotify-action-button.btn-primary{border:none;border-radius:0}.brighttheme-notice .ui-pnotify-action-button.btn-primary{background-color:#ff0;color:#4f4f00}.brighttheme-info .ui-pnotify-action-button.btn-primary{background-color:#0286a5;color:#012831}.brighttheme-success .ui-pnotify-action-button.btn-primary{background-color:#35db00;color:#104300}.brighttheme-error .ui-pnotify-action-button.btn-primary{background-color:#ff1800;color:#4f0800} -.ui-pnotify-closer,.ui-pnotify-sticker{float:right;margin-left:.2em} -.ui-pnotify-history-container{position:absolute;top:0;right:18px;width:70px;border-top:none;padding:0;-webkit-border-top-left-radius:0;-moz-border-top-left-radius:0;border-top-left-radius:0;-webkit-border-top-right-radius:0;-moz-border-top-right-radius:0;border-top-right-radius:0;z-index:10000}.ui-pnotify-history-container.ui-pnotify-history-fixed{position:fixed}.ui-pnotify-history-container .ui-pnotify-history-header{padding:2px;text-align:center}.ui-pnotify-history-container button{cursor:pointer;display:block;width:100%}.ui-pnotify-history-container .ui-pnotify-history-pulldown{display:block;margin:0 auto}.ui-pnotify-history-brighttheme{background-color:#8fcedd;border:0 solid #0286a5;color:#012831}.ui-pnotify-history-brighttheme button{text-transform:uppercase;font-weight:700;padding:4px 8px;border:none;background:0 0}.ui-pnotify-history-brighttheme .ui-pnotify-history-pulldown::after{display:block;font-size:16px;line-height:14px;padding-bottom:4px;content:"⌄";text-align:center;font-weight:700;font-family:Arial,sans-serif} -.ui-pnotify-container{position:relative;left:0}@media (max-width:480px){.ui-pnotify-mobile-able.ui-pnotify{position:fixed;top:0;right:0;left:0;width:auto!important;font-size:1.2em;-webkit-font-smoothing:antialiased;-moz-font-smoothing:antialiased;-ms-font-smoothing:antialiased;font-smoothing:antialiased}.ui-pnotify-mobile-able.ui-pnotify .ui-pnotify-shadow{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;border-bottom-width:5px}.ui-pnotify-mobile-able .ui-pnotify-container{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.ui-pnotify-mobile-able.ui-pnotify.stack-bottomleft,.ui-pnotify-mobile-able.ui-pnotify.stack-topleft{left:0;right:0}.ui-pnotify-mobile-able.ui-pnotify.stack-bottomleft,.ui-pnotify-mobile-able.ui-pnotify.stack-bottomright{left:0;right:0;bottom:0;top:auto}.ui-pnotify-mobile-able.ui-pnotify.stack-bottomleft .ui-pnotify-shadow,.ui-pnotify-mobile-able.ui-pnotify.stack-bottomright .ui-pnotify-shadow{border-top-width:5px;border-bottom-width:1px}} -.ui-pnotify.ui-pnotify-nonblock-fade{opacity:.2}.ui-pnotify.ui-pnotify-nonblock-hide{display:none!important} diff --git a/dashboardv2/public/js/external_lib/pnotify/pnotify.custom.min.js b/dashboardv2/public/js/external_lib/pnotify/pnotify.custom.min.js deleted file mode 100644 index cac2934ec48..00000000000 --- a/dashboardv2/public/js/external_lib/pnotify/pnotify.custom.min.js +++ /dev/null @@ -1,31 +0,0 @@ -/* -PNotify 3.2.0 sciactive.com/pnotify/ -(C) 2015 Hunter Perrin; Google, Inc. -license Apache-2.0 -*/ -!function(t,i){"function"==typeof define&&define.amd?define("pnotify",["jquery"],function(s){return i(s,t)}):"object"==typeof exports&&"undefined"!=typeof module?module.exports=i(require("jquery"),global||t):t.PNotify=i(t.jQuery,t)}("undefined"!=typeof window?window:this,function(t,i){var s=function(i){var e,o,n={dir1:"down",dir2:"left",push:"bottom",spacing1:36,spacing2:36,context:t("body"),modal:!1},a=t(i),r=function(){o=t("body"),c.prototype.options.stack.context=o,a=t(i),a.bind("resize",function(){e&&clearTimeout(e),e=setTimeout(function(){c.positionAll(!0)},10)})},h=function(i){var s=t("
        ",{class:"ui-pnotify-modal-overlay"});return s.prependTo(i.context),i.overlay_close&&s.click(function(){c.removeStack(i)}),s},c=function(t){this.state="initializing",this.timer=null,this.animTimer=null,this.styles=null,this.elem=null,this.container=null,this.title_container=null,this.text_container=null,this.animating=!1,this.timerHide=!1,this.parseOptions(t),this.init()};return t.extend(c.prototype,{version:"3.2.0",options:{title:!1,title_escape:!1,text:!1,text_escape:!1,styling:"brighttheme",addclass:"",cornerclass:"",auto_display:!0,width:"300px",min_height:"16px",type:"notice",icon:!0,animation:"fade",animate_speed:"normal",shadow:!0,hide:!0,delay:8e3,mouse_reset:!0,remove:!0,insert_brs:!0,destroy:!0,stack:n},modules:{},runModules:function(t,i){var s;for(var e in this.modules)s="object"==typeof i&&e in i?i[e]:i,"function"==typeof this.modules[e][t]&&(this.modules[e].notice=this,this.modules[e].options="object"==typeof this.options[e]?this.options[e]:{},this.modules[e][t](this,"object"==typeof this.options[e]?this.options[e]:{},s))},init:function(){var i=this;return this.modules={},t.extend(!0,this.modules,c.prototype.modules),"object"==typeof this.options.styling?this.styles=this.options.styling:this.styles=c.styling[this.options.styling],this.elem=t("
        ",{class:"ui-pnotify "+this.options.addclass,css:{display:"none"},"aria-live":"assertive","aria-role":"alertdialog",mouseenter:function(t){if(i.options.mouse_reset&&"out"===i.animating){if(!i.timerHide)return;i.cancelRemove()}i.options.hide&&i.options.mouse_reset&&i.cancelRemove()},mouseleave:function(t){i.options.hide&&i.options.mouse_reset&&"out"!==i.animating&&i.queueRemove(),c.positionAll()}}),"fade"===this.options.animation&&this.elem.addClass("ui-pnotify-fade-"+this.options.animate_speed),this.container=t("
        ",{class:this.styles.container+" ui-pnotify-container "+("error"===this.options.type?this.styles.error:"info"===this.options.type?this.styles.info:"success"===this.options.type?this.styles.success:this.styles.notice),role:"alert"}).appendTo(this.elem),""!==this.options.cornerclass&&this.container.removeClass("ui-corner-all").addClass(this.options.cornerclass),this.options.shadow&&this.container.addClass("ui-pnotify-shadow"),!1!==this.options.icon&&t("
        ",{class:"ui-pnotify-icon"}).append(t("",{class:!0===this.options.icon?"error"===this.options.type?this.styles.error_icon:"info"===this.options.type?this.styles.info_icon:"success"===this.options.type?this.styles.success_icon:this.styles.notice_icon:this.options.icon})).prependTo(this.container),this.title_container=t("

        ",{class:"ui-pnotify-title"}).appendTo(this.container),!1===this.options.title?this.title_container.hide():this.options.title_escape?this.title_container.text(this.options.title):this.title_container.html(this.options.title),this.text_container=t("
        ",{class:"ui-pnotify-text","aria-role":"alert"}).appendTo(this.container),!1===this.options.text?this.text_container.hide():this.options.text_escape?this.text_container.text(this.options.text):this.text_container.html(this.options.insert_brs?String(this.options.text).replace(/\n/g,"
        "):this.options.text),"string"==typeof this.options.width&&this.elem.css("width",this.options.width),"string"==typeof this.options.min_height&&this.container.css("min-height",this.options.min_height),"top"===this.options.stack.push?c.notices=t.merge([this],c.notices):c.notices=t.merge(c.notices,[this]),"top"===this.options.stack.push&&this.queuePosition(!1,1),this.options.stack.animation=!1,this.runModules("init"),this.state="closed",this.options.auto_display&&this.open(),this},update:function(i){var s=this.options;return this.parseOptions(s,i),this.elem.removeClass("ui-pnotify-fade-slow ui-pnotify-fade-normal ui-pnotify-fade-fast"),"fade"===this.options.animation&&this.elem.addClass("ui-pnotify-fade-"+this.options.animate_speed),this.options.cornerclass!==s.cornerclass&&this.container.removeClass("ui-corner-all "+s.cornerclass).addClass(this.options.cornerclass),this.options.shadow!==s.shadow&&(this.options.shadow?this.container.addClass("ui-pnotify-shadow"):this.container.removeClass("ui-pnotify-shadow")),!1===this.options.addclass?this.elem.removeClass(s.addclass):this.options.addclass!==s.addclass&&this.elem.removeClass(s.addclass).addClass(this.options.addclass),!1===this.options.title?this.title_container.slideUp("fast"):this.options.title!==s.title&&(this.options.title_escape?this.title_container.text(this.options.title):this.title_container.html(this.options.title),!1===s.title&&this.title_container.slideDown(200)),!1===this.options.text?this.text_container.slideUp("fast"):this.options.text!==s.text&&(this.options.text_escape?this.text_container.text(this.options.text):this.text_container.html(this.options.insert_brs?String(this.options.text).replace(/\n/g,"
        "):this.options.text),!1===s.text&&this.text_container.slideDown(200)),this.options.type!==s.type&&this.container.removeClass(this.styles.error+" "+this.styles.notice+" "+this.styles.success+" "+this.styles.info).addClass("error"===this.options.type?this.styles.error:"info"===this.options.type?this.styles.info:"success"===this.options.type?this.styles.success:this.styles.notice),(this.options.icon!==s.icon||!0===this.options.icon&&this.options.type!==s.type)&&(this.container.find("div.ui-pnotify-icon").remove(),!1!==this.options.icon&&t("
        ",{class:"ui-pnotify-icon"}).append(t("",{class:!0===this.options.icon?"error"===this.options.type?this.styles.error_icon:"info"===this.options.type?this.styles.info_icon:"success"===this.options.type?this.styles.success_icon:this.styles.notice_icon:this.options.icon})).prependTo(this.container)),this.options.width!==s.width&&this.elem.animate({width:this.options.width}),this.options.min_height!==s.min_height&&this.container.animate({minHeight:this.options.min_height}),this.options.hide?s.hide||this.queueRemove():this.cancelRemove(),this.queuePosition(!0),this.runModules("update",s),this},open:function(){this.state="opening",this.runModules("beforeOpen");var t=this;return this.elem.parent().length||this.elem.appendTo(this.options.stack.context?this.options.stack.context:o),"top"!==this.options.stack.push&&this.position(!0),this.animateIn(function(){t.queuePosition(!0),t.options.hide&&t.queueRemove(),t.state="open",t.runModules("afterOpen")}),this},remove:function(s){this.state="closing",this.timerHide=!!s,this.runModules("beforeClose");var e=this;return this.timer&&(i.clearTimeout(this.timer),this.timer=null),this.animateOut(function(){if(e.state="closed",e.runModules("afterClose"),e.queuePosition(!0),e.options.remove&&e.elem.detach(),e.runModules("beforeDestroy"),e.options.destroy&&null!==c.notices){var i=t.inArray(e,c.notices);-1!==i&&c.notices.splice(i,1)}e.runModules("afterDestroy")}),this},get:function(){return this.elem},parseOptions:function(i,s){this.options=t.extend(!0,{},c.prototype.options),this.options.stack=c.prototype.options.stack;for(var e,o=[i,s],n=0;n(i.context.is(o)?a.height():i.context.prop("scrollHeight"))||"up"===i.dir1&&i.nextpos1+s.height()>(i.context.is(o)?a.height():i.context.prop("scrollHeight"))||"left"===i.dir1&&i.nextpos1+s.width()>(i.context.is(o)?a.width():i.context.prop("scrollWidth"))||"right"===i.dir1&&i.nextpos1+s.width()>(i.context.is(o)?a.width():i.context.prop("scrollWidth")))&&(i.nextpos1=i.firstpos1,i.nextpos2+=i.addpos2+(void 0===i.spacing2?25:i.spacing2),i.addpos2=0),"number"==typeof i.nextpos2&&(i.animation?s.css(p,i.nextpos2+"px"):(s.removeClass("ui-pnotify-move"),s.css(p,i.nextpos2+"px"),s.css(p),s.addClass("ui-pnotify-move"))),i.dir2){case"down":case"up":s.outerHeight(!0)>i.addpos2&&(i.addpos2=s.height());break;case"left":case"right":s.outerWidth(!0)>i.addpos2&&(i.addpos2=s.width())}switch("number"==typeof i.nextpos1&&(i.animation?s.css(c,i.nextpos1+"px"):(s.removeClass("ui-pnotify-move"),s.css(c,i.nextpos1+"px"),s.css(c),s.addClass("ui-pnotify-move"))),i.dir1){case"down":case"up":i.nextpos1+=s.height()+(void 0===i.spacing1?25:i.spacing1);break;case"left":case"right":i.nextpos1+=s.width()+(void 0===i.spacing1?25:i.spacing1)}}return this}},queuePosition:function(t,i){return e&&clearTimeout(e),i||(i=10),e=setTimeout(function(){c.positionAll(t)},i),this},cancelRemove:function(){return this.timer&&i.clearTimeout(this.timer),this.animTimer&&i.clearTimeout(this.animTimer),"closing"===this.state&&(this.state="open",this.animating=!1,this.elem.addClass("ui-pnotify-in"),"fade"===this.options.animation&&this.elem.addClass("ui-pnotify-fade-in")),this},queueRemove:function(){var t=this;return this.cancelRemove(),this.timer=i.setTimeout(function(){t.remove(!0)},isNaN(this.options.delay)?0:this.options.delay),this}}),t.extend(c,{notices:[],reload:s,removeAll:function(){t.each(c.notices,function(t,i){i.remove&&i.remove(!1)})},removeStack:function(i){t.each(c.notices,function(t,s){s.remove&&s.options.stack===i&&s.remove(!1)})},positionAll:function(i){if(e&&clearTimeout(e),e=null,c.notices&&c.notices.length)t.each(c.notices,function(t,s){var e=s.options.stack;e&&(e.overlay&&e.overlay.hide(),e.nextpos1=e.firstpos1,e.nextpos2=e.firstpos2,e.addpos2=0,e.animation=i)}),t.each(c.notices,function(t,i){i.position()});else{var s=c.prototype.options.stack;s&&(delete s.nextpos1,delete s.nextpos2)}},styling:{brighttheme:{container:"brighttheme",notice:"brighttheme-notice",notice_icon:"brighttheme-icon-notice",info:"brighttheme-info",info_icon:"brighttheme-icon-info",success:"brighttheme-success",success_icon:"brighttheme-icon-success",error:"brighttheme-error",error_icon:"brighttheme-icon-error"},bootstrap3:{container:"alert",notice:"alert-warning",notice_icon:"glyphicon glyphicon-exclamation-sign",info:"alert-info",info_icon:"glyphicon glyphicon-info-sign",success:"alert-success",success_icon:"glyphicon glyphicon-ok-sign",error:"alert-danger",error_icon:"glyphicon glyphicon-warning-sign"}}}),c.styling.fontawesome=t.extend({},c.styling.bootstrap3),t.extend(c.styling.fontawesome,{notice_icon:"fa fa-exclamation-circle",info_icon:"fa fa-info",success_icon:"fa fa-check",error_icon:"fa fa-warning"}),i.document.body?r():t(r),c};return s(i)}); -//# sourceMappingURL=pnotify.js.map -// Animate -!function(n,i){"function"==typeof define&&define.amd?define("pnotify.animate",["jquery","pnotify"],i):"object"==typeof exports&&"undefined"!=typeof module?module.exports=i(require("jquery"),require("./pnotify")):i(n.jQuery,n.PNotify)}("undefined"!=typeof window?window:this,function(n,i){return i.prototype.options.animate={animate:!1,in_class:"",out_class:""},i.prototype.modules.animate={init:function(n,i){this.setUpAnimations(n,i),n.attention=function(i,t){n.elem.one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",function(){n.elem.removeClass(i),t&&t.call(n)}).addClass("animated "+i)}},update:function(n,i,t){i.animate!=t.animate&&this.setUpAnimations(n,i)},setUpAnimations:function(n,i){if(i.animate){n.options.animation="none",n.elem.removeClass("ui-pnotify-fade-slow ui-pnotify-fade-normal ui-pnotify-fade-fast"),n._animateIn||(n._animateIn=n.animateIn),n._animateOut||(n._animateOut=n.animateOut),n.animateIn=this.animateIn.bind(this),n.animateOut=this.animateOut.bind(this);var t=400;"slow"===n.options.animate_speed?t=600:"fast"===n.options.animate_speed?t=200:n.options.animate_speed>0&&(t=n.options.animate_speed),t/=1e3,n.elem.addClass("animated").css({"-webkit-animation-duration":t+"s","-moz-animation-duration":t+"s","animation-duration":t+"s"})}else n._animateIn&&n._animateOut&&(n.animateIn=n._animateIn,delete n._animateIn,n.animateOut=n._animateOut,delete n._animateOut,n.elem.addClass("animated"))},animateIn:function(n){this.notice.animating="in";var i=this;n=function(){i.notice.elem.removeClass(i.options.in_class),this&&this.call(),i.notice.animating=!1}.bind(n),this.notice.elem.show().one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",n).removeClass(this.options.out_class).addClass("ui-pnotify-in").addClass(this.options.in_class)},animateOut:function(n){this.notice.animating="out";var i=this;n=function(){i.notice.elem.removeClass("ui-pnotify-in "+i.options.out_class),this&&this.call(),i.notice.animating=!1}.bind(n),this.notice.elem.one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend",n).removeClass(this.options.in_class).addClass(this.options.out_class)}},i}); -//# sourceMappingURL=pnotify.animate.js.map -// Buttons -!function(o,s){"function"==typeof define&&define.amd?define("pnotify.buttons",["jquery","pnotify"],s):"object"==typeof exports&&"undefined"!=typeof module?module.exports=s(require("jquery"),require("./pnotify")):s(o.jQuery,o.PNotify)}("undefined"!=typeof window?window:this,function(o,s){return s.prototype.options.buttons={closer:!0,closer_hover:!0,sticker:!0,sticker_hover:!0,show_on_nonblock:!1,labels:{close:"Close",stick:"Stick",unstick:"Unstick"},classes:{closer:null,pin_up:null,pin_down:null}},s.prototype.modules.buttons={init:function(s,i){var n=this;s.elem.on({mouseenter:function(o){!n.options.sticker||s.options.nonblock&&s.options.nonblock.nonblock&&!n.options.show_on_nonblock||n.sticker.trigger("pnotify:buttons:toggleStick").css("visibility","visible"),!n.options.closer||s.options.nonblock&&s.options.nonblock.nonblock&&!n.options.show_on_nonblock||n.closer.css("visibility","visible")},mouseleave:function(o){n.options.sticker_hover&&n.sticker.css("visibility","hidden"),n.options.closer_hover&&n.closer.css("visibility","hidden")}}),this.sticker=o("
        ",{class:"ui-pnotify-sticker","aria-role":"button","aria-pressed":s.options.hide?"false":"true",tabindex:"0",title:s.options.hide?i.labels.stick:i.labels.unstick,css:{cursor:"pointer",visibility:i.sticker_hover?"hidden":"visible"},click:function(){s.options.hide=!s.options.hide,s.options.hide?s.queueRemove():s.cancelRemove(),o(this).trigger("pnotify:buttons:toggleStick")}}).bind("pnotify:buttons:toggleStick",function(){var i=null===n.options.classes.pin_up?s.styles.pin_up:n.options.classes.pin_up,e=null===n.options.classes.pin_down?s.styles.pin_down:n.options.classes.pin_down;o(this).attr("title",s.options.hide?n.options.labels.stick:n.options.labels.unstick).children().attr("class","").addClass(s.options.hide?i:e).attr("aria-pressed",s.options.hide?"false":"true")}).append("").trigger("pnotify:buttons:toggleStick").prependTo(s.container),(!i.sticker||s.options.nonblock&&s.options.nonblock.nonblock&&!i.show_on_nonblock)&&this.sticker.css("display","none"),this.closer=o("
        ",{class:"ui-pnotify-closer","aria-role":"button",tabindex:"0",title:i.labels.close,css:{cursor:"pointer",visibility:i.closer_hover?"hidden":"visible"},click:function(){s.remove(!1),n.sticker.css("visibility","hidden"),n.closer.css("visibility","hidden")}}).append(o("",{class:null===i.classes.closer?s.styles.closer:i.classes.closer})).prependTo(s.container),(!i.closer||s.options.nonblock&&s.options.nonblock.nonblock&&!i.show_on_nonblock)&&this.closer.css("display","none")},update:function(o,s){!s.closer||o.options.nonblock&&o.options.nonblock.nonblock&&!s.show_on_nonblock?this.closer.css("display","none"):s.closer&&this.closer.css("display","block"),!s.sticker||o.options.nonblock&&o.options.nonblock.nonblock&&!s.show_on_nonblock?this.sticker.css("display","none"):s.sticker&&this.sticker.css("display","block"),this.sticker.trigger("pnotify:buttons:toggleStick"),this.closer.find("span").attr("class","").addClass(null===s.classes.closer?o.styles.closer:s.classes.closer),s.sticker_hover?this.sticker.css("visibility","hidden"):o.options.nonblock&&o.options.nonblock.nonblock&&!s.show_on_nonblock||this.sticker.css("visibility","visible"),s.closer_hover?this.closer.css("visibility","hidden"):o.options.nonblock&&o.options.nonblock.nonblock&&!s.show_on_nonblock||this.closer.css("visibility","visible")}},o.extend(s.styling.brighttheme,{closer:"brighttheme-icon-closer",pin_up:"brighttheme-icon-sticker",pin_down:"brighttheme-icon-sticker brighttheme-icon-stuck"}),o.extend(s.styling.bootstrap3,{closer:"glyphicon glyphicon-remove",pin_up:"glyphicon glyphicon-pause",pin_down:"glyphicon glyphicon-play"}),o.extend(s.styling.fontawesome,{closer:"fa fa-times",pin_up:"fa fa-pause",pin_down:"fa fa-play"}),s}); -//# sourceMappingURL=pnotify.buttons.js.map -// Callbacks -!function(o,t){"function"==typeof define&&define.amd?define("pnotify.callbacks",["jquery","pnotify"],t):"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("jquery"),require("./pnotify")):t(o.jQuery,o.PNotify)}("undefined"!=typeof window?window:this,function(o,t){var i=t.prototype.init,e=t.prototype.open,n=t.prototype.remove;return t.prototype.init=function(){this.options.before_init&&this.options.before_init(this.options),i.apply(this,arguments),this.options.after_init&&this.options.after_init(this)},t.prototype.open=function(){var o;this.options.before_open&&(o=this.options.before_open(this)),!1!==o&&(e.apply(this,arguments),this.options.after_open&&this.options.after_open(this))},t.prototype.remove=function(o){var t;this.options.before_close&&(t=this.options.before_close(this,o)),!1!==t&&(n.apply(this,arguments),this.options.after_close&&this.options.after_close(this,o))},t}); -//# sourceMappingURL=pnotify.callbacks.js.map -// Confirm -!function(t,n){"function"==typeof define&&define.amd?define("pnotify.confirm",["jquery","pnotify"],n):"object"==typeof exports&&"undefined"!=typeof module?module.exports=n(require("jquery"),require("./pnotify")):n(t.jQuery,t.PNotify)}("undefined"!=typeof window?window:this,function(t,n){return n.prototype.options.confirm={confirm:!1,prompt:!1,prompt_class:"",prompt_default:"",prompt_multi_line:!1,align:"right",buttons:[{text:"Ok",addClass:"",promptTrigger:!0,click:function(t,n){t.remove(),t.get().trigger("pnotify.confirm",[t,n])}},{text:"Cancel",addClass:"",click:function(t){t.remove(),t.get().trigger("pnotify.cancel",t)}}]},n.prototype.modules.confirm={init:function(n,o){this.container=t('
        ').css("text-align",o.align).appendTo(n.container),o.confirm||o.prompt?this.makeDialog(n,o):this.container.hide()},update:function(t,n){n.confirm?(this.makeDialog(t,n),this.container.show()):this.container.hide().empty()},afterOpen:function(t,n){n.prompt&&this.prompt.focus()},makeDialog:function(o,e){var i,s,r=!1,p=this;this.container.empty(),e.prompt&&(this.prompt=t("<"+(e.prompt_multi_line?'textarea rows="5"':'input type="text"')+' style="margin-bottom:5px;clear:both;" />').addClass((void 0===o.styles.input?"":o.styles.input)+" "+(void 0===e.prompt_class?"":e.prompt_class)).val(e.prompt_default).appendTo(this.container));for(var u=e.buttons[0]&&e.buttons[0]!==n.prototype.options.confirm.buttons[0],c=0;c').addClass((void 0===o.styles.btn?"":o.styles.btn)+" "+(void 0===i.addClass?"":i.addClass)).text(i.text).appendTo(this.container).on("click",function(t){return function(){"function"==typeof t.click&&t.click(o,e.prompt?p.prompt.val():null)}}(i)),e.prompt&&!e.prompt_multi_line&&i.promptTrigger&&this.prompt.keypress(function(t){return function(n){13==n.keyCode&&t.click()}}(s)),o.styles.text&&s.wrapInner(''),o.styles.btnhover&&s.hover(function(t){return function(){t.addClass(o.styles.btnhover)}}(s),function(t){return function(){t.removeClass(o.styles.btnhover)}}(s)),o.styles.btnactive&&s.on("mousedown",function(t){return function(){t.addClass(o.styles.btnactive)}}(s)).on("mouseup",function(t){return function(){t.removeClass(o.styles.btnactive)}}(s)),o.styles.btnfocus&&s.on("focus",function(t){return function(){t.addClass(o.styles.btnfocus)}}(s)).on("blur",function(t){return function(){t.removeClass(o.styles.btnfocus)}}(s)))}},t.extend(n.styling.bootstrap3,{btn:"btn btn-default",input:"form-control"}),t.extend(n.styling.fontawesome,{btn:"btn btn-default",input:"form-control"}),n}); -//# sourceMappingURL=pnotify.confirm.js.map -// Desktop -!function(i,t){"function"==typeof define&&define.amd?define("pnotify.desktop",["jquery","pnotify"],t):"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("jquery"),require("./pnotify")):t(i.jQuery,i.PNotify)}("undefined"!=typeof window?window:this,function(i,t){var o,n=function(i,t){return(n="Notification"in window?function(i,t){return new Notification(i,t)}:"mozNotification"in navigator?function(i,t){return navigator.mozNotification.createNotification(i,t.body,t.icon).show()}:"webkitNotifications"in window?function(i,t){return window.webkitNotifications.createNotification(t.icon,i,t.body)}:function(i,t){return null})(i,t)};return t.prototype.options.desktop={desktop:!1,fallback:!0,icon:null,tag:null,title:null,text:null},t.prototype.modules.desktop={genNotice:function(i,t){null===t.icon?this.icon="http://sciactive.com/pnotify/includes/desktop/"+i.options.type+".png":!1===t.icon?this.icon=null:this.icon=t.icon,null!==this.tag&&null===t.tag||(this.tag=null===t.tag?"PNotify-"+Math.round(1e6*Math.random()):t.tag),i.desktop=n(t.title||i.options.title,{icon:this.icon,body:t.text||i.options.text,tag:this.tag}),!("close"in i.desktop)&&"cancel"in i.desktop&&(i.desktop.close=function(){i.desktop.cancel()}),i.desktop.onclick=function(){i.elem.trigger("click")},i.desktop.onclose=function(){"closing"!==i.state&&"closed"!==i.state&&i.remove()}},init:function(i,n){if(n.desktop){if(0!==(o=t.desktop.checkPermission()))return void(n.fallback||(i.options.auto_display=!1));this.genNotice(i,n)}},update:function(i,t,n){0!==o&&t.fallback||!t.desktop||this.genNotice(i,t)},beforeOpen:function(i,t){0!==o&&t.fallback||!t.desktop||i.elem.css({left:"-10000px"}).removeClass("ui-pnotify-in")},afterOpen:function(i,t){0!==o&&t.fallback||!t.desktop||(i.elem.css({left:"-10000px"}).removeClass("ui-pnotify-in"),"show"in i.desktop&&i.desktop.show())},beforeClose:function(i,t){0!==o&&t.fallback||!t.desktop||i.elem.css({left:"-10000px"}).removeClass("ui-pnotify-in")},afterClose:function(i,t){0!==o&&t.fallback||!t.desktop||(i.elem.css({left:"-10000px"}).removeClass("ui-pnotify-in"),"close"in i.desktop&&i.desktop.close())}},t.desktop={permission:function(){"undefined"!=typeof Notification&&"requestPermission"in Notification?Notification.requestPermission():"webkitNotifications"in window&&window.webkitNotifications.requestPermission()},checkPermission:function(){return"undefined"!=typeof Notification&&"permission"in Notification?"granted"===Notification.permission?0:1:"webkitNotifications"in window&&0==window.webkitNotifications.checkPermission()?0:1}},o=t.desktop.checkPermission(),t}); -//# sourceMappingURL=pnotify.desktop.js.map -// History -!function(t,i){"function"==typeof define&&define.amd?define("pnotify.history",["jquery","pnotify"],i):"object"==typeof exports&&"undefined"!=typeof module?module.exports=i(require("jquery"),require("./pnotify")):i(t.jQuery,t.PNotify)}("undefined"!=typeof window?window:this,function(t,i){var e,o;return t(function(){t("body").on("pnotify.history-all",function(){t.each(i.notices,function(){this.modules.history.inHistory&&(this.elem.is(":visible")?this.options.hide&&this.queueRemove():this.open&&this.open())})}).on("pnotify.history-last",function(){var t,e="top"===i.prototype.options.stack.push,o=e?0:-1;do{if(t=-1===o?i.notices.slice(o):i.notices.slice(o,o+1),!t[0])return!1;o=e?o+1:o-1}while(!t[0].modules.history.inHistory||t[0].elem.is(":visible"));t[0].open&&t[0].open()})}),i.prototype.options.history={history:!0,menu:!1,fixed:!0,maxonscreen:1/0,labels:{redisplay:"Redisplay",all:"All",last:"Last"}},i.prototype.modules.history={init:function(i,n){if(i.options.destroy=!1,this.inHistory=n.history,n.menu&&void 0===e){e=t("
        ",{class:"ui-pnotify-history-container "+i.styles.hi_menu,mouseleave:function(){e.css("top","-"+o+"px")}}).append(t("
        ",{class:"ui-pnotify-history-header",text:n.labels.redisplay})).append(t("
        \ No newline at end of file diff --git a/dashboardv2/public/js/templates/audit/AdminAuditTableLayoutView_tmpl.html b/dashboardv2/public/js/templates/audit/AdminAuditTableLayoutView_tmpl.html deleted file mode 100644 index 62bef23f9b7..00000000000 --- a/dashboardv2/public/js/templates/audit/AdminAuditTableLayoutView_tmpl.html +++ /dev/null @@ -1,75 +0,0 @@ - -
        -
        -
        -
        - -
        -
        -
        - -
        - -
        -
        - -
        -
        -
        -

        - Admin -

        -
        - -
        -
        -
        -
        -
        -
        -
        -
        -
        -
        - -
        -
        - -
        -
        -
        -
        -
        -

    - - - - - -
    No Records found!
    - - - - - \ No newline at end of file diff --git a/dashboardv2/public/js/templates/audit/AuditTableLayoutView_tmpl.html b/dashboardv2/public/js/templates/audit/AuditTableLayoutView_tmpl.html deleted file mode 100644 index c8d8a503451..00000000000 --- a/dashboardv2/public/js/templates/audit/AuditTableLayoutView_tmpl.html +++ /dev/null @@ -1,26 +0,0 @@ - -

    -
    - -
    - -
    - -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/audit/CreateAuditTableLayoutView_tmpl.html b/dashboardv2/public/js/templates/audit/CreateAuditTableLayoutView_tmpl.html deleted file mode 100644 index 11814d39fa1..00000000000 --- a/dashboardv2/public/js/templates/audit/CreateAuditTableLayoutView_tmpl.html +++ /dev/null @@ -1,124 +0,0 @@ - -

    -
    -
    -
    -

    - Properties -

    -
    - -
    -
    -
    -
    - - - - - - -
    No records found!
    -
    -
    -
    -
    -
    -

    - Technical properties -

    -
    - -
    -
    -
    -
    - - - - - - -
    No records found!
    -
    -
    -
    -
    - -
    -
    - - - - - - -
    No records found!
    -
    -
    -
    -
    - -
    -
    - - - - - - -
    No records found!
    -
    -
    -
    -
    -
    -

    - Labels -

    -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    No details to show!

    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/audit/ReplicationAuditTableLayoutView_tmpl.html b/dashboardv2/public/js/templates/audit/ReplicationAuditTableLayoutView_tmpl.html deleted file mode 100644 index 83fdd57fe9d..00000000000 --- a/dashboardv2/public/js/templates/audit/ReplicationAuditTableLayoutView_tmpl.html +++ /dev/null @@ -1,20 +0,0 @@ - -
    -
    -
    -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/business_metadata/BusinessMetadataAttrTableLayoutView_tmpl.html b/dashboardv2/public/js/templates/business_metadata/BusinessMetadataAttrTableLayoutView_tmpl.html deleted file mode 100644 index 98f30a3b12b..00000000000 --- a/dashboardv2/public/js/templates/business_metadata/BusinessMetadataAttrTableLayoutView_tmpl.html +++ /dev/null @@ -1,47 +0,0 @@ - - - \ No newline at end of file diff --git a/dashboardv2/public/js/templates/business_metadata/BusinessMetadataAttributeItemView_tmpl.html b/dashboardv2/public/js/templates/business_metadata/BusinessMetadataAttributeItemView_tmpl.html deleted file mode 100644 index 3d316f68869..00000000000 --- a/dashboardv2/public/js/templates/business_metadata/BusinessMetadataAttributeItemView_tmpl.html +++ /dev/null @@ -1,110 +0,0 @@ - - \ No newline at end of file diff --git a/dashboardv2/public/js/templates/business_metadata/BusinessMetadataContainerLayoutView_tmpl.html b/dashboardv2/public/js/templates/business_metadata/BusinessMetadataContainerLayoutView_tmpl.html deleted file mode 100644 index d964202c81d..00000000000 --- a/dashboardv2/public/js/templates/business_metadata/BusinessMetadataContainerLayoutView_tmpl.html +++ /dev/null @@ -1,20 +0,0 @@ - -
    -
    -
    -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/business_metadata/BusinessMetadataDetailLayoutView_tmpl.html b/dashboardv2/public/js/templates/business_metadata/BusinessMetadataDetailLayoutView_tmpl.html deleted file mode 100644 index d8a2b5b873a..00000000000 --- a/dashboardv2/public/js/templates/business_metadata/BusinessMetadataDetailLayoutView_tmpl.html +++ /dev/null @@ -1,26 +0,0 @@ - -
    -
    - -
    -
    -

    -

    -
    -
    - \ No newline at end of file diff --git a/dashboardv2/public/js/templates/business_metadata/BusinessMetadataTableLayoutView_tmpl.html b/dashboardv2/public/js/templates/business_metadata/BusinessMetadataTableLayoutView_tmpl.html deleted file mode 100644 index 154d5b8bf80..00000000000 --- a/dashboardv2/public/js/templates/business_metadata/BusinessMetadataTableLayoutView_tmpl.html +++ /dev/null @@ -1,47 +0,0 @@ - - - \ No newline at end of file diff --git a/dashboardv2/public/js/templates/business_metadata/CreateBusinessMetadataLayoutView_tmpl.html b/dashboardv2/public/js/templates/business_metadata/CreateBusinessMetadataLayoutView_tmpl.html deleted file mode 100644 index a78614d15f5..00000000000 --- a/dashboardv2/public/js/templates/business_metadata/CreateBusinessMetadataLayoutView_tmpl.html +++ /dev/null @@ -1,53 +0,0 @@ - -
    - -
    -
    - {{#if fromTable}} -
    - - {{#if create}} -
    - -
    - {{else}} - {{/if}} -
    -
    - -
    - -
    -
    - {{/if}} -
    - - {{#if isEditAttr}} -
    - -
    - {{/if}} -
    -
    -
    - -
    - \ No newline at end of file diff --git a/dashboardv2/public/js/templates/business_metadata/EnumCreateUpdateItemView_tmpl.html b/dashboardv2/public/js/templates/business_metadata/EnumCreateUpdateItemView_tmpl.html deleted file mode 100644 index be0ab813cca..00000000000 --- a/dashboardv2/public/js/templates/business_metadata/EnumCreateUpdateItemView_tmpl.html +++ /dev/null @@ -1,39 +0,0 @@ - -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - - -
    -
    -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/common/Modal.html b/dashboardv2/public/js/templates/common/Modal.html deleted file mode 100644 index 207722e5b7e..00000000000 --- a/dashboardv2/public/js/templates/common/Modal.html +++ /dev/null @@ -1,52 +0,0 @@ - - \ No newline at end of file diff --git a/dashboardv2/public/js/templates/common/TableLayout_tmpl.html b/dashboardv2/public/js/templates/common/TableLayout_tmpl.html deleted file mode 100644 index 4b5698a43bd..00000000000 --- a/dashboardv2/public/js/templates/common/TableLayout_tmpl.html +++ /dev/null @@ -1,112 +0,0 @@ - -
    -
    -
    - {{#unless columnOpts.el}} -
    - {{/unless}} -
    -
    -
    -
    - {{#if includeTableLoader}} -
    - -
    - {{/if}} -
    - {{#if includePagination}} -
    -
    -
    -
    -
    -
    -
    - {{#if includeGotoPage}} - - {{/if}} - {{#if includePageSize}} -
    -
    - Page Limit : -
    - -
    -
    -
    - {{/if}} -
    -
    -
    - {{/if}} {{#if includeAtlasPagination}} -
    -
    - -
    -
    -
    -
    -
      -
    • - -
    • -
    • - -
    • -
    • - -
    • -
    -
    - {{#if includeAtlasGotoPage}} - - {{/if}} {{#if includeAtlasPageSize}} -
    -
    - Page Limit : -
    - -
    -
    -
    - {{/if}} -
    -
    -
    - {{/if}} -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/common/buttons_tmpl.html b/dashboardv2/public/js/templates/common/buttons_tmpl.html deleted file mode 100644 index 19db7cfe34d..00000000000 --- a/dashboardv2/public/js/templates/common/buttons_tmpl.html +++ /dev/null @@ -1,19 +0,0 @@ - -{{#if btn_edit}} - -{{/if}} \ No newline at end of file diff --git a/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html b/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html deleted file mode 100644 index ee4b9431fdf..00000000000 --- a/dashboardv2/public/js/templates/detail_page/DetailPageLayoutView_tmpl.html +++ /dev/null @@ -1,154 +0,0 @@ - -
    -
    - -
    -
    -

    -
    - -

    {{#if entityUpdate}} - - {{/if}} -
    - Classifications: -
    - -
    -
    -
    - Terms: -
    - -
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - \ No newline at end of file diff --git a/dashboardv2/public/js/templates/detail_page/PendingTaskTableLayoutView_tmpl.html b/dashboardv2/public/js/templates/detail_page/PendingTaskTableLayoutView_tmpl.html deleted file mode 100644 index 059c42f6909..00000000000 --- a/dashboardv2/public/js/templates/detail_page/PendingTaskTableLayoutView_tmpl.html +++ /dev/null @@ -1,26 +0,0 @@ - -
    - -
    -
    - -
    - -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/dev_debug/DebugMetricsLayoutView_tmpl.html b/dashboardv2/public/js/templates/dev_debug/DebugMetricsLayoutView_tmpl.html deleted file mode 100644 index 78d91bf13c8..00000000000 --- a/dashboardv2/public/js/templates/dev_debug/DebugMetricsLayoutView_tmpl.html +++ /dev/null @@ -1,30 +0,0 @@ - -
    - -
    -
    -
    -
    -
    -
    -
    - \ No newline at end of file diff --git a/dashboardv2/public/js/templates/entity/CreateEntityLayoutView_tmpl.html b/dashboardv2/public/js/templates/entity/CreateEntityLayoutView_tmpl.html deleted file mode 100644 index 9fcbd858990..00000000000 --- a/dashboardv2/public/js/templates/entity/CreateEntityLayoutView_tmpl.html +++ /dev/null @@ -1,45 +0,0 @@ - -
    -
    -
    -
    - {{#if guid}} -
    - -
    - {{else}} -
    - -
    - {{/if}} -
    - Required - - All -
    -
    -
    -
    -
    -
    - \ No newline at end of file diff --git a/dashboardv2/public/js/templates/entity/EntityBusinessMetaDataItemView_tmpl.html b/dashboardv2/public/js/templates/entity/EntityBusinessMetaDataItemView_tmpl.html deleted file mode 100644 index 0b92cb1c215..00000000000 --- a/dashboardv2/public/js/templates/entity/EntityBusinessMetaDataItemView_tmpl.html +++ /dev/null @@ -1,44 +0,0 @@ - -{{#ifCond model "has" "isNew"}} - - - - - - - -
    - {{{callmyfunction getBusinessMetadataDroupdown businessMetadataCollection}}} - : - - - - -
    -{{else}} -
    - -{{/ifCond}} \ No newline at end of file diff --git a/dashboardv2/public/js/templates/entity/EntityBusinessMetaDataView_tmpl.html b/dashboardv2/public/js/templates/entity/EntityBusinessMetaDataView_tmpl.html deleted file mode 100644 index 4904c28d8bb..00000000000 --- a/dashboardv2/public/js/templates/entity/EntityBusinessMetaDataView_tmpl.html +++ /dev/null @@ -1,44 +0,0 @@ - -
    - - {{#ifCond readOnlyEntity "===" false}} -
    - - - -
    - {{/ifCond}} -
    -
    -
    - -
    -
    -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/entity/EntityDetailTableLayoutView_tmpl.html b/dashboardv2/public/js/templates/entity/EntityDetailTableLayoutView_tmpl.html deleted file mode 100644 index 3fe0e95e50f..00000000000 --- a/dashboardv2/public/js/templates/entity/EntityDetailTableLayoutView_tmpl.html +++ /dev/null @@ -1,49 +0,0 @@ - -
    -
    -
    -

    - Technical properties -

    -
    - -
    -
    -
    -
    - -
    - -
    -
    - {{#ifCond editEntity "===" true}} - - {{/ifCond}} -
    -
    -
    -
    - - - -
    -
    -
    -
    -
    -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/entity/EntityLabelDefineView_tmpl.html b/dashboardv2/public/js/templates/entity/EntityLabelDefineView_tmpl.html deleted file mode 100644 index 0b54481200b..00000000000 --- a/dashboardv2/public/js/templates/entity/EntityLabelDefineView_tmpl.html +++ /dev/null @@ -1,90 +0,0 @@ - -
    -
    - {{#ifCond labels.length "===" 0}} -
    -

    - Labels -

    -
    - -
    -
    - {{else}} -
    -

    - Labels -

    -
    - -
    -
    - {{/ifCond}} - {{#ifCond readOnlyEntity "===" false}} -
    - {{#ifCond swapItem "!==" true}} - - {{/ifCond}} - {{#ifCond saveLabels "===" true}} - - - {{/ifCond}} -
    - {{/ifCond}} -
    - {{#ifCond labels.length "===" 0}} -
    -
    -
    - {{#ifCond swapItem "===" true}} - - {{else}} - {{#ifCond readOnlyEntity "===" false}} -
    - No labels have been created yet. To add a labels, click here -
    - {{/ifCond}} - {{/ifCond}} -
    -
    -
    - {{/ifCond}} -
    - {{#ifCond labels.length ">" 0}} -
    -
    -
    -
    - {{#ifCond swapItem "===" true}} - - {{else}} -
    - {{#each labels}} - - {{/each}} -
    - {{/ifCond}} -
    -
    -
    -
    - {{/ifCond}} -
    -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/entity/EntityUserDefineItemView_tmpl.html b/dashboardv2/public/js/templates/entity/EntityUserDefineItemView_tmpl.html deleted file mode 100644 index edc6ba27967..00000000000 --- a/dashboardv2/public/js/templates/entity/EntityUserDefineItemView_tmpl.html +++ /dev/null @@ -1,49 +0,0 @@ - - - {{#each items}} - - - - - - - {{/each}} - - - - {{#if allValueRemovedUpdate}} - All properties has been removed. To add a property, click here{{else}} - {{#ifCond items.length "===" 0}} - No properties have been created yet. To add a property, click here - {{/ifCond}}{{/if}} -
    - -

    -
    : - -

    -
    - - -
    -

    -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/entity/EntityUserDefineView_tmpl.html b/dashboardv2/public/js/templates/entity/EntityUserDefineView_tmpl.html deleted file mode 100644 index c0fd384b70a..00000000000 --- a/dashboardv2/public/js/templates/entity/EntityUserDefineView_tmpl.html +++ /dev/null @@ -1,101 +0,0 @@ - -
    -
    - {{#ifCond customAttibutes.length "===" 0}} - - {{else}} - - {{/ifCond}} - {{#ifCond readOnlyEntity "===" false}} -
    - {{#ifCond swapItem "!==" true}} - - {{/ifCond}} - {{#ifCond saveAttrItems "===" true}} - - - {{/ifCond}} -
    - {{/ifCond}} -
    - {{#ifCond customAttibutes.length "===" 0}} -
    -
    -
    - {{#ifCond swapItem "===" true}} -
    - {{else}} - {{#ifCond readOnlyEntity "===" false}} - No properties have been created yet. To add a property, click here - {{/ifCond}} -
    - {{/ifCond}} -
    -
    -
    - {{/ifCond}} -
    - {{#ifCond customAttibutes.length ">" 0}} -
    -
    -
    -
    - {{#ifCond swapItem "===" true}} -
    - {{else}} -
    - - - {{#each customAttibutes}} - - - - - {{/each}} - -
    -
    {{key}}
    - -
    -
    {{value}}
    -
    -
    - {{/ifCond}} -
    -
    -
    -
    -{{/ifCond}} -
    - \ No newline at end of file diff --git a/dashboardv2/public/js/templates/glossary/AssignTermLayoutView_tmpl.html b/dashboardv2/public/js/templates/glossary/AssignTermLayoutView_tmpl.html deleted file mode 100644 index 978aa12cd0e..00000000000 --- a/dashboardv2/public/js/templates/glossary/AssignTermLayoutView_tmpl.html +++ /dev/null @@ -1,39 +0,0 @@ - -{{#if isAttributeRelationView}} -
    -

    Select Term

    -
    -
    -
    -

    Attributes

    -
    -
    - {{#each selectedTermAttributeList}} -
    - -
    - -
    -
    - {{/each}} -
    -
    -
    -{{else}} -
    -{{/if}} \ No newline at end of file diff --git a/dashboardv2/public/js/templates/glossary/CreateEditCategoryTermLayoutView_tmpl.html b/dashboardv2/public/js/templates/glossary/CreateEditCategoryTermLayoutView_tmpl.html deleted file mode 100644 index 88565023048..00000000000 --- a/dashboardv2/public/js/templates/glossary/CreateEditCategoryTermLayoutView_tmpl.html +++ /dev/null @@ -1,36 +0,0 @@ - -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/glossary/CreateEditGlossaryLayoutView_tmpl.html b/dashboardv2/public/js/templates/glossary/CreateEditGlossaryLayoutView_tmpl.html deleted file mode 100644 index f1e4ef20bb9..00000000000 --- a/dashboardv2/public/js/templates/glossary/CreateEditGlossaryLayoutView_tmpl.html +++ /dev/null @@ -1,36 +0,0 @@ - -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html b/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html deleted file mode 100644 index 4600df78a82..00000000000 --- a/dashboardv2/public/js/templates/glossary/GlossaryDetailLayoutView_tmpl.html +++ /dev/null @@ -1,99 +0,0 @@ - -
    -
    - -
    -
    -

    - -
    - Short Description:  -
    -

    -
    -
    -
    - Long Description:  -
    - -
    -
    - {{#if isTermView}} -
    - Classifications: -
    - -
    -
    -
    - Categories: -
    - -
    -
    - {{/if}} {{#if isCategoryView}} -
    - Terms: -
    - -
    -
    - {{/if}} {{#if isTermView}} - - {{/if}} -
    -
    -{{#if isTermView}} -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -{{/if}} \ No newline at end of file diff --git a/dashboardv2/public/js/templates/glossary/GlossaryLayoutView_tmpl.html b/dashboardv2/public/js/templates/glossary/GlossaryLayoutView_tmpl.html deleted file mode 100644 index 805e5dc3c3f..00000000000 --- a/dashboardv2/public/js/templates/glossary/GlossaryLayoutView_tmpl.html +++ /dev/null @@ -1,65 +0,0 @@ - -
    -
    - {{#unless isAssignView}} -
    - Terms - - Category -
    -
    - - - - - {{/unless}} -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    - -
    -
    -
    -
    - -
    -
    -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/glossary/TermRelationAttributeLayoutView_tmpl.html b/dashboardv2/public/js/templates/glossary/TermRelationAttributeLayoutView_tmpl.html deleted file mode 100644 index 8173682ade1..00000000000 --- a/dashboardv2/public/js/templates/glossary/TermRelationAttributeLayoutView_tmpl.html +++ /dev/null @@ -1,19 +0,0 @@ - -
    -
    -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/glossary/TermRelationAttributeTable_tmpl.html b/dashboardv2/public/js/templates/glossary/TermRelationAttributeTable_tmpl.html deleted file mode 100644 index 50381e93516..00000000000 --- a/dashboardv2/public/js/templates/glossary/TermRelationAttributeTable_tmpl.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - {{#if relationTypeTable}} - {{/if}} - - - - {{#if relationTypeTable}} {{#each attributes}} - - - {{{callmyfunction ../getTerms @key}}} - - {{/each}} {{else}} {{#if attributeValue}} {{#each attributeValue}} - - - - - {{/each}}{{else}} - - - {{/if}} {{/if}} - -
    {{#if relationTypeTable}}Relation Types{{else}}Term{{/if}}{{#if relationTypeTable}}Related Terms{{else}}Attribute{{/if}}Attributes
    {{@key}}
    {{this.displayText}} -
    - - - - - - - - - {{#each ../attributes}} - - - {{#if ../../editMode}} - {{else}} - - {{/if}} - - {{/each}} - -
    NameValue
    {{@key}} - - {{lookup ../../this @key "- "}}
    -
    -
    No records found!
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html b/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html deleted file mode 100644 index 5f90b096e3e..00000000000 --- a/dashboardv2/public/js/templates/graph/LineageLayoutView_tmpl.html +++ /dev/null @@ -1,153 +0,0 @@ - - -
    -
    -
    -

    Filters

    - -
    -
    -
    -
    - -
    - -
    -
    -
    -
    -
    - -
    - -
    -
    -
    -
    - -
    - -
    -
    -
    -
    - -
    -
    -

    Settings

    - -
    -
    -
    -
    - -
    - -
    -
    -
    -
    -
    - -
    - -
    -
    -
    -
    -
    - -
    - -
    -
    -
    -
    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - - -
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    -
    -

    - - -
    -
    - - -
    -
    -
    -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/graph/PropagationPropertyModalView_tmpl.html b/dashboardv2/public/js/templates/graph/PropagationPropertyModalView_tmpl.html deleted file mode 100644 index 7dc4850cacd..00000000000 --- a/dashboardv2/public/js/templates/graph/PropagationPropertyModalView_tmpl.html +++ /dev/null @@ -1,80 +0,0 @@ - -
    -
    -
    -
    - Enable/Disable Propagation - - Select Classifications to Block Propagation -
    -
    -
    -
    -
    -

    -
    -
    - -
    -
    -
    -
      -
    • -
      - - -
      -
    • - - -
    • -
      - - -
      -
    • -
    -
    -
    - -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/graph/RelationshipLayoutView_tmpl.html b/dashboardv2/public/js/templates/graph/RelationshipLayoutView_tmpl.html deleted file mode 100644 index acf9bb3a307..00000000000 --- a/dashboardv2/public/js/templates/graph/RelationshipLayoutView_tmpl.html +++ /dev/null @@ -1,74 +0,0 @@ - -
    -
    - Graph - - Table -
    -
    -
    - - -
    -
    - Active - Deleted -
    -
    -
    - -
    -
    -
    - -
    - -
    -
    -
    - - - - - - - - - -
    KeyValue
    -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/graph/TypeSystemTreeView_tmpl.html b/dashboardv2/public/js/templates/graph/TypeSystemTreeView_tmpl.html deleted file mode 100644 index 3b4a67e9a88..00000000000 --- a/dashboardv2/public/js/templates/graph/TypeSystemTreeView_tmpl.html +++ /dev/null @@ -1,149 +0,0 @@ - -
    -
    -
    -
    -

    -
    - -
    - -
    -
    - -
    - -
    -
    - - -
    -
    -
    
    -            
    -
    -
    -
    - -
    -
    -
    -

    Filters

    - -
    -
    -
    - -
    -
    -
    - -
    -
    -

    Settings

    - -
    -
    -
    -
    - -
    - -
    -
    -
    -
    -
    - -
    - -
    -
    -
    -
    -
    - -
    - -
    -
    -
    -
    -
    -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - -
    -
    - - -
    -
    - -
    -
    - - - -
    \ No newline at end of file diff --git a/dashboardv2/public/js/templates/import/ImportLayoutView_tmpl.html b/dashboardv2/public/js/templates/import/ImportLayoutView_tmpl.html deleted file mode 100644 index 2199d28d090..00000000000 --- a/dashboardv2/public/js/templates/import/ImportLayoutView_tmpl.html +++ /dev/null @@ -1,20 +0,0 @@ - -
    -
    -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/migration/MigrationView_tmpl.html b/dashboardv2/public/js/templates/migration/MigrationView_tmpl.html deleted file mode 100644 index 67572fad08d..00000000000 --- a/dashboardv2/public/js/templates/migration/MigrationView_tmpl.html +++ /dev/null @@ -1,17 +0,0 @@ - -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/profile/ProfileColumnLayoutView_tmpl.html b/dashboardv2/public/js/templates/profile/ProfileColumnLayoutView_tmpl.html deleted file mode 100644 index c907cf0b3ab..00000000000 --- a/dashboardv2/public/js/templates/profile/ProfileColumnLayoutView_tmpl.html +++ /dev/null @@ -1,96 +0,0 @@ - -
      -
      -
      -
      Rows
      -
      -
      -
      -
      -
      -
      Date Created
      -
      -
      -
      -
      -
      -
      Table
      -
      -
      -
      -
      -
      -
      -
      -
      -

      {{typeObject.label}}

      -
      - -
      -
      -
      -
      - -
      -
      - {{#if profileData}} -
      -
      Cardinality
      -
      {{profileData.cardinality}}
      -
      -
      -
      -
      % NonNull
      -
      {{profileData.nonNullData}}%
      -
      -
      {{#ifCond typeObject.type "==" "string"}} -
      -
      Average Length
      -
      {{profileData.averageLength}}
      -
      -
      -
      -
      Max Length
      -
      {{profileData.maxLength}}
      -
      -
      {{/ifCond}} {{#ifCond typeObject.type "==" "numeric"}} -
      -
      Min
      -
      {{profileData.minValue}}
      -
      -
      -
      -
      Max
      -
      {{profileData.maxValue}}
      -
      -
      -
      -
      Mean
      -
      {{profileData.meanValue}}
      -
      -
      -
      -
      Median
      -
      {{profileData.medianValue}}
      -
      - {{/ifCond}} {{/if}} -
      -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/profile/ProfileLayoutView_tmpl.html b/dashboardv2/public/js/templates/profile/ProfileLayoutView_tmpl.html deleted file mode 100644 index 96adc9bcd78..00000000000 --- a/dashboardv2/public/js/templates/profile/ProfileLayoutView_tmpl.html +++ /dev/null @@ -1,24 +0,0 @@ - -
      - {{#if profileData}} -
      - -
      {{else}} {{#ifCond typeName "==" "hive_db"}} -

      No Tables to Show!

      {{else}} -

      No Profile to Show!

      {{/ifCond}} {{/if}} -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/profile/ProfileTableLayoutView_tmpl.html b/dashboardv2/public/js/templates/profile/ProfileTableLayoutView_tmpl.html deleted file mode 100644 index 033a2253a62..00000000000 --- a/dashboardv2/public/js/templates/profile/ProfileTableLayoutView_tmpl.html +++ /dev/null @@ -1,48 +0,0 @@ - -
      -
      -
      -
      Rows
      -
      -
      -
      -
      -
      -
      Date Created
      -
      -
      -
      -
      -
      -
      Table
      -
      -
      -
      -
      -
      -
      DB
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/schema/SchemaTableLayoutView_tmpl.html b/dashboardv2/public/js/templates/schema/SchemaTableLayoutView_tmpl.html deleted file mode 100644 index d77544f500b..00000000000 --- a/dashboardv2/public/js/templates/schema/SchemaTableLayoutView_tmpl.html +++ /dev/null @@ -1,30 +0,0 @@ - -
      -
      -
      - -
      - -
      -
      -
      -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/search/AdvancedSearchInfo_tmpl.html b/dashboardv2/public/js/templates/search/AdvancedSearchInfo_tmpl.html deleted file mode 100644 index 64f1a31d41f..00000000000 --- a/dashboardv2/public/js/templates/search/AdvancedSearchInfo_tmpl.html +++ /dev/null @@ -1,36 +0,0 @@ - -
      -

      Use DSL (Domain Specific Language) to build queries

      -
        -
      • Single Query -

        DB where name="Reporting" select name, owner

        -
      • -
      • GROUPBY -

        select count(CustomerID), Country from Customers group by Country

        -
      • -
      • ORDERBY -

        DB where name="Reporting" select name, owner orderby name limit 10 offset 5

        -
      • -
      • LIMIT -

        DB where name="Reporting" select name, owner limit 10 offset 0

        -
      • -
      -
      -   More sample queries and use-cases -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/search/QueryBuilder_tmpl.html b/dashboardv2/public/js/templates/search/QueryBuilder_tmpl.html deleted file mode 100644 index 39f6e5431de..00000000000 --- a/dashboardv2/public/js/templates/search/QueryBuilder_tmpl.html +++ /dev/null @@ -1,17 +0,0 @@ - -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/search/SearchDetailLayoutView_tmpl.html b/dashboardv2/public/js/templates/search/SearchDetailLayoutView_tmpl.html deleted file mode 100644 index 289830cb675..00000000000 --- a/dashboardv2/public/js/templates/search/SearchDetailLayoutView_tmpl.html +++ /dev/null @@ -1,23 +0,0 @@ - -
      -
      -
      -
      -
      -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html b/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html deleted file mode 100644 index 3bc3121f497..00000000000 --- a/dashboardv2/public/js/templates/search/SearchLayoutView_tmpl.html +++ /dev/null @@ -1,81 +0,0 @@ - -
      -
      -
      -
      - Basic - - Advanced - -
      -
      - -
      -
      -
      -
      -
      -
      - Search By Type -
      -
      - -
      -
      - -
      -
      -
      -
      - Search By Classification -
      -
      - -
      -
      - -
      -
      -
      -
      - Search By Term -
      -
      - -
      -
      -
      -
      - Search By Text - -
      -
      - - -
      -
      -
      -
      -
      -
      - -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/search/SearchQuery_tmpl.html b/dashboardv2/public/js/templates/search/SearchQuery_tmpl.html deleted file mode 100644 index ced907f4fbe..00000000000 --- a/dashboardv2/public/js/templates/search/SearchQuery_tmpl.html +++ /dev/null @@ -1,21 +0,0 @@ - -
      -
      - -
      -
      diff --git a/dashboardv2/public/js/templates/search/SearchResultLayoutView_tmpl.html b/dashboardv2/public/js/templates/search/SearchResultLayoutView_tmpl.html deleted file mode 100644 index 9b71d28e1a2..00000000000 --- a/dashboardv2/public/js/templates/search/SearchResultLayoutView_tmpl.html +++ /dev/null @@ -1,130 +0,0 @@ - -
      -
      - -
      - -
      - -
      - -
      - -
      - {{#if isSearchTab}}

      {{searchType}}

      {{/if}} - -
      - -
      -
      -
      - \ No newline at end of file diff --git a/dashboardv2/public/js/templates/search/UserDefine_tmpl.html b/dashboardv2/public/js/templates/search/UserDefine_tmpl.html deleted file mode 100644 index 756ea8c8108..00000000000 --- a/dashboardv2/public/js/templates/search/UserDefine_tmpl.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - -
      - -

      -
      : - -

      -
      -

      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/search/save/SaveModalLayoutView_tmpl.html b/dashboardv2/public/js/templates/search/save/SaveModalLayoutView_tmpl.html deleted file mode 100644 index 7b199bd8481..00000000000 --- a/dashboardv2/public/js/templates/search/save/SaveModalLayoutView_tmpl.html +++ /dev/null @@ -1,24 +0,0 @@ - -
      -
      - -
      - -
      -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/search/save/SaveSearchItemView_tmpl.html b/dashboardv2/public/js/templates/search/save/SaveSearchItemView_tmpl.html deleted file mode 100644 index 28fa73366c8..00000000000 --- a/dashboardv2/public/js/templates/search/save/SaveSearchItemView_tmpl.html +++ /dev/null @@ -1,22 +0,0 @@ - -
      -
      - -
      - {{name}} -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/search/save/SaveSearchView_tmpl.html b/dashboardv2/public/js/templates/search/save/SaveSearchView_tmpl.html deleted file mode 100644 index fe6fc79ed3e..00000000000 --- a/dashboardv2/public/js/templates/search/save/SaveSearchView_tmpl.html +++ /dev/null @@ -1,31 +0,0 @@ - -
      -
      - Favorite Searches -
      - - -
      -
      -
      -You don't have any favorite search. -
        -
        - -
        -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/site/AboutAtlas_tmpl.html b/dashboardv2/public/js/templates/site/AboutAtlas_tmpl.html deleted file mode 100644 index 6581e77d545..00000000000 --- a/dashboardv2/public/js/templates/site/AboutAtlas_tmpl.html +++ /dev/null @@ -1,26 +0,0 @@ - -
      -
      - -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/site/DebugMetricsTableLayoutView_tmpl.html b/dashboardv2/public/js/templates/site/DebugMetricsTableLayoutView_tmpl.html deleted file mode 100644 index 8b543680a2a..00000000000 --- a/dashboardv2/public/js/templates/site/DebugMetricsTableLayoutView_tmpl.html +++ /dev/null @@ -1,29 +0,0 @@ - -
      -
      - - -
      -
      -
      -
      -
      -
      -
      -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/site/Header.html b/dashboardv2/public/js/templates/site/Header.html deleted file mode 100644 index 572e39e7804..00000000000 --- a/dashboardv2/public/js/templates/site/Header.html +++ /dev/null @@ -1,85 +0,0 @@ - -
      - - - - - - -
      - - - - - - - - - -
      - - -
      -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/site/MetricsUIInfoView_tmpl.html b/dashboardv2/public/js/templates/site/MetricsUIInfoView_tmpl.html deleted file mode 100644 index 837c3b5bf9c..00000000000 --- a/dashboardv2/public/js/templates/site/MetricsUIInfoView_tmpl.html +++ /dev/null @@ -1,33 +0,0 @@ - -
      -

      Debug Metrics Information

      -
        -
      • Count -

        Number of times the API has been hit since Atlas started

        -
      • -
      • Min Time (secs) -

        Minimum API execution time since Atlas started

        -
      • -
      • Max Time (secs) -

        Maximum API execution time since Atlas started

        -
      • -
      • Average Time (secs) -

        Average time taken to execute by an API within an interval of time

        -
      • -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/site/SideNavLayoutView_tmpl.html b/dashboardv2/public/js/templates/site/SideNavLayoutView_tmpl.html deleted file mode 100644 index 9e72c678a86..00000000000 --- a/dashboardv2/public/js/templates/site/SideNavLayoutView_tmpl.html +++ /dev/null @@ -1,37 +0,0 @@ - - -
      -
      -
      -
      - -
      -
      -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/site/Statistics_Notification_table_tmpl.html b/dashboardv2/public/js/templates/site/Statistics_Notification_table_tmpl.html deleted file mode 100644 index dc5a191a01f..00000000000 --- a/dashboardv2/public/js/templates/site/Statistics_Notification_table_tmpl.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - Period - Count - Avg Time (ms) - Creates - Updates - Deletes - Failed - - -{{#if data}} - - {{#each tableCol}} - - {{{this.label}}} - {{#each ../tableHeader}} - {{callmyfunction ../../getTmplValue ../this this}} - {{/each }} - - {{/each}} - -{{/if}} \ No newline at end of file diff --git a/dashboardv2/public/js/templates/site/Statistics_Topic_Offset_table_tmpl.html b/dashboardv2/public/js/templates/site/Statistics_Topic_Offset_table_tmpl.html deleted file mode 100644 index b4c8d8677fb..00000000000 --- a/dashboardv2/public/js/templates/site/Statistics_Topic_Offset_table_tmpl.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - Kafka Topic-Partition - Start Offset - Current Offset - Processed - Failed - Last Message Processed Time - - -{{#if data}} - - {{#each tableCol}} - - {{{this.label}}} - {{#each ../tableHeader}} - {{callmyfunction ../../getTmplValue ../this this}} - {{/each }} - - {{/each}} - -{{/if}} \ No newline at end of file diff --git a/dashboardv2/public/js/templates/site/Statistics_tmpl.html b/dashboardv2/public/js/templates/site/Statistics_tmpl.html deleted file mode 100644 index 646e37fe7c8..00000000000 --- a/dashboardv2/public/js/templates/site/Statistics_tmpl.html +++ /dev/null @@ -1,187 +0,0 @@ - -
      -
      -
      - -
      -
      -
      Migration is successful. To exit form migration mode, please remove atlas.migration.data.filename property and restart Atlas.
      -
      - -
      -
      -
      -
      -
      -

      - Entities (0) -

      -
      - -
      -
      -
      -
      - - - - - - -
      No records found!
      -
      -
      -
      -
      -
      -

      - Classifications (0) -

      -
      - -
      -
      -
      -
      - - - - - - - - - - - - -
      NameCount (0)
      No records found!
      -
      -
      -
      -
      -
      -

      - Server Statistics -

      -
      - -
      -
      -
      -
      -
      -
      -
      Server Details
      -
      - - - - - - -
      No records found!
      -
      -
      -
      -
      -
      -
      Notification Details
      -
      - - - - - - -
      No records found!
      -
      - - - - - - - -
      No records found!
      -
      -
      -
      -
      -
      -
      -
      - -
      -
      -
      -
      -
      OS
      -
      - - - - - - -
      No records found!
      -
      -
      -
      -
      -
      -
      Runtime
      -
      - - - - - - -
      No records found!
      -
      -
      -
      -
      -
      -
      Memory
      -
      - - - - - - -
      No records found!
      -
      -
      -
      -
      -
      -
      -
      -
      - -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/site/entity_tmpl.html b/dashboardv2/public/js/templates/site/entity_tmpl.html deleted file mode 100644 index ec88fd162a4..00000000000 --- a/dashboardv2/public/js/templates/site/entity_tmpl.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - Entity Type - Active - Deleted - Shell - - -{{#if data}} - - {{#each data}} - - {{@key}} ({{arithmetic this.active '+' this.deleted}}) - {{#if this.active}} - - {{this.active}} - - {{else}} - 0 - {{/if}} - {{#if this.deleted}} - - {{this.deleted}} - - {{else}} - 0 - {{/if}} - {{#if this.shell}} - - {{this.shell}} - - {{else}} - 0 - {{/if}} - - {{/each}} - -{{/if}} \ No newline at end of file diff --git a/dashboardv2/public/js/templates/tag/AddTagAttributeView_tmpl.html b/dashboardv2/public/js/templates/tag/AddTagAttributeView_tmpl.html deleted file mode 100644 index 0454a70defb..00000000000 --- a/dashboardv2/public/js/templates/tag/AddTagAttributeView_tmpl.html +++ /dev/null @@ -1,28 +0,0 @@ - -
      - -
      -
      -
      -
      - -
      -
      -
      -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/tag/AddTagModalView_tmpl.html b/dashboardv2/public/js/templates/tag/AddTagModalView_tmpl.html deleted file mode 100644 index 977149ea7cf..00000000000 --- a/dashboardv2/public/js/templates/tag/AddTagModalView_tmpl.html +++ /dev/null @@ -1,72 +0,0 @@ - -
      -
      -
      -
      - {{#if tagModel}} -

      {{tagModel.typeName}}

      -
      {{else}} - -
      - {{/if}} -
      -
      -
      - -
      -
      - -
      -
      -
      -
      -
      - -
      -
      -
      - -
      -
      -
      - -
      - -
      - \ No newline at end of file diff --git a/dashboardv2/public/js/templates/tag/AddTimezoneView_tmpl.html b/dashboardv2/public/js/templates/tag/AddTimezoneView_tmpl.html deleted file mode 100644 index 08667ef90b4..00000000000 --- a/dashboardv2/public/js/templates/tag/AddTimezoneView_tmpl.html +++ /dev/null @@ -1,34 +0,0 @@ - -
      -
      - - -
      -
      - - -
      -
      - - -
      -
      - -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/tag/CreateTagLayoutView_tmpl.html b/dashboardv2/public/js/templates/tag/CreateTagLayoutView_tmpl.html deleted file mode 100644 index 27ea9124799..00000000000 --- a/dashboardv2/public/js/templates/tag/CreateTagLayoutView_tmpl.html +++ /dev/null @@ -1,54 +0,0 @@ - -
      - -
      -
      -
      - - {{#if create}} -
      - -
      - {{else}} - {{/if}} -
      -
      - -
      - -
      -
      - {{#if create}} -
      -
      - -

      Attributes define additional properties for the classification

      - -
      -
      -
      - -
      - -
      -
      - {{/if}} -
      -
      - -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/tag/TagAttributeDetailLayoutView_tmpl.html b/dashboardv2/public/js/templates/tag/TagAttributeDetailLayoutView_tmpl.html deleted file mode 100644 index d12785bd832..00000000000 --- a/dashboardv2/public/js/templates/tag/TagAttributeDetailLayoutView_tmpl.html +++ /dev/null @@ -1,49 +0,0 @@ - -
      -
      - -
      -
      -

      - -

      - - - -
      - -
      -
      -
      - -
      -
      -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/tag/TagAttributeItemView_tmpl.html b/dashboardv2/public/js/templates/tag/TagAttributeItemView_tmpl.html deleted file mode 100644 index 0212e8a4ce6..00000000000 --- a/dashboardv2/public/js/templates/tag/TagAttributeItemView_tmpl.html +++ /dev/null @@ -1,37 +0,0 @@ - -
      -
      - - -
      -
      - -
      -
      - -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/tag/TagDetailLayoutView_tmpl.html b/dashboardv2/public/js/templates/tag/TagDetailLayoutView_tmpl.html deleted file mode 100644 index 80696d984b2..00000000000 --- a/dashboardv2/public/js/templates/tag/TagDetailLayoutView_tmpl.html +++ /dev/null @@ -1,25 +0,0 @@ - -
      -
      -
      -
      -
      -
      -
      -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/tag/TagDetailTableLayoutView_tmpl.html b/dashboardv2/public/js/templates/tag/TagDetailTableLayoutView_tmpl.html deleted file mode 100644 index c161a2ce0ed..00000000000 --- a/dashboardv2/public/js/templates/tag/TagDetailTableLayoutView_tmpl.html +++ /dev/null @@ -1,27 +0,0 @@ - -
      -
      -
      -
      - -
      -
      -
      -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/templates/tag/TagLayoutView_tmpl.html b/dashboardv2/public/js/templates/tag/TagLayoutView_tmpl.html deleted file mode 100644 index b6135c84f25..00000000000 --- a/dashboardv2/public/js/templates/tag/TagLayoutView_tmpl.html +++ /dev/null @@ -1,54 +0,0 @@ - -
      -
      -
      - Flat - - Tree -
      -
      - - -
      -
      -
      -
      -
      - -
      -
      -
      - -
        -
      -
      - -
      -
      - Loading Classifications -
      -
      \ No newline at end of file diff --git a/dashboardv2/public/js/utils/CommonViewFunction.js b/dashboardv2/public/js/utils/CommonViewFunction.js deleted file mode 100644 index f7400c230b8..00000000000 --- a/dashboardv2/public/js/utils/CommonViewFunction.js +++ /dev/null @@ -1,1045 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', 'utils/Utils', 'modules/Modal', 'utils/Messages', 'utils/Enums', 'moment', 'utils/Globals', 'moment-timezone'], function(require, Utils, Modal, Messages, Enums, moment, Globals) { - 'use strict'; - - var CommonViewFunction = {}; - CommonViewFunction.deleteTag = function(options) { - require(['models/VTag'], function(VTag) { - if (options && options.guid && options.tagName) { - var tagModel = new VTag(), - noticeRef = null, - notifyObj = { - modal: true, - okCloses: false, - okShowLoader: true, - text: options.msg, - title: options.titleMessage, - okText: options.okText, - ok: function(notice) { - noticeRef = notice; - if (options.showLoader) { - options.showLoader(); - } - tagModel.deleteAssociation(options.guid, options.tagName, options.associatedGuid, { - defaultErrorMessage: options.tagName + Messages.deleteErrorMessage, - success: function(data) { - if (noticeRef) { - noticeRef.remove(); - } - Utils.notifySuccess({ - content: "Classification " + options.tagName + Messages.getAbbreviationMsg(false, 'removeSuccessMessage') - }); - if (options.callback) { - options.callback(); - } - if (options.collection) { - options.collection.fetch({ reset: true }); - } - - }, - cust_error: function(model, response) { - if (noticeRef) { - noticeRef.hideButtonLoader(); - } - if (options.hideLoader) { - options.hideLoader(); - } - } - }); - }, - cancel: function(argument) { - if (options.hideLoader) { - options.hideLoader(); - } - } - }; - Utils.notifyConfirm(notifyObj); - } - }); - }; - CommonViewFunction.propertyTable = function(options) { - var scope = options.scope, - sortBy = options.sortBy, - valueObject = options.valueObject, - extractJSON = options.extractJSON, - getArrayOfStringElement = options.getArrayOfStringElement, - getArrayOfStringFormat = options.getArrayOfStringFormat, - isTable = _.isUndefined(options.isTable) ? true : options.isTable, - attributeDefs = options.attributeDefs, - formatIntVal = options.formatIntVal, - showListCount = options.showListCount || true, - highlightString = options.highlightString, - formatStringVal = options.formatStringVal, - numberFormat = options.numberFormat || _.numberFormatWithComma; - - var table = "", - getHighlightedString = function(resultStr) { - if (highlightString && highlightString.length) { - try { - return resultStr.replace(new RegExp(highlightString, "gi"), function(foundStr) { - return "" + foundStr + "" - }); - } catch (error) { - return resultStr; - } - } else { - return resultStr; - } - }, - getEmptyString = function(key) { - if (options.getEmptyString) { - return options.getEmptyString(key); - } - return "N/A"; - }, - getValue = function(val, key) { - if (options && options.getValue) { - val = options.getValue(val, key); - } - if (!_.isUndefined(val) && !_.isNull(val)) { - if ((_.isNumber(val) || !_.isNaN(parseInt(val))) && formatIntVal) { - return numberFormat(val); - } else { - var newVal = val; - if (formatStringVal) { - newVal = parseInt(val); - if (_.isNaN(newVal)) { - newVal = val; - } else { - newVal = numberFormat(newVal); - } - } - return getHighlightedString(_.escape(newVal)); - } - } else { - return getEmptyString(key); - } - }, - fetchInputOutputValue = function(id, defEntity) { - var that = this; - scope.entityModel.getEntityHeader(id, { - success: function(serverData) { - var value = "", - deleteButton = "", - data = serverData; - value = Utils.getName(data); - var id = ""; - if (data.guid) { - if (Enums.entityStateReadOnly[data.status || data.entityStatus]) { - deleteButton += ''; - } - id = data.guid; - } - if (value.length > 0) { - scope.$('td div[data-id="' + id + '"]').html('' + getValue(value) + ''); - } else { - scope.$('td div[data-id="' + id + '"]').html('' + _.escape(id) + ''); - } - if (deleteButton.length) { - scope.$('td div[data-id="' + id + '"]').addClass('block readOnlyLink'); - scope.$('td div[data-id="' + id + '"]').append(deleteButton); - } - }, - cust_error: function(error, xhr) { - if (xhr.status == 403) { - scope.$('td div[data-id="' + id + '"]').html('
      Not Authorized
      '); - } else if (defEntity && defEntity.options && defEntity.options.isSoftReference === "true") { - scope.$('td div[data-id="' + id + '"]').html('
      ' + id + '
      '); - } else { - scope.$('td div[data-id="' + id + '"]').html('
      ' + Messages.defaultErrorMessage + '
      '); - } - }, - complete: function() {} - }); - }, - extractObject = function(opt) { - var valueOfArray = [], - keyValue = opt.keyValue, - key = opt.key, - defEntity = opt.defEntity; - if (!_.isArray(keyValue) && _.isObject(keyValue)) { - keyValue = [keyValue]; - } - var subLink = ""; - for (var i = 0; i < keyValue.length; i++) { - var inputOutputField = keyValue[i], - id = inputOutputField.guid || (_.isObject(inputOutputField.id) ? inputOutputField.id.id : inputOutputField.id), - tempLink = "", - status = (inputOutputField.status || inputOutputField.entityStatus) || (_.isObject(inputOutputField.id) ? inputOutputField.id.state : inputOutputField.state), - readOnly = Enums.entityStateReadOnly[status]; - if (!inputOutputField.attributes && inputOutputField.values) { - inputOutputField['attributes'] = inputOutputField.values; - } - if (_.isString(inputOutputField) || _.isBoolean(inputOutputField) || _.isNumber(inputOutputField)) { - var tempVarfor$check = inputOutputField.toString(); - if (tempVarfor$check.indexOf("$") == -1) { - var tmpVal = getValue(inputOutputField, key) - if (getArrayOfStringElement) { - valueOfArray.push(getArrayOfStringElement(tmpVal, key)); - } else { - valueOfArray.push('' + tmpVal + ''); - } - } - } else if (_.isObject(inputOutputField) && !id) { - var attributesList = inputOutputField; - if (scope.typeHeaders && inputOutputField.typeName) { - var typeNameCategory = scope.typeHeaders.fullCollection.findWhere({ name: inputOutputField.typeName }); - if (attributesList.attributes && typeNameCategory && typeNameCategory.get('category') === 'STRUCT') { - attributesList = attributesList.attributes; - } - } - - if (extractJSON && extractJSON.extractKey) { - var newAttributesList = {}; - _.each(attributesList, function(objValue, objKey) { - var value = _.isObject(objValue) ? objValue : _.escape(objValue), - tempVarfor$check = objKey.toString(); - if (tempVarfor$check.indexOf("$") == -1) { - if (_.isObject(extractJSON.extractKey)) { - _.each(extractJSON.extractKey, function(extractKey) { - if (objKey === extractKey) { - newAttributesList[_.escape(objKey)] = value; - } - }); - } else if (_.isString(extractJSON.extractKey) && extractJSON.extractKey === objKey) { - newAttributesList[_.escape(objKey)] = value; - } - } - }); - valueOfArray.push(Utils.JSONPrettyPrint(newAttributesList, getValue)); - } else { - valueOfArray.push(Utils.JSONPrettyPrint(attributesList, getValue)); - } - } - if (id && inputOutputField) { - var name = Utils.getName(inputOutputField); - if ((name === "-" || name === id) && !inputOutputField.attributes) { - var fetch = true; - var fetchId = (_.isObject(id) ? id.id : id); - fetchInputOutputValue(fetchId, defEntity); - tempLink += '
      '; - } else { - if (inputOutputField.typeName == "AtlasGlossaryTerm") { - tempLink += '' + name + '' - } else { - tempLink += '' + name + '' - } - } - } - if (readOnly) { - if (!fetch) { - tempLink += ''; - subLink += ''; - } else { - fetch = false; - subLink += tempLink; - } - - } else { - if (tempLink.search('href') != -1) { - subLink += '
      ' + tempLink + '
      ' - } else if (tempLink.length) { - subLink += tempLink - } - } - } - if (valueOfArray.length) { - if (getArrayOfStringFormat) { - subLink = getArrayOfStringFormat(valueOfArray, key); - } else { - subLink = valueOfArray.join(', '); - } - } - return subLink === "" ? getEmptyString(key) : subLink; - } - var valueObjectKeysList = _.keys(_.omit(valueObject, ['paramsCount'])); - if (_.isUndefined(sortBy) || sortBy == true) { - valueObjectKeysList = _.sortBy(valueObjectKeysList); - } - valueObjectKeysList.map(function(key) { - if (key == "profileData") { - return; - } - var keyValue = valueObject[key], - listCount = ""; - if (key == "isIncomplete" && keyValue == false) { - return; - } - if (showListCount && _.isArray(keyValue) && keyValue.length > 0) { - listCount = (valueObject && valueObject.paramsCount != undefined) ? (numberFormat(valueObject.paramsCount) != 0) ? ' (' + numberFormat(valueObject.paramsCount) + ')' : '' : ' (' + numberFormat(keyValue.length) + ')'; - } - var defEntity = _.find(attributeDefs, { name: key }); - if (defEntity && defEntity.typeName) { - var defEntityType = defEntity.typeName.toLocaleLowerCase(); - if (defEntityType === 'date') { - keyValue = keyValue > 0 ? Utils.formatDate({ date: keyValue }) : null; - } else if (_.isObject(keyValue)) { - keyValue = extractObject({ "keyValue": keyValue, "key": key, 'defEntity': defEntity }); - } - } else { - if (_.isObject(keyValue)) { - keyValue = extractObject({ "keyValue": keyValue, "key": key }); - } - } - var val = ""; - if (_.isObject(valueObject[key])) { - val = keyValue - } else if (key === 'guid' || key === "__guid") { - if (options.guidHyperLink === false) { - val = getValue(keyValue, key); - } else { - val = '' + getValue(keyValue, key) + ''; - } - } else { - val = getValue(keyValue, key); - } - if (isTable) { - var value = val, - appendClass = (value == "N/A" ? "hide-row" : ""), - htmlTag = '
      ' + value + '
      '; - if (_.isObject(valueObject[key]) && !_.isEmpty(valueObject[key])) { - var matchedLinkString = val.match(/href|value-loader\w*/g), - matchedJson = val.match(/json-value|json-string\w*/g), - matchedKey = val.match(/json-key\w*/g), - isMatchLinkStringIsSingle = matchedLinkString && matchedLinkString.length <= 5, - isMatchJSONStringIsSingle = matchedJson && matchedJson.length == 1, - expandCollapseButton = ""; - if ((matchedJson) || (matchedLinkString)) { - var className = "code-block fixed-height"; - if (!isMatchJSONStringIsSingle) { - className += " shrink"; - expandCollapseButton = ''; - } - htmlTag = '
      ' + expandCollapseButton + '' + val + '
      '; - } - } - table += '' + (_.escape(key) + listCount) + '' + htmlTag + ''; - } else { - table += '' + val + ''; - } - - }); - return table && table.length > 0 ? table : 'No Record found!'; - } - CommonViewFunction.tagForTable = function(obj) { - var traits = obj.classifications, - tagHtml = "", - addTag = "", - popTag = "", - count = 0, - entityName = Utils.getName(obj); - if (traits) { - traits.map(function(tag) { - var className = "btn btn-action btn-sm btn-blue btn-icon", - deleteIcon = ""; - if (obj.guid === tag.entityGuid) { - deleteIcon = ''; - } else if (obj.guid !== tag.entityGuid && tag.entityStatus === "DELETED") { - deleteIcon = ''; - } else { - className += " propagte-classification"; - } - var tagString = '' + tag.typeName + '' + deleteIcon + ''; - if (count >= 1) { - popTag += tagString; - } else { - tagHtml += tagString; - } - ++count; - }); - } - if (!Enums.entityStateReadOnly[obj.status || obj.entityStatus]) { - if (obj.guid) { - addTag += ''; - } else { - addTag += ''; - } - } - if (count > 1) { - addTag += '
      ' - } - return '
      ' + tagHtml + addTag + '
      '; - } - CommonViewFunction.termForTable = function(obj) { - var terms = obj.meanings, - termHtml = "", - addTerm = "", - popTerm = "", - count = 0, - entityName = Utils.getName(obj); - if (terms) { - terms.map(function(term) { - var displayText = _.escape(term.displayText); - var className = "btn btn-action btn-sm btn-blue btn-icon", - deleteIcon = '', - termString = '' + displayText + '' + deleteIcon + ''; - if (count >= 1) { - popTerm += termString; - } else { - termHtml += termString; - } - ++count; - }); - } - if (!Enums.entityStateReadOnly[obj.status || obj.entityStatus]) { - if (obj.guid) { - addTerm += ''; - } else { - addTerm += ''; - } - } - if (count > 1) { - addTerm += '
      ' - } - return '
      ' + termHtml + addTerm + '
      '; - } - CommonViewFunction.generateQueryOfFilter = function(value) { - value = Utils.getUrlState.getQueryParams(); - var entityFilters = CommonViewFunction.attributeFilter.extractUrl({ "value": value.entityFilters, "formatDate": true }), - tagFilters = CommonViewFunction.attributeFilter.extractUrl({ "value": value.tagFilters, "formatDate": true }), - queryArray = []; - - function objToString(filterObj) { - var generatedQuery = _.map(filterObj.rules, function(obj, key) { - var obj = $.extend(true, {}, obj); // not to update the timezone abbr on original obj , copy of obj is used - if (_.has(obj, 'condition')) { - return ' ' + obj.condition + ' ' + '(' + objToString(obj) + ')'; - } else { - if (obj.type === "date") { - if (Enums.queryBuilderDateRangeUIValueToAPI[obj.value]) { - obj.value = Enums.queryBuilderDateRangeUIValueToAPI[obj.value]; - } else { - obj.value = obj.value + " (" + moment.tz(moment.tz.guess()).zoneAbbr() + ")"; - } - } - return '' + (Enums.systemAttributes[obj.id] ? Enums.systemAttributes[obj.id] : _.escape(obj.id)) + ' ' + _.escape(obj.operator) + ' ' + (Enums[obj.id] ? Enums[obj.id][obj.value] : _.escape(obj.value)) + ""; - } - }); - return generatedQuery; - } - if (value.type) { - var typeKeyValue = 'Type: ' + _.escape(value.type) + ''; - if (entityFilters) { - var conditionForEntity = entityFilters.rules.length == 1 ? '' : 'AND'; - typeKeyValue += ' ' + conditionForEntity + ' (' + entityFilters.condition + ' (' + objToString(entityFilters) + '))'; - } - queryArray.push(typeKeyValue) - } - if (value.tag) { - var tagKeyValue = 'Classification: ' + _.escape(value.tag) + ''; - if (tagFilters) { - var conditionFortag = tagFilters.rules.length == 1 ? '' : 'AND'; - tagKeyValue += ' ' + conditionFortag + ' (' + tagFilters.condition + ' (' + objToString(tagFilters) + '))'; - } - queryArray.push(tagKeyValue); - } - if (value.term) { - var tagKeyValue = 'Term: ' + _.escape(value.term) + ''; - queryArray.push(tagKeyValue); - } - if (value.query) { - queryArray.push('Query: ' + _.trim(_.escape(value.query)) + ' '); - } - if (queryArray.length == 1) { - return queryArray.join(); - } else { - return "( " + queryArray.join(' ) AND ( ') + " )"; - - } - } - CommonViewFunction.generateObjectForSaveSearchApi = function(options) { - var obj = { - name: options.name, - guid: options.guid - }; - var value = options.value; - if (value) { - _.each(Enums.extractFromUrlForSearch, function(svalue, skey) { - if (_.isObject(svalue)) { - _.each(svalue, function(v, k) { - var val = value[k]; - if (!_.isUndefinedNull(val)) { - if (k == "attributes") { - val = val.split(','); - } else if (_.contains(["tagFilters", "entityFilters"], k)) { - val = CommonViewFunction.attributeFilter.generateAPIObj(val); - } else if (_.contains(["includeDE", "excludeST", "excludeSC"], k)) { - val = val ? false : true; - } - } - if (_.contains(["includeDE", "excludeST", "excludeSC"], k)) { - val = _.isUndefinedNull(val) ? true : val; - } - if (!obj[skey]) { - obj[skey] = {}; - } - obj[skey][v] = val; - }); - } else { - obj[skey] = value[skey]; - } - }); - return obj; - } - } - CommonViewFunction.generateUrlFromSaveSearchObject = function(options) { - var value = options.value, - classificationDefCollection = options.classificationDefCollection, - entityDefCollection = options.entityDefCollection, - obj = {}; - if (value) { - _.each(Enums.extractFromUrlForSearch, function(svalue, skey) { - if (_.isObject(svalue)) { - _.each(svalue, function(v, k) { - var val = value[skey][v]; - if (!_.isUndefinedNull(val)) { - if (k == "attributes") { - val = val.join(','); - } else if (k == "tagFilters") { - if (classificationDefCollection) { - var classificationDef = classificationDefCollection.fullCollection.findWhere({ 'name': value[skey].classification }), - attributeDefs = []; - if (classificationDef) { - attributeDefs = Utils.getNestedSuperTypeObj({ - collection: classificationDefCollection, - attrMerge: true, - data: classificationDef.toJSON() - }); - } - if (Globals[value[skey].typeName]) { - attributeDefs = Globals[value[skey].typeName].attributeDefs; - } - if (Globals._ALL_CLASSIFICATION_TYPES && Globals._ALL_CLASSIFICATION_TYPES.attributeDefs) { - attributeDefs = attributeDefs.concat(Globals._ALL_CLASSIFICATION_TYPES.attributeDefs); - } - } - val = CommonViewFunction.attributeFilter.generateUrl({ "value": val, "attributeDefs": attributeDefs }); - } else if (k == "entityFilters") { - if (entityDefCollection) { - var entityDef = entityDefCollection.fullCollection.findWhere({ 'name': value[skey].typeName }), - attributeDefs = []; - if (entityDef) { - attributeDefs = Utils.getNestedSuperTypeObj({ - collection: entityDefCollection, - attrMerge: true, - data: entityDef.toJSON() - }); - } - if (Globals[value[skey].typeName]) { - attributeDefs = Globals[value[skey].typeName].attributeDefs; - } - if (Globals._ALL_ENTITY_TYPES && Globals._ALL_ENTITY_TYPES.attributeDefs) { - attributeDefs = attributeDefs.concat(Globals._ALL_ENTITY_TYPES.attributeDefs); - } - } - val = CommonViewFunction.attributeFilter.generateUrl({ "value": val, "attributeDefs": attributeDefs }); - } else if (_.contains(["includeDE", "excludeST", "excludeSC"], k)) { - val = val ? false : true; - } - } - obj[k] = val; - }); - } else { - obj[skey] = value[skey]; - } - }); - return obj; - } - } - CommonViewFunction.attributeFilter = { - generateUrl: function(options) { - var attrQuery = [], - attrObj = options.value, - formatedDateToLong = options.formatedDateToLong, - attributeDefs = options.attributeDefs, - /* set attributeType for criterion while creating object*/ - spliter = 1; - attrQuery = conditionalURl(attrObj, spliter); - - function conditionalURl(options, spliter) { - if (options) { - return _.map(options.rules || options.criterion, function(obj, key) { - if (_.has(obj, 'condition')) { - return obj.condition + '(' + conditionalURl(obj, (spliter + 1)) + ')'; - } - if (attributeDefs) { - var attributeDef = _.findWhere(attributeDefs, { 'name': obj.attributeName }); - if (attributeDef) { - obj.attributeValue = obj.attributeValue; - obj['attributeType'] = attributeDef.typeName; - } - } - var type = (obj.type || obj.attributeType), - //obj.value will come as an object when selected type is Date and operator is isNull or not_null; - value = ((_.isString(obj.value) && _.contains(["is_null", "not_null"], obj.operator) && type === 'date') || _.isObject(obj.value) ? "" : _.trim(obj.value || obj.attributeValue)), - url = [(obj.id || obj.attributeName), mapApiOperatorToUI(obj.operator), value]; - if (obj.operator === "TIME_RANGE") { - if (value.indexOf("-") > -1) { - url[2] = value.split('-').map(function(udKey) { - return Date.parse(udKey.trim()).toString() - }).join(",") - } else { - url[2] = Enums.queryBuilderDateRangeUIValueToAPI[_.trim(value)] || value; - } - } else if (value.length && type === 'date' && formatedDateToLong) { - url[2] = Date.parse(value); - } - if (type) { - url.push(type); - } - return url.join("::"); - }).join('|' + spliter + '|') - } else { - return null; - } - } - if (attrQuery.length) { - return attrObj.condition + '(' + attrQuery + ')'; - } else { - return null; - } - - function mapApiOperatorToUI(oper) { - // Enum will be in effect once we click on save search. - return Enums.queryBuilderApiOperatorToUI[oper] || oper; - } - }, - extractUrl: function(options) { - var attrObj = {}, - urlObj = options.value, - formatDate = options.formatDate, - spliter = 1, - apiObj = options.apiObj, - mapUiOperatorToAPI = function(oper) { - return Enums.queryBuilderUIOperatorToAPI[oper] || oper; - }, - createObject = function(urlObj) { - var finalObj = {}; - finalObj['condition'] = /^AND\(/.test(urlObj) ? "AND" : "OR"; - urlObj = finalObj.condition === "AND" ? urlObj.substr(4).slice(0, -1) : urlObj.substr(3).slice(0, -1); - finalObj[apiObj ? "criterion" : "rules"] = _.map(urlObj.split('|' + spliter + '|'), function(obj, key) { - var isStringNested = obj.split('|' + (spliter + 1) + '|').length > 1, - isCondition = /^AND\(/.test(obj) || /^OR\(/.test(obj); - if (isStringNested && isCondition) { - ++spliter; - return createObject(obj); - } else if (isCondition) { - return createObject(obj); - } else { - var temp = obj.split("::") || obj.split('|' + spliter + '|'), - rule = {}; - if (apiObj) { - rule = { attributeName: temp[0], operator: mapUiOperatorToAPI(temp[1]), attributeValue: _.trim(temp[2]) } - rule.attributeValue = rule.type === 'date' && formatDate && rule.attributeValue.length ? Utils.formatDate({ date: parseInt(rule.attributeValue), zone: false }) : rule.attributeValue; - } else { - rule = { id: temp[0], operator: temp[1], value: _.trim(temp[2]) } - if (temp[3]) { - rule['type'] = temp[3]; - } - if (rule.operator === "TIME_RANGE") { - if (temp[2].indexOf(",") > -1) { - rule.value = temp[2].split(",").map(function(udKey) { - return Utils.formatDate({ date: parseInt(udKey.trim()), zone: false }) - }).join(" - ") - } else { - rule.value = Enums.queryBuilderDateRangeAPIValueToUI[_.trim(rule.value)] || rule.value; - } - } else if (rule.type === 'date' && formatDate && rule.value.length) { - rule.value = Utils.formatDate({ date: parseInt(rule.value), zone: false }) - } - } - return rule; - } - }); - return finalObj; - } - //if apiObj then create object for API call else for QueryBuilder. - if (urlObj && urlObj.length) { - attrObj = createObject(urlObj); - } else { - return null; - } - return attrObj; - }, - generateAPIObj: function(url) { - if (url && url.length) { - return this.extractUrl({ "value": url, "apiObj": true }); - } else { - return null; - } - } - } - CommonViewFunction.createEditGlossaryCategoryTerm = function(options) { - if (options) { - var model = options.model, - isTermView = options.isTermView, - isGlossaryView = options.isGlossaryView, - collection = options.collection - } - require([ - 'views/glossary/CreateEditCategoryTermLayoutView', - 'views/glossary/CreateEditGlossaryLayoutView', - 'modules/Modal' - ], function(CreateEditCategoryTermLayoutView, CreateEditGlossaryLayoutView, Modal) { - var view = null, - title = null; - if (isGlossaryView) { - view = new CreateEditGlossaryLayoutView({ "glossaryCollection": collection, "model": model }); - title = "Glossary"; - } else { - view = new CreateEditCategoryTermLayoutView({ "glossaryCollection": collection, "modelJSON": model }); - title = (isTermView ? 'Term' : 'Category'); - } - - var modal = new Modal({ - "title": ((model ? "Update " : "Create ") + title), - "content": view, - "cancelText": "Cancel", - "okCloses": false, - "okText": model ? "Update" : "Create", - "allowCancel": true - }).open(); - modal.$el.find('input[data-id=shortDescription]').on('input keydown', function(e) { - $(this).val($(this).val().replace(/\s+/g, ' ')); - }); - modal.$el.find('button.ok').attr("disabled", "true"); - modal.on('ok', function() { - modal.$el.find('button.ok').showButtonLoader(); - CommonViewFunction.createEditGlossaryCategoryTermSubmit(_.extend({ "ref": view, "modal": modal }, options)); - }); - modal.on('closeModal', function() { - modal.trigger('cancel'); - if (options.onModalClose) { - options.onModalClose() - } - }); - }); - } - CommonViewFunction.createEditGlossaryCategoryTermSubmit = function(options) { - if (options) { - var ref = options.ref, - modal = options.modal, - model = options.model, - node = options.node, - isTermView = options.isTermView, - isCategoryView = options.isCategoryView, - collection = options.collection, - isGlossaryView = options.isGlossaryView, - data = ref.ui[(isGlossaryView ? "glossaryForm" : "categoryTermForm")].serializeArray().reduce(function(obj, item) { - obj[item.name] = item.value.trim(); - return obj; - }, {}), - newModel = new options.collection.model(), - messageType = "Glossary "; - } - if (isTermView) { - messageType = "Term "; - } else if (isCategoryView) { - messageType = "Category "; - } - var ajaxOptions = { - silent: true, - success: function(rModel, response) { - var msgType = model ? "editSuccessMessage" : "addSuccessMessage"; - Utils.notifySuccess({ - content: messageType + ref.ui.name.val() + Messages.getAbbreviationMsg(false, msgType) - }); - if (options.callback) { - options.callback(rModel); - } - modal.trigger('closeModal'); - }, - cust_error: function() { - modal.$el.find('button.ok').hideButtonLoader(); - } - } - if (model) { - if (isGlossaryView) { - model.clone().set(data, { silent: true }).save(null, ajaxOptions) - } else { - newModel[isTermView ? "createEditTerm" : "createEditCategory"](_.extend(ajaxOptions, { - guid: model.guid, - data: JSON.stringify(_.extend({}, model, data)), - })); - } - - } else { - if (isGlossaryView) { - new collection.model().set(data).save(null, ajaxOptions); - } else { - if (node) { - var key = "anchor", - guidKey = "glossaryGuid"; - data["anchor"] = { - "glossaryGuid": node.glossaryId || node.guid, - "displayText": node.glossaryName || node.text - } - if (node.type == "GlossaryCategory") { - data["parentCategory"] = { - "categoryGuid": node.guid - } - } - } - newModel[isTermView ? "createEditTerm" : "createEditCategory"](_.extend(ajaxOptions, { - data: JSON.stringify(data), - })); - } - } - } - CommonViewFunction.removeCategoryTermAssociation = function(options) { - if (options) { - var selectedGuid = options.selectedGuid, - termGuid = options.termGuid, - isCategoryView = options.isCategoryView, - isTermView = options.isTermView, - isEntityView = options.isEntityView, - collection = options.collection, - model = options.model, - newModel = new options.collection.model(), - noticeRef = null, - ajaxOptions = { - success: function(rModel, response) { - if (noticeRef) { - noticeRef.remove(); - } - Utils.notifySuccess({ - content: ((isCategoryView || isEntityView ? "Term" : "Category") + " association is removed successfully") - }); - if (options.callback) { - options.callback(); - } - }, - cust_error: function() { - if (noticeRef) { - noticeRef.hideButtonLoader(); - } - if (options.hideLoader) { - options.hideLoader(); - } - } - }, - notifyObj = { - modal: true, - okCloses: false, - okShowLoader: true, - text: options.msg, - title: options.titleMessage, - okText: options.buttonText, - ok: function(notice) { - noticeRef = notice; - if (options.showLoader) { - options.showLoader(); - } - if (isEntityView && model) { - var data = [model]; - newModel.removeTermFromEntity(termGuid, _.extend(ajaxOptions, { - data: JSON.stringify(data) - })) - } else { - var data = _.extend({}, model); - if (isTermView) { - data.categories = _.reject(data.categories, function(term) { return term.categoryGuid == selectedGuid }); - } else { - data.terms = _.reject(data.terms, function(term) { return term.termGuid == selectedGuid }); - } - - newModel[isTermView ? "createEditTerm" : "createEditCategory"](_.extend(ajaxOptions, { - guid: model.guid, - data: JSON.stringify(_.extend({}, model, data)), - })); - } - }, - cancel: function() {} - }; - Utils.notifyConfirm(notifyObj); - } - } - CommonViewFunction.addRestCsrfCustomHeader = function(xhr, settings) { - if (null != settings.url) { - var method = settings.type; - var csrfToken = CommonViewFunction.restCsrfValue; - null == CommonViewFunction.restCsrfCustomHeader || CommonViewFunction.restCsrfMethodsToIgnore[method] || xhr.setRequestHeader(CommonViewFunction.restCsrfCustomHeader, csrfToken); - } - } - CommonViewFunction.restCsrfCustomHeader = null; - CommonViewFunction.restCsrfMethodsToIgnore = null; - CommonViewFunction.userDataFetch = function(options) { - var csrfEnabled = false, - header = null, - methods = []; - - function getTrimmedStringArrayValue(string) { - var str = string, - array = []; - if (str) { - var splitStr = str.split(','); - for (var i = 0; i < splitStr.length; i++) { - array.push(splitStr[i].trim()); - } - } - return array; - } - if (options.url) { - $.ajax({ - url: options.url, - success: function(response) { - if (response) { - if (response['atlas.rest-csrf.enabled']) { - var str = "" + response['atlas.rest-csrf.enabled']; - csrfEnabled = (str.toLowerCase() == 'true'); - } - if (response["atlas.rest-csrf.custom-header"] && (header = response["atlas.rest-csrf.custom-header"].trim()), - response["atlas.rest-csrf.methods-to-ignore"] && (methods = getTrimmedStringArrayValue(response["atlas.rest-csrf.methods-to-ignore"])), - csrfEnabled) { - CommonViewFunction.restCsrfCustomHeader = header, CommonViewFunction.restCsrfMethodsToIgnore = {}, - CommonViewFunction.restCsrfValue = response["_csrfToken"] || '""', - methods.map(function(method) { - CommonViewFunction.restCsrfMethodsToIgnore[method] = !0; - }); - var statusCodeErrorFn = function(error) { - Utils.defaultErrorHandler(null, error) - } - Backbone.$.ajaxSetup({ - statusCode: { - 401: statusCodeErrorFn, - 419: statusCodeErrorFn, - 403: statusCodeErrorFn - }, - beforeSend: CommonViewFunction.addRestCsrfCustomHeader - }); - } - } - }, - complete: function(response) { - if (options.callback) { - options.callback(response.responseJSON); - } - } - }); - } - } - CommonViewFunction.CheckDuplicateAndEmptyInput = function(elements, datalist) { - var keyMap = new Map(), - validation = true, - hasDup = []; - for (var i = 0; i < elements.length; i++) { - var input = elements[i], - pEl = input.nextElementSibling, - classes = 'form-control', - val = input.value.trim(); - pEl.innerText = ""; - - if (val === '') { - validation = false; - pEl.innerText = 'Required!'; - } else if (val.includes(':')) { - validation = false; - var errorText = $(".errorMsg[data-id='charSupportMsg']").text(); - if (errorText && errorText.length === 0) { - pEl.innerText = "These special character '(:)' are not supported."; - } - } else { - if (input.tagName === 'INPUT') { - var duplicates = datalist.filter(function(c) { - return c.key === val; - }); - if (keyMap.has(val) || duplicates.length > 1) { - classes = 'form-control errorClass'; - hasDup.push('duplicate'); - pEl.innerText = 'Duplicate key'; - } else { - keyMap.set(val, val); - } - } - } - if (validation === false) { - classes = 'form-control errorClass'; - } - input.setAttribute('class', classes); - } - return { - validation: validation, - hasDuplicate: (hasDup.length === 0 ? false : true) - }; - } - CommonViewFunction.getRandomIdAndAnchor = function() { - var randomId = "collapse_" + parseInt((Math.random() * 100)) + "_" + new Date().getUTCMilliseconds(); - return { - id: randomId, - anchor: "#" + randomId - }; - } - CommonViewFunction.udKeysStringParser = function(udKeys) { - var o = {}; - _.each(udKeys.split(','), function(udKey) { - var ud = udKey.split(':'); - o[ud[0]] = ud[1]; - }) - return o; - } - CommonViewFunction.udKeysObjectToStringParser = function(udKeys) { - var list = _.map(udKeys, function(udKey) { - var t = udKey.key + ':' + udKey.value; - return t; - }); - return list.join(','); - } - CommonViewFunction.fetchRootEntityAttributes = function(options) { - $.ajax({ - url: options.url, - methods: 'GET', - dataType: 'json', - cache: true, - success: function(response) { - if (response) { - _.each(options.entity, function(rootEntity) { - Globals[rootEntity] = $.extend(true, {}, response, { name: rootEntity, guid: rootEntity }); - }); - } - }, - complete: function(response) { - if (options.callback) { - options.callback(response); - } - } - }); - } - CommonViewFunction.fetchRootClassificationAttributes = function(options) { - $.ajax({ - url: options.url, - methods: 'GET', - dataType: 'json', - cache: true, - success: function(response) { - if (response) { - _.each(options.classification, function(rootClassification) { - Globals[rootClassification] = $.extend(true, {}, response, { name: rootClassification, guid: rootClassification }); - }); - } - }, - complete: function(response) { - if (options.callback) { - options.callback(response); - } - } - }); - } - return CommonViewFunction; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/utils/Enums.js b/dashboardv2/public/js/utils/Enums.js deleted file mode 100644 index ee80313c22e..00000000000 --- a/dashboardv2/public/js/utils/Enums.js +++ /dev/null @@ -1,286 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(["require", "backbone"], function(require) { - 'use strict'; - - var Enums = {}; - - Enums.auditAction = { - ENTITY_CREATE: "Entity Created", - ENTITY_UPDATE: "Entity Updated", - ENTITY_DELETE: "Entity Deleted", - CLASSIFICATION_ADD: "Classification Added", - CLASSIFICATION_DELETE: "Classification Deleted", - CLASSIFICATION_UPDATE: "Classification Updated", - PROPAGATED_CLASSIFICATION_ADD: "Propagated Classification Added", - PROPAGATED_CLASSIFICATION_DELETE: "Propagated Classification Deleted", - PROPAGATED_CLASSIFICATION_UPDATE: "Propagated Classification Updated", - ENTITY_IMPORT_CREATE: "Entity Created by import", - ENTITY_IMPORT_UPDATE: "Entity Updated by import", - ENTITY_IMPORT_DELETE: "Entity Deleted by import", - TERM_ADD: "Term Added", - TERM_DELETE: "Term Deleted", - LABEL_ADD: "Label(s) Added", - LABEL_DELETE: "Label(s) Deleted", - ENTITY_PURGE: "Entity Purged", - BUSINESS_ATTRIBUTE_ADD: "Business Attribute(s) Added", - BUSINESS_ATTRIBUTE_UPDATE: "Business Attribute(s) Updated", - BUSINESS_ATTRIBUTE_DELETE: "Business Attribute(s) Deleted", - CUSTOM_ATTRIBUTE_UPDATE: "User-defined Attribute(s) Updated", - TYPE_DEF_UPDATE: "Type Updated", - TYPE_DEF_CREATE: "Type Created", - TYPE_DEF_DELETE: "Type Deleted", - IMPORT: "Import", - EXPORT: "Export" - } - Enums.serverAudits = { - SERVER_START: "Server Start", - SERVER_STOP: "Server End", - SERVER_STATE_ACTIVE: "Server State Active", - SERVER_STATE_PASSIVE: "Server State Passive" - } - - Enums.category = { - PRIMITIVE: "Primitive", - OBJECT_ID_TYPE: "Object Id type", - ENUM: "Enum", - STRUCT: "Struct", - CLASSIFICATION: "Classification", - ENTITY: "Entity", - ARRAY: "Array", - MAP: "Map", - RELATIONSHIP: "Relationship", - BUSINESS_METADATA: "Business Metadata", - PURGE: "Purge Entities", - IMPORT: "Import Entities", - EXPORT: "Export Entities" - } - - Enums.entityStateReadOnly = { - ACTIVE: false, - DELETED: true, - STATUS_ACTIVE: false, - STATUS_DELETED: true - } - - Enums.isEntityPurged = { - PURGED: true - } - - Enums.lineageUrlType = { - INPUT: 'inputs', - OUTPUT: 'outputs', - SCHEMA: 'schema' - } - - Enums.searchUrlType = { - DSL: 'dsl', - FULLTEXT: 'basic' - } - - Enums.profileTabType = { - 'count-frequency': "Count Frequency Distribution", - 'decile-frequency': "Decile Frequency Distribution", - 'annual': "Annual Distribution" - } - Enums.extractFromUrlForSearch = { - "searchParameters": { - "pageLimit": "limit", - "type": "typeName", - "tag": "classification", - "query": "query", - "pageOffset": "offset", - "includeDE": "excludeDeletedEntities", - "excludeST": "includeSubTypes", - "excludeSC": "includeSubClassifications", - "tagFilters": "tagFilters", - "entityFilters": "entityFilters", - "attributes": "attributes", - "term": "termName" - }, - "uiParameters": "uiParameters" - } - Enums.regex = { - RANGE_CHECK: { - "byte": { - min: -128, - max: 127 - }, - "short": { - min: -32768, - max: 32767 - }, - "int": { - min: -2147483648, - max: 2147483647 - }, - "long": { - min: -9223372036854775808, - max: 9223372036854775807 - }, - "float": { - min: -3.4028235E38, - max: 3.4028235E38 - }, - "double": { - min: -1.7976931348623157E308, - max: 1.7976931348623157E308 - } - } - } - Enums.graphIcon = { - // hive_db: { icon: "fa-database", textContent: '\uf1c0' }, - // hive_column: { icon: "fa-columns", textContent: '\uf0db' }, - // hive_table: { icon: "fa-table", textContent: '\uf0ce' } - } - var getTermRelationAttributes = function() { - return { - description: null, - expression: null, - steward: null, - source: null - } - } - Enums.termRelationAttributeList = { - seeAlso: getTermRelationAttributes(), - synonyms: getTermRelationAttributes(), - antonyms: getTermRelationAttributes(), - preferredTerms: getTermRelationAttributes(), - preferredToTerms: getTermRelationAttributes(), - replacementTerms: getTermRelationAttributes(), - replacedBy: getTermRelationAttributes(), - translationTerms: getTermRelationAttributes(), - translatedTerms: getTermRelationAttributes(), - isA: getTermRelationAttributes(), - classifies: getTermRelationAttributes(), - validValues: getTermRelationAttributes(), - validValuesFor: getTermRelationAttributes() - } - Enums.addOnClassification = ["_ALL_CLASSIFICATION_TYPES", "_CLASSIFIED", "_NOT_CLASSIFIED"]; - Enums.addOnEntities = ["_ALL_ENTITY_TYPES"]; - - Enums.stats = { - generalData: { - "collectionTime": "day" - }, - Server: { - "startTimeStamp": "day", - "activeTimeStamp": "day", - "upTime": "none" - }, - ConnectionStatus: { - "statusBackendStore": "status-html", - "statusIndexStore": "status-html" - }, - Notification: { - "currentDay": "number", - "currentDayAvgTime": "number", - "currentDayEntityCreates": "number", - "currentDayEntityDeletes": "number", - "currentDayEntityUpdates": "number", - "currentDayFailed": "number", - "currentDayStartTime": "day", - "currentHour": "number", - "currentHourAvgTime": "millisecond", - "currentHourEntityCreates": "number", - "currentHourEntityDeletes": "number", - "currentHourEntityUpdates": "number", - "currentHourFailed": "number", - "currentHourStartTime": "day", - "lastMessageProcessedTime": "day", - "offsetCurrent": "number", - "offsetStart": "number", - "previousDay": "number", - "previousDayAvgTime": "millisecond", - "previousDayEntityCreates": "number", - "previousDayEntityDeletes": "number", - "previousDayEntityUpdates": "number", - "previousDayFailed": "number", - "previousHour": "number", - "previousHourAvgTime": "millisecond", - "previousHourEntityCreates": "number", - "previousHourEntityDeletes": "number", - "previousHourEntityUpdates": "number", - "previousHourFailed": "number", - "total": "number", - "totalAvgTime": "millisecond", - "totalCreates": "number", - "totalDeletes": "number", - "totalFailed": "number", - "totalUpdates": "number", - "processedMessageCount": "number", - "failedMessageCount": "number" - } - }; - Enums.systemAttributes = { - "__classificationNames": "Classification(s)", - "__createdBy": "Created By User", - "__customAttributes": "User-defined Properties", - "__guid": "Guid", - "__isIncomplete": "IsIncomplete", - "__labels": "Label(s)", - "__modificationTimestamp": "Last Modified Timestamp", - "__modifiedBy": "Last Modified User", - "__propagatedClassificationNames": "Propagated Classification(s)", - "__state": "Status", - "__entityStatus": "Entity Status", - "__timestamp": "Created Timestamp", - "__typeName": "Type Name" - }; - Enums.__isIncomplete = { - 0: "false", - 1: "true" - }; - - Enums.queryBuilderUIOperatorToAPI = { - "=": "eq", - "!=": "neq", - "<": "lt", - "<=": "lte", - ">": "gt", - ">=": "gte", - "begins_with": "startsWith", - "ends_with": "endsWith", - "not_null": "notNull", - "is_null": "isNull", - "TIME_RANGE": "timerange" - }; - - Enums.queryBuilderApiOperatorToUI = _.invert(Enums.queryBuilderUIOperatorToAPI); - - Enums.queryBuilderDateRangeUIValueToAPI = { - "Today": "TODAY", - "Yesterday": "YESTERDAY", - "Last 7 Days": "LAST_7_DAYS", - "Last 30 Days": "LAST_30_DAYS", - "This Month": "THIS_MONTH", - "Last Month": "LAST_MONTH", - "This Quarter": "THIS_QUARTER", - "Last Quarter": "LAST_QUARTER", - "This Year": "THIS_YEAR", - "Last Year": "LAST_YEAR", - "Last 3 Months": "LAST_3_MONTHS", - "Last 6 Months": "LAST_6_MONTHS", - "Last 12 Months": "LAST_12_MONTHS" - }; - - Enums.queryBuilderDateRangeAPIValueToUI = _.invert(Enums.queryBuilderDateRangeUIValueToAPI); - - return Enums; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/utils/Globals.js b/dashboardv2/public/js/utils/Globals.js deleted file mode 100644 index 8fe8ebc4cf4..00000000000 --- a/dashboardv2/public/js/utils/Globals.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(["require"], function(require) { - "use strict"; - - var Globals = {}; - Globals.settings = {}; - Globals.settings.PAGE_SIZE = 25; - Globals.saveApplicationState = { - mainPageState: {}, - tabState: { - stateChanged: false, - tagUrl: "#!/tag", - searchUrl: "#!/search", - glossaryUrl: "#!/glossary", - administratorUrl: "#!/administrator", - debugMetricsUrl: "#!/debugMetrics" - }, - detailPageState: {} - }; - Globals.userLogedIn = { - status: false, - response: {} - }; - Globals.serviceTypeMap = {}; - Globals.entityImgPath = "/img/entity-icon/"; - Globals.DEFAULT_UI = "v2"; - - // Date Format - Globals.dateTimeFormat = "MM/DD/YYYY hh:mm:ss A"; - Globals.dateFormat = "MM/DD/YYYY"; - Globals.isTimezoneFormatEnabled = true; - - Globals.isDebugMetricsEnabled = false; - Globals.isTasksEnabled = false; - Globals.idealTimeoutSeconds = 900; - - return Globals; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/utils/Helper.js b/dashboardv2/public/js/utils/Helper.js deleted file mode 100644 index f211bd055a8..00000000000 --- a/dashboardv2/public/js/utils/Helper.js +++ /dev/null @@ -1,378 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -define(['require', - 'utils/Utils', - 'd3', - 'marionette', - 'jquery-ui' -], function(require, Utils, d3) { - 'use strict'; - _.mixin({ - numberFormatWithComma: function(number) { - return d3.format(',')(number); - }, - numberFormatWithBytes: function(number) { - if (number > -1) { - if (number === 0) { - return "0 Bytes"; - } - var i = number == 0 ? 0 : Math.floor(Math.log(number) / Math.log(1024)); - if (i > 8) { - return _.numberFormatWithComma(number); - } - return Number((number / Math.pow(1024, i)).toFixed(2)) + " " + ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"][i]; - } else { - return number; - } - }, - isEmptyArray: function(val) { - if (val && _.isArray(val)) { - return _.isEmpty(val); - } else { - return false; - } - }, - toArrayifObject: function(val) { - return _.isObject(val) ? [val] : val; - }, - startsWith: function(str, matchStr) { - if (str && matchStr && _.isString(str) && _.isString(matchStr)) { - return str.lastIndexOf(matchStr, 0) === 0 - } else { - return; - } - }, - isUndefinedNull: function(val) { - if (_.isUndefined(val) || _.isNull(val)) { - return true - } else { - return false; - } - }, - trim: function(val) { - if (val && val.trim) { - return val.trim(); - } else { - return val; - } - }, - isTypePrimitive: function(type) { - if (type === "int" || type === "byte" || type === "short" || type === "long" || type === "float" || type === "double" || type === "string" || type === "boolean" || type === "date") { - return true; - } - return false; - } - }); - var getPopoverEl = function(e) { - return $(e.target).parent().data("bs.popover") || $(e.target).data("bs.popover") || $(e.target).parents('.popover').length; - } - $(document).on('click DOMMouseScroll mousewheel', function(e) { - if (e.originalEvent) { - // Do action if it is triggered by a human. - //e.isImmediatePropagationStopped(); - var isPopOverEl = getPopoverEl(e) - if (!isPopOverEl) { - $('.popover').popover('hide'); - } else if (isPopOverEl.$tip) { - $('.popover').not(isPopOverEl.$tip).popover('hide'); - } - $(".tooltip").tooltip("hide"); - } - }); - $('body').on('hidden.bs.popover', function(e) { - $(e.target).data("bs.popover").inState = { click: false, hover: false, focus: false } - }); - $('body').on('show.bs.popover', '[data-js="popover"]', function() { - $('.popover').not(this).popover('hide'); - }); - $('body').on('keypress', 'input.number-input,.number-input .select2-search__field', function(e) { - if (e.which != 8 && e.which != 0 && (e.which < 48 || e.which > 57)) { - return false; - } - }); - $('body').on('keypress', 'input.number-input-negative,.number-input-negative .select2-search__field', function(e) { - if (e.which != 8 && e.which != 0 && (e.which < 48 || e.which > 57)) { - if (e.which == 45) { - if (this.value.length) { - return false; - } - } else { - return false; - } - } - }); - $('body').on('keypress', 'input.number-input-exponential,.number-input-exponential .select2-search__field', function(e) { - if ((e.which != 8 && e.which != 0) && (e.which < 48 || e.which > 57) && (e.which != 69 && e.which != 101 && e.which != 43 && e.which != 45 && e.which != 46 && e.which != 190)) { - return false; - } - }); - $("body").on('click', '.dropdown-menu.dropdown-changetitle li a', function() { - $(this).parents('li').find(".btn:first-child").html($(this).text() + ' '); - }); - $("body").on('click', '.btn', function() { - $(this).blur(); - }); - $('body').on('keyup input', '.modal-body', function(e) { - var target = e.target, - isGlossary = (e.target.dataset.id === "searchTerm" || e.target.dataset.id === "searchCategory") ? true : false; // assign term/category modal - if ((target.type === "text" || target.type === "textarea") && !isGlossary) { - var $this = $(this), - $footerButton = $this.parents(".modal").find('.modal-footer button.ok'), - requiredInputField = _.filter($this.find('input'), function($e) { - if ($e.getAttribute('placeholder') && $e.getAttribute('placeholder').indexOf('require') >= 0) { - return ($e.value.trim() == ""); - } - }); - if (requiredInputField.length > 0) { - $footerButton.attr("disabled", "true"); - } else { - $footerButton.removeAttr("disabled"); - } - } - }); - if ($.fn.select2) { - $.fn.select2.amd.define("TagHideDeleteButtonAdapter", [ - "select2/utils", - "select2/selection/multiple", - "select2/selection/placeholder", - "select2/selection/eventRelay", - "select2/selection/search", - ], - function(Utils, MultipleSelection, Placeholder, EventRelay, SelectionSearch) { - - // Decorates MultipleSelection with Placeholder - - var adapter = Utils.Decorate(MultipleSelection, Placeholder); - adapter = Utils.Decorate(adapter, SelectionSearch); - adapter = Utils.Decorate(adapter, EventRelay); - - adapter.prototype.render = function() { - // Use selection-box from SingleSelection adapter - // This implementation overrides the default implementation - var $search = $( - '' - ); - - this.$searchContainer = $search; - this.$search = $search.find('input'); - var $selection = MultipleSelection.prototype.render.call(this); - this._transferTabIndex(); - return $selection; - }; - - adapter.prototype.update = function(data) { - // copy and modify SingleSelection adapter - var that = this; - this.clear(); - if (data.length === 0) { - this.$selection.find('.select2-selection__rendered') - .append(this.$searchContainer); - this.$search.attr('placeholder', this.options.get("placeholder")); - return; - } - this.$search.attr('placeholder', ''); - var $rendered = this.$selection.find('.select2-selection__rendered'), - $selectionContainer = []; - if (data.length > 0) { - _.each(data, function(obj) { - var $container = $('
    1. '), - formatted = that.display(obj, $rendered), - $remove = $('×'), - allowRemoveAttr = $(obj.element).data("allowremove"), - allowRemove = obj.allowRemove === undefined ? allowRemoveAttr : obj.allowRemove; - if (allowRemove === undefined || allowRemove !== false) { - $container.append($remove); - } - $container.data("data", obj); - $container.append(formatted); - $selectionContainer.push($container); - }); - Utils.appendMany($rendered, $selectionContainer); - } - - - var searchHadFocus = this.$search[0] == document.activeElement; - this.$search.attr('placeholder', ''); - this.$selection.find('.select2-selection__rendered') - .append(this.$searchContainer); - this.resizeSearch(); - if (searchHadFocus) { - this.$search.focus(); - } - }; - return adapter; - }); - - - $.fn.select2.amd.define("ServiceTypeFilterDropdownAdapter", [ - "select2/utils", - "select2/dropdown", - "select2/dropdown/attachBody", - "select2/dropdown/attachContainer", - "select2/dropdown/search", - "select2/dropdown/minimumResultsForSearch", - "select2/dropdown/closeOnSelect", - ], - function(Utils, Dropdown, AttachBody, AttachContainer, Search, MinimumResultsForSearch, CloseOnSelect) { - - // Decorate Dropdown with Search functionalities - var dropdownWithSearch = Utils.Decorate(Utils.Decorate(Dropdown, CloseOnSelect), Search); - - dropdownWithSearch.prototype.render = function() { - // Copy and modify default search render method - var $rendered = Dropdown.prototype.render.call(this), - dropdownCssClass = this.options.get("dropdownCssClass") - if (dropdownCssClass) { - $rendered.addClass(dropdownCssClass); - } - - // Add ability for a placeholder in the search box - var placeholder = this.options.get("placeholderForSearch") || ""; - var $search = $( - '
      ' + - '
      ' + - '
      ' + - '
      ' - ); - if (!this.options.options.getFilterBox) { - throw "In order to render the filter options adapter needed getFilterBox function" - } - var $Filter = $('
        '); - this.$Filter = $Filter; - this.$Filter.append(this.options.options.getFilterBox()); - this.$Filter.hide(); - - this.$searchContainer = $search; - if ($Filter.find('input[type="checkbox"]:checked').length) { - $search.find('button.filter').addClass('active'); - } else { - $search.find('button.filter').removeClass('active'); - } - this.$search = $search.find('input'); - - $rendered.prepend($search); - $rendered.append($Filter); - return $rendered; - }; - var oldDropdownWithSearchBindRef = dropdownWithSearch.prototype.bind; - dropdownWithSearch.prototype.bind = function(container, $container) { - var self = this; - oldDropdownWithSearchBindRef.call(this, container, $container); - var self = this; - this.$Filter.on('click', 'li', function() { - var itemCallback = self.options.options.onFilterItemSelect; - itemCallback && itemCallback(this); - }) - - this.$searchContainer.find('button.filter').click(function() { - container.$dropdown.find('.select2-search').hide(150); - container.$dropdown.find('.select2-results').hide(150); - self.$Filter.html(self.options.options.getFilterBox()); - self.$Filter.show(); - }); - this.$Filter.on('click', 'button.filterDone', function() { - container.$dropdown.find('.select2-search').show(150); - container.$dropdown.find('.select2-results').show(150); - self.$Filter.hide(); - var filterSubmitCallback = self.options.options.onFilterSubmit; - filterSubmitCallback && filterSubmitCallback({ - filterVal: _.map(self.$Filter.find('input[type="checkbox"]:checked'), function(item) { - return $(item).data('value') - }) - }); - }); - container.$element.on('hideFilter', function() { - container.$dropdown.find('.select2-search').show(); - container.$dropdown.find('.select2-results').show(); - self.$Filter.hide(); - }); - - } - // Decorate the dropdown+search with necessary containers - var adapter = Utils.Decorate(dropdownWithSearch, AttachContainer); - adapter = Utils.Decorate(adapter, AttachBody); - - return adapter; - }); - } - - - $.widget("custom.atlasAutoComplete", $.ui.autocomplete, { - _create: function() { - this._super(); - this.widget().menu("option", "items", "> :not(.ui-autocomplete-category,.empty)"); - }, - _renderMenu: function(ul, items) { - var that = this, - currentCategory = ""; - items = _.sortBy(items, 'order'); - $.each(items, function(index, item) { - var li; - if (item.category != currentCategory) { - ul.append("
      • " + item.category + "
      • "); - currentCategory = item.category; - } - that._renderItemData(ul, item); - }); - }, - _renderItemData: function(ul, item) { - return this._renderItem(ul, item); - } - }); - - // For placeholder support - if (!('placeholder' in HTMLInputElement.prototype)) { - var originalRender = Backbone.Marionette.LayoutView.prototype.render; - Backbone.Marionette.LayoutView.prototype.render = function() { - originalRender.apply(this, arguments); - this.$('input, textarea').placeholder(); - } - } - $('body').on('click', 'pre.code-block .expand-collapse-button', function(e) { - var $el = $(this).parents('.code-block'); - if ($el.hasClass('shrink')) { - $el.removeClass('shrink'); - } else { - $el.addClass('shrink'); - } - }); - - // For adding tooltip globally - $("body").on('mouseenter', '.select2-selection__choice', function() { - $(this).attr("title", ""); - }); - if ($('body').tooltip) { - $('body').tooltip({ - selector: '[title]:not(".select2-selection__choice,.select2-selection__rendered")', - placement: function() { - return this.$element.attr("data-placement") || "bottom"; - }, - container: 'body' - }); - } - //For closing the modal on browsers navigation - $(window).on('popstate', function(){ - $('body').find('.modal-dialog .close').click(); - }); -}) \ No newline at end of file diff --git a/dashboardv2/public/js/utils/Messages.js b/dashboardv2/public/js/utils/Messages.js deleted file mode 100644 index d79fb904da1..00000000000 --- a/dashboardv2/public/js/utils/Messages.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require'], function(require) { - 'use strict'; - - var Messages = { - defaultErrorMessage: "Something went wrong", - addSuccessMessage: " created successfully", - addErrorMessage: " could not be Created", - removeTag: "Remove Classification Assignment", - deleteSuccessMessage: " deleted successfully", - deleteErrorMessage: " could not be deleted", - removeSuccessMessage: " removed successfully", - removeErrorMessage: " could not be removed", - editSuccessMessage: " updated successfully", - assignDeletedEntity: " is deleted, Classification cannot be assigned", - assignTermDeletedEntity: " is deleted, Term cannot be assigned", - conformation: { - deleteMessage: "Are you sure you want to delete " - }, - search: { - noRecordForPage: "No record found at ", - onSamePage: "You are on the same page!", - notExists: "Invalid Expression or Classification/Type has been deleted.", - favoriteSearch: { - save: "Do you want to overwrite ", - notSelectedFavoriteElement: "Please select any one favorite search", - notSelectedSearchFilter: "Please select at least one filter" - } - }, - tag: { - addAttributeSuccessMessage: "Classification attribute is added successfully", - updateTagDescriptionMessage: "Classification description is updated successfully" - }, - glossary: { - removeTermfromCategory: "Remove Term Assignment", - removeTermfromEntity: "Remove Term Assignment", - removeCategoryfromTerm: "Remove Category Assignment" - }, - getAbbreviationMsg: function(abbrev, type) { - var msg = abbrev ? "s were" : " was"; - return msg + this[type]; - } - }; - return Messages; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/utils/MigrationEnums.js b/dashboardv2/public/js/utils/MigrationEnums.js deleted file mode 100644 index c89b9da47df..00000000000 --- a/dashboardv2/public/js/utils/MigrationEnums.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require'], function(require) { - 'use strict'; - - var Enums = {}; - - Enums.migrationStatus = { - STARTED: "STARTED", - IN_PROGRESS: "IN_PROGRESS", - FAIL: "FAIL", - DONE: "DONE" - } - - return Enums; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/utils/Overrides.js b/dashboardv2/public/js/utils/Overrides.js deleted file mode 100644 index 492785aabe6..00000000000 --- a/dashboardv2/public/js/utils/Overrides.js +++ /dev/null @@ -1,337 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', 'utils/Utils', 'lossless-json', 'marionette', 'backgrid', 'asBreadcrumbs', 'jquery-placeholder'], function(require, Utils, LosslessJSON) { - 'use strict'; - - Backbone.$.ajaxSetup({ - cache: false - }); - - var oldBackboneSync = Backbone.sync; - Backbone.sync = function(method, model, options) { - var that = this; - if (options.queryParam) { - var generateQueryParam = $.param(options.queryParam); - if (options.url.indexOf('?') !== -1) { - options.url = options.url + "&" + generateQueryParam; - } else { - options.url = options.url + "?" + generateQueryParam; - } - } - return oldBackboneSync.apply(this, [method, model, - _.extend(options, { - error: function(response) { - Utils.defaultErrorHandler(that, response, options); - that.trigger("error", that, response); - if (options.cust_error) { - options.cust_error(that, response); - } - }, - converters: _.extend($.ajaxSettings.converters, { - "text json": function(data) { - try { - return LosslessJSON.parse(data, function(k, v) { try { return (v.isLosslessNumber) ? v.valueOf() : v } catch (err) { return v.value } }); - } catch (err) { - if (err.name.toLowerCase() === "syntaxerror" && data.length > 0 && data.indexOf(" -1) { // to handel logout for multile windows - var redirectUrl = window.location.origin + window.location.pathname; - window.location = redirectUrl.substring(0, redirectUrl.lastIndexOf("/")); - } else { - return $.parseJSON(data); - } - } - } - }) - }) - ]); - } - - String.prototype.trunc = String.prototype.trunc || - function(n) { - return (this.length > n) ? this.substr(0, n - 1) + '...' : this; - }; - String.prototype.capitalize = function() { - return this.charAt(0).toUpperCase() + this.slice(1); - } - - /* - * Overriding default sortType - */ - Backgrid.Column.prototype.defaults.sortType = "toggle"; - - /* - * Overriding Cell for adding custom className to Cell i.e - */ - var cellInit = Backgrid.Cell.prototype.initialize; - Backgrid.Cell.prototype.initialize = function() { - cellInit.apply(this, arguments); - var className = this.column.get('className'); - var rowClassName = this.column.get('rowClassName'); - if (rowClassName) this.$el.addClass(rowClassName); - if (className) this.$el.addClass(className); - } - /* - * Overriding Cell for adding custom width to Cell i.e - */ - Backgrid.HeaderRow = Backgrid.HeaderRow.extend({ - render: function() { - var that = this; - Backgrid.HeaderRow.__super__.render.apply(this, arguments); - _.each(this.columns.models, function(modelValue) { - var elAttr = modelValue.get('elAttr'), - elAttrObj = null; - if (elAttr) { - if (_.isFunction(elAttr)) { - elAttrObj = elAttr(modelValue); - } else if (_.isObject(elAttr)) { - if (!_.isArray(elAttr)) { - elAttrObj = [elAttr]; - } else { - elAttrObj = elAttr; - } - } - _.each(elAttrObj, function(val) { - that.$el.find('.' + modelValue.get('name')).data(val); - }); - } - if (modelValue.get('width')) that.$el.find('.' + modelValue.get('name')).css('min-width', modelValue.get('width') + 'px'); - if (modelValue.get('fixWidth')) that.$el.find('.' + modelValue.get('name')).css('width', modelValue.get('fixWidth') + 'px'); - if (modelValue.get('toolTip')) that.$el.find('.' + modelValue.get('name')).attr('title', modelValue.get('toolTip')); - if (modelValue.get('headerClassName')) that.$el.find('.' + modelValue.get('name').replace(".", "\\.")).addClass(modelValue.get('headerClassName')); - }); - return this; - } - }); - /* - * HtmlCell renders any html code - * @class Backgrid.HtmlCell - * @extends Backgrid.Cell - */ - var HtmlCell = Backgrid.HtmlCell = Backgrid.Cell.extend({ - - /** @property */ - className: "html-cell", - - render: function() { - this.$el.empty(); - var rawValue = this.model.get(this.column.get("name")); - var formattedValue = this.formatter.fromRaw(rawValue, this.model); - this.$el.append(formattedValue); - this.delegateEvents(); - return this; - } - }); - - - /* - * Backgrid Header render listener when resize or re-ordered - */ - var BackgridHeaderInitializeMethod = function(options) { - this.columns = options.columns; - if (!(this.columns instanceof Backbone.Collection)) { - this.columns = new Backgrid.Columns(this.columns); - } - this.createHeaderRow(); - - this.listenTo(this.columns, "sort", _.bind(function() { - this.createHeaderRow(); - this.render(); - }, this)); - }; - - /** - * Sets up a new headerRow and attaches it to the view - * Tested with backgrid 0.3.5 - */ - var BackgridHeaderCreateHeaderRowMethod = function() { - this.row = new Backgrid.HeaderRow({ - columns: this.columns, - collection: this.collection - }); - }; - - /** - * Tested with backgrid 0.3.5 - */ - var BackgridHeaderRenderMethod = function() { - this.$el.empty(); - this.$el.append(this.row.render().$el); - this.delegateEvents(); - - // Trigger event - this.trigger("backgrid:header:rendered", this); - - return this; - }; - /* - backgrid-expandable-cell - https://github.com/cime/backgrid-expandable-cell - - Copyright (c) 2014 Andrej Cimperšek - Licensed under the MIT @license. - */ - Backgrid.ExpandableCell = Backgrid.Cell.extend({ - accordion: true, - toggle: '', - toggleClass: 'toggle', - toggleExpandedClass: 'fa fa-angle-down', - toggleCollapsedClass: 'fa fa-angle-right', - trClass: 'expandable', - tdClass: 'expandable-content', - events: { - 'click': 'setToggle' - }, - initialize: function(options) { - if (options.accordion) { - this.accordion = options.accordion; - } - - this.column = options.column; - if (!(this.column instanceof Backgrid.Column)) { - this.column = new Backgrid.Column(this.column); - } - - var column = this.column, - model = this.model, - $el = this.$el; - - if (Backgrid.callByNeed(column.renderable(), column, model)) $el.addClass("renderable"); - }, - - render: function() { - /* follow along with the original render really... */ - this.$el.empty(); - var isExpand = true; - if (this.column.get('isExpandVisible')) { - isExpand = this.column.get('isExpandVisible')(this.$el, this.model); - } - this.$toggleEl = $(this.toggle).addClass(this.toggleClass).addClass(this.toggleCollapsedClass); - this.$toggleEl = isExpand ? this.$toggleEl : this.$toggleEl.addClass("noToggle"); - - this.$el.append(this.$toggleEl); - - this.delegateEvents(); - - return this; - }, - - setToggle: function() { - var detailsRow = this.$el.data('details'); - var toggle = this.$toggleEl; - /* if there's details data is not there/undefined and $toggleEl having noToggle class, no need to expand */ - if (!detailsRow && this.$toggleEl.hasClass('noToggle')) { - return false; - } - - /* if there's details data already stored, then we'll remove it */ - if (detailsRow) { - $(detailsRow).remove(); - this.$el.data('details', null); - toggle.removeClass(this.toggleExpandedClass).addClass(this.toggleCollapsedClass); - } else { - if (this.accordion) { - var table = this.$el.closest('table'); - $('.' + this.toggleClass, table).filter('.' + this.toggleExpandedClass).click(); - } - - var renderableColumns = this.$el.closest('table').find('th.renderable').length; - var isRenderable = false; - var cellClass = this.tdClass; - - if (Backgrid.callByNeed(this.column.renderable(), this.column, this.model)) { - isRenderable = true; - cellClass += ' renderable'; - } - - /* build a jquery object for the new row... */ - detailsRow = $(''); - - /* Inject new row */ - this.$el.closest('tr').after(detailsRow); - - /* Call expand function */ - this.column.get('expand')(detailsRow.find('td.' + this.tdClass), this.model); - - this.$el.data('details', detailsRow); - - toggle.removeClass(this.toggleCollapsedClass).addClass(this.toggleExpandedClass); - } - - return this; - } - }); - - // Backgrid patch - Backgrid.Header.prototype.initialize = BackgridHeaderInitializeMethod; - Backgrid.Header.prototype.createHeaderRow = BackgridHeaderCreateHeaderRowMethod; - Backgrid.Header.prototype.render = BackgridHeaderRenderMethod; - - /* End: Backgrid Header render listener when resize or re-ordered */ - - var UriCell = Backgrid.UriCell = Backgrid.Cell.extend({ - className: "uri-cell", - title: null, - target: "_blank", - - initialize: function(options) { - UriCell.__super__.initialize.apply(this, arguments); - this.title = options.title || this.title; - this.target = options.target || this.target; - }, - - render: function() { - this.$el.empty(); - var rawValue = this.model.get(this.column.get("name")); - var href = _.isFunction(this.column.get("href")) ? this.column.get('href')(this.model) : this.column.get('href'); - var klass = this.column.get("klass"); - var formattedValue = this.formatter.fromRaw(rawValue, this.model); - this.$el.append($("", { - tabIndex: -1, - href: href, - title: this.title || formattedValue, - 'class': klass - }).text(formattedValue)); - - if (this.column.has("iconKlass")) { - var iconKlass = this.column.get("iconKlass"); - var iconTitle = this.column.get("iconTitle"); - this.$el.find('a').append(''); - } - this.delegateEvents(); - return this; - } - }); - - var HeaderDecodeCell = Backgrid.HeaderHTMLDecodeCell = Backgrid.HeaderCell.extend({ - initialize: function(options) { - Backgrid.HeaderCell.prototype.initialize.apply(this, arguments); - this.name = _.unescape(this.column.get("label")) - // Add class - this.$el.addClass(this.name); - }, - render: function() { - this.$el.empty(); - - // Add to header - this.$el.text(this.name); - - this.delegateEvents(); - return this; - } - }); -}); \ No newline at end of file diff --git a/dashboardv2/public/js/utils/TableLayout.js b/dashboardv2/public/js/utils/TableLayout.js deleted file mode 100644 index 8322029b12b..00000000000 --- a/dashboardv2/public/js/utils/TableLayout.js +++ /dev/null @@ -1,772 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -/** - * @file This is the common View file for displaying Table/Grid to be used overall in the application. - */ -define(['require', - 'backbone', - 'hbs!tmpl/common/TableLayout_tmpl', - 'utils/Messages', - 'utils/Utils', - 'utils/Globals', - 'utils/CommonViewFunction', - 'backgrid-filter', - 'backgrid-paginator', - 'backgrid-sizeable', - 'backgrid-orderable', - 'backgrid-select-all', - 'backgrid-columnmanager' -], function(require, Backbone, FSTablelayoutTmpl, Messages, Utils, Globals, CommonViewFunction) { - 'use strict'; - - var FSTableLayout = Backbone.Marionette.LayoutView.extend( - /** @lends FSTableLayout */ - { - _viewName: 'FSTableLayout', - - template: FSTablelayoutTmpl, - templateHelpers: function() { - return this.options; - }, - - /** Layout sub regions */ - regions: { - 'rTableList': 'div[data-id="r_tableList"]', - 'rTableSpinner': 'div[data-id="r_tableSpinner"]', - 'rPagination': 'div[data-id="r_pagination"]', - 'rFooterRecords': 'div[data-id="r_footerRecords"]' - }, - - // /** ui selector cache */ - ui: { - selectPageSize: 'select[data-id="pageSize"]', - paginationDiv: '[data-id="paginationDiv"]', - previousData: "[data-id='previousData']", - nextData: "[data-id='nextData']", - pageRecordText: "[data-id='pageRecordText']", - showPage: "[data-id='showPage']", - gotoPage: "[data-id='gotoPage']", - gotoPagebtn: "[data-id='gotoPagebtn']", - activePage: "[data-id='activePage']" - }, - - gridOpts: { - className: 'table table-bordered table-hover table-condensed backgrid', - emptyText: 'No Records found!' - }, - - /** - * Backgrid.Filter default options - */ - filterOpts: { - placeholder: 'plcHldr.searchByResourcePath', - wait: 150 - }, - - /** - * Paginator default options - */ - paginatorOpts: { - // If you anticipate a large number of pages, you can adjust - // the number of page handles to show. The sliding window - // will automatically show the next set of page handles when - // you click next at the end of a window. - windowSize: 5, // Default is 10 - - // Used to multiple windowSize to yield a number of pages to slide, - // in the case the number is 5 - slideScale: 0.5, // Default is 0.5 - - // Whether sorting should go back to the first page - goBackFirstOnSort: false // Default is true - }, - - /** - page handlers for pagination - */ - controlOpts: { - rewind: null, - back: { - label: "", - title: "Previous" - }, - forward: { - label: "", - title: "Next" - }, - fastForward: null - }, - columnOpts: { - opts: { - initialColumnsVisible: 4, - // State settings - saveState: false, - loadStateOnInit: true - }, - visibilityControlOpts: {}, - el: null - }, - - includePagination: true, - - includeAtlasPagination: false, - - includeAtlasPageSize: false, - - includeFilter: false, - - includeHeaderSearch: false, - - includePageSize: false, - - includeGotoPage: false, - - includeFooterRecords: true, - - includeColumnManager: false, - - includeSizeAbleColumns: false, - - includeOrderAbleColumns: false, - - includeTableLoader: true, - - includeAtlasTableSorting: false, - - showDefaultTableSorted: false, - - /** - * [updateFullCollectionManually If collection was updated using silent true - * then need to update FullCollection Manually for correct sorting experience] - * @type {Boolean} - */ - updateFullCollectionManually: false, - - sortOpts: { - sortColumn: "name", - sortDirection: "ascending" - }, - - - /** ui events hash */ - events: function() { - var events = {}, - that = this; - events['change ' + this.ui.selectPageSize] = 'onPageSizeChange'; - events['change ' + this.ui.showPage] = 'changePageLimit'; - events["click " + this.ui.nextData] = "onClicknextData"; - events["click " + this.ui.previousData] = "onClickpreviousData"; - events["click " + this.ui.gotoPagebtn] = 'gotoPagebtn'; - events["keyup " + this.ui.gotoPage] = function(e) { - var code = e.which, - goToPage = parseInt(e.currentTarget.value); - if (e.currentTarget.value) { - that.ui.gotoPagebtn.attr('disabled', false); - } else { - that.ui.gotoPagebtn.attr('disabled', true); - } - if (code == 13) { - if (e.currentTarget.value) { - that.gotoPagebtn(); - } - } - }; - return events; - }, - - /** - * intialize a new HDFSTableLayout Layout - * @constructs - */ - initialize: function(options) { - this.limit = 25; - this.offset = 0; - _.extend(this, _.omit(options, 'gridOpts', 'sortOpts', 'atlasPaginationOpts')); - _.extend(this, options.atlasPaginationOpts); - _.extend(this.gridOpts, options.gridOpts, { collection: this.collection, columns: this.columns }); - _.extend(this.sortOpts, options.sortOpts); - if (this.isApiSorting) { - //after audit sorting pagination values - if (this.offset === 0) { - this.limit = this.count || this.limit; - } - } - if (this.includeAtlasTableSorting) { - var oldSortingRef = this.collection.setSorting; - this.collection.setSorting = function() { - this.state.pageSize = this.length - var val = oldSortingRef.apply(this, arguments); - val.fullCollection.sort(); - this.comparator = function(next, previous, data) { - var getValue = function(options) { - var next = options.next, - previous = options.previous, - order = options.order; - if (next === previous) { - return null; - } else { - if (order === -1) { - return next < previous ? -1 : 1; - } else { - return next < previous ? 1 : -1; - } - } - }, - getKeyVal = function(model, key) { - //for nested obj - var value = null; - if (model && key) { - value = model[key]; - if (!value) { - _.each(model, function(modalValue) { - if (typeof(modalValue) == "object") { - if (!value) { - value = getKeyVal(modalValue, key); - } - } - }); - } - } - return Number(value) || value; - }; - if (val.state && (!_.isNull(val.state.sortKey))) { - var nextValue, - previousValue; - if ((next && next.get("attributes") && next.get("attributes")[val.state.sortKey]) || (previous && previous.get("attributes") && previous.get("attributes")[val.state.sortKey])) { - nextValue = next.get("attributes")[val.state.sortKey]; - previousValue = previous.get("attributes")[val.state.sortKey]; - } else { - nextValue = getKeyVal(next.attributes, val.state.sortKey); - previousValue = getKeyVal(previous.attributes, val.state.sortKey); - } - nextValue = (typeof nextValue === 'string') ? nextValue.toLowerCase() : nextValue; - previousValue = (typeof previousValue === 'string') ? previousValue.toLowerCase() : previousValue; - return getValue({ - "next": nextValue || '', - "previous": previousValue || '', - "order": val.state.order - }); - } - } - return val; - }; - } - this.bindEvents(); - }, - /** all events binding here */ - bindEvents: function() { - this.listenTo(this.collection, 'request', function() { - this.$('div[data-id="r_tableSpinner"]').addClass('show'); - }, this); - this.listenTo(this.collection, 'sync error', function() { - this.$('div[data-id="r_tableSpinner"]').removeClass('show'); - }, this); - - this.listenTo(this.collection, 'reset', function(collection, options) { - this.$('div[data-id="r_tableSpinner"]').removeClass('show'); - this.ui.gotoPage.val(''); - this.ui.gotoPage.parent().removeClass('has-error'); - this.ui.gotoPagebtn.prop("disabled", true); - if (this.includePagination) { - this.renderPagination(); - } - if (this.includeFooterRecords) { - this.renderFooterRecords(this.collection.state); - } - if (this.includeAtlasPagination) { - this.renderAtlasPagination(options); - } - }, this); - - /*This "sort" trigger event is fired when clicked on - 'sortable' header cell (backgrid). - Collection.trigger event was fired because backgrid has - removeCellDirection function (backgrid.js - line no: 2088) - which is invoked when "sort" event is triggered - on collection (backgrid.js - line no: 2081). - removeCellDirection function - removes "ascending" and "descending" - which in turn removes chevrons from every 'sortable' header-cells*/ - this.listenTo(this.collection, "backgrid:sorted", function(column, direction, collection) { - // backgrid:sorted fullCollection trigger required for icon chage - if (this.isApiSorting) { - column.set("direction", direction); - } else { - this.collection.fullCollection.trigger("backgrid:sorted", column, direction, collection) - if (this.includeAtlasTableSorting && this.updateFullCollectionManually) { - this.collection.fullCollection.reset(collection.toJSON(), { silent: true }); - } - } - }, this); - this.listenTo(this, "grid:refresh", function() { - if (this.grid) { - this.grid.trigger("backgrid:refresh"); - } - }); - this.listenTo(this, "grid:refresh:update", function() { - if (this.grid) { - this.grid.trigger("backgrid:refresh"); - if (this.grid.collection) { this.grid.collection.trigger("backgrid:colgroup:updated"); } - } - }); - - // It will show tool tip when td has ellipsis Property - this.listenTo(this.collection, "backgrid:refresh", function() { - /*this.$('.table td').bind('mouseenter', function() { - var $this = $(this); - if (this.offsetWidth < this.scrollWidth && !$this.attr('title')) { - $this.attr('title', $this.text()); - } - });*/ - }, this); - - }, - - /** on render callback */ - onRender: function() { - this.renderTable(); - if (this.includePagination) { - this.renderPagination(); - } - if (this.includeAtlasPagination) { - this.renderAtlasPagination(); - } - if (this.includeFilter) { - this.renderFilter(); - } - if (this.includeFooterRecords) { - this.renderFooterRecords(this.collection.state); - } - if (this.includeColumnManager) { - this.renderColumnManager(); - } - var pageSizeEl = null; - if (this.includePageSize) { - pageSizeEl = this.ui.selectPageSize; - } else if (this.includeAtlasPageSize) { - pageSizeEl = this.ui.showPage; - } - if (pageSizeEl) { - pageSizeEl.select2({ - data: _.sortBy(_.union([25, 50, 100, 150, 200, 250, 300, 350, 400, 450, 500], [this.collection.state.pageSize])), - tags: true, - dropdownCssClass: "number-input", - multiple: false - }); - var val = this.collection.state.pageSize; - if (this.value && this.value.pageLimit) { - val = this.limit; - } - pageSizeEl.val(val).trigger('change', { "skipViewChange": true }); - } - - }, - /** - * show table - */ - renderTable: function() { - var that = this; - this.grid = new Backgrid.Grid(this.gridOpts).on('backgrid:rendered', function() { - that.trigger('backgrid:manual:rendered', this) - }); - if (this.showDefaultTableSorted) { - this.grid.render(); - if (this.collection.fullCollection.length > 1 || this.isApiSorting) { - this.grid.sort(this.sortOpts.sortColumn, this.sortOpts.sortDirection); - } - this.rTableList.show(this.grid); - } else { - this.rTableList.show(this.grid); - } - }, - onShow: function() { - if (this.includeSizeAbleColumns) { - this.renderSizeAbleColumns(); - } - if (this.includeOrderAbleColumns) { - this.renderOrderAbleColumns(); - } - }, - /** - * show pagination buttons(first, last, next, prev and numbers) - */ - renderPagination: function() { - var options = _.extend({ - collection: this.collection, - controls: this.controlOpts - }, this.paginatorOpts); - - // TODO - Debug this part - if (this.rPagination) { - this.rPagination.show(new Backgrid.Extension.Paginator(options)); - } else if (this.regions.rPagination) { - this.$('div[data-id="r_pagination"]').show(new Backgrid.Extension.Paginator(options)); - this.showHideGoToPage(); - } - }, - - renderAtlasPagination: function(options) { - var isFirstPage = this.offset === 0, - dataLength = this.collection.length, - goToPage = this.ui.gotoPage.val(); - - /*Next button check. - It's outside of Previous button else condition - because when user comes from 2 page to 1 page than we need to check next button.*/ - if (dataLength < this.limit) { - this.ui.nextData.attr('disabled', true); - } else { - this.ui.nextData.attr('disabled', false); - } - - if (isFirstPage && (!dataLength || dataLength < this.limit)) { - this.ui.paginationDiv.hide(); - } else { - this.ui.paginationDiv.show(); - } - - // Previous button check.s - if (isFirstPage) { - this.ui.previousData.attr('disabled', true); - this.pageFrom = 1; - this.pageTo = this.limit; - } else { - this.ui.previousData.attr('disabled', false); - } - - if (options && options.next) { - //on next click, adding "1" for showing the another records. - this.pageTo = this.offset + this.limit; - this.pageFrom = this.offset + 1; - } else if (!isFirstPage && options && options.previous) { - this.pageTo = this.pageTo - this.limit; - this.pageFrom = (this.pageTo - this.limit) + 1; - } - if (this.isApiSorting && !this.pageTo && !this.pageFrom) { - this.limit = this.count; - this.pageTo = (this.offset + this.limit); - this.pageFrom = this.offset + 1; - } - this.ui.pageRecordText.html("Showing " + this.collection.length + " records From " + this.pageFrom + " - " + this.pageTo); - this.activePage = Math.round(this.pageTo / this.limit); - this.ui.activePage.attr('title', "Page " + this.activePage); - this.ui.activePage.text(this.activePage); - this.ui.showPage.val(this.limit).trigger('change', { "skipViewChange": true }); - - if (!dataLength && this.offset >= this.limit && ((options && options.next) || goToPage) && (options && !options.fromUrl)) { - /* User clicks on next button and server returns - empty response then disabled the next button without rendering table*/ - - var pageNumber = this.activePage; - if (goToPage) { - pageNumber = goToPage; - this.offset = (this.activePage - 1) * this.limit; - } else { - this.ui.nextData.attr('disabled', true); - } - if (this.value) { - this.value.pageOffset = this.offset; - if (this.triggerUrl) { - this.triggerUrl(); - } - } - Utils.notifyInfo({ - html: true, - content: Messages.search.noRecordForPage + '' + Utils.getNumberSuffix({ number: pageNumber, sup: true }) + ' page' - }); - return; - } - }, - - /** - * show/hide pagination buttons of the grid - */ - showHidePager: function() { - - if (!this.includePagination) { - return; - } - - if (this.collection.state && this.collection.state.totalRecords > this.collection.state.pageSize) { - this.$('div[data-id="r_pagination"]').show(); - } else { - this.$('div[data-id="r_pagination"]').hide(); - } - }, - - showHideGoToPage: function() { - if (this.collection.state.pageSize > this.collection.fullCollection.length) { - this.ui.paginationDiv.hide(); - } else { - this.ui.paginationDiv.show(); - } - }, - - /** - * show/hide filter of the grid - */ - renderFilter: function() { - this.rFilter.show(new Backgrid.Extension.ServerSideFilter({ - collection: this.collection, - name: ['name'], - placeholder: 'plcHldr.searchByResourcePath', - wait: 150 - })); - - setTimeout(function() { - that.$('table').colResizable({ liveDrag: true }); - }, 0); - }, - - /** - * show/hide footer details of the list/collection shown in the grid - */ - renderFooterRecords: function(collectionState) { - var collState = collectionState; - var totalRecords = collState.totalRecords || 0; - var pageStartIndex = totalRecords ? (collState.currentPage * collState.pageSize) : 0; - var pageEndIndex = pageStartIndex + this.collection.length; - this.$('[data-id="r_footerRecords"]').html('
        Showing ' + (totalRecords ? pageStartIndex + 1 : (this.collection.length === 0) ? 0 : 1) + ' - ' + pageEndIndex + '
        '); - return this; - }, - /** - * ColumnManager for the table - */ - renderColumnManager: function() { - if (!this.columns) { - return; - } - var that = this, - $el = this.columnOpts.el || this.$("[data-id='control']"), - colManager = new Backgrid.Extension.ColumnManager(this.columns, this.columnOpts.opts), - // Add control - colVisibilityControl = new Backgrid.Extension.ColumnManagerVisibilityControl(_.extend({ - columnManager: colManager, - }, this.columnOpts.visibilityControlOpts)); - if (!$el.jquery) { - $el = $($el) - } - if (this.columnOpts.el) { - $el.html(colVisibilityControl.render().el); - } else { - $el.append(colVisibilityControl.render().el); - } - - colManager.on("state-changed", function(state) { - that.collection.trigger("state-changed", state); - }); - colManager.on("state-saved", function() { - that.collection.trigger("state-changed"); - }); - }, - renderSizeAbleColumns: function() { - // Add sizeable columns - var that = this, - sizeAbleCol = new Backgrid.Extension.SizeAbleColumns({ - collection: this.collection, - columns: this.columns, - grid: this.getGridObj() - }); - this.$('thead').before(sizeAbleCol.render().el); - - // Add resize handlers - var sizeHandler = new Backgrid.Extension.SizeAbleColumnsHandlers({ - sizeAbleColumns: sizeAbleCol, - // grid: this.getGridObj(), - saveModelWidth: true - }); - this.$('thead').before(sizeHandler.render().el); - - // Listen to resize events - this.columns.on('resize', function(columnModel, newWidth, oldWidth) { - console.log('Resize event on column; name, model, new and old width: ', columnModel.get("name"), columnModel, newWidth, oldWidth); - }); - }, - - renderOrderAbleColumns: function() { - // Add orderable columns - var sizeAbleCol = new Backgrid.Extension.SizeAbleColumns({ - collection: this.collection, - grid: this.getGridObj(), - columns: this.columns - }); - this.$('thead').before(sizeAbleCol.render().el); - var orderHandler = new Backgrid.Extension.OrderableColumns({ - grid: this.getGridObj(), - sizeAbleColumns: sizeAbleCol - }); - this.$('thead').before(orderHandler.render().el); - }, - - /** on close */ - onClose: function() {}, - - /** - * get the Backgrid object - * @return {null} - */ - getGridObj: function() { - if (this.rTableList.currentView) { - return this.rTableList.currentView; - } - return null; - }, - - /** - * handle change event on page size select box - * @param {Object} e event - */ - onPageSizeChange: function(e, options) { - if (!options || !options.skipViewChange) { - var pagesize = $(e.currentTarget).val(); - if (pagesize == 0) { - this.ui.selectPageSize.data('select2').$container.addClass('has-error'); - return; - } else { - this.ui.selectPageSize.data('select2').$container.removeClass('has-error'); - } - this.collection.state.pageSize = parseInt(pagesize, 10); - this.collection.state.currentPage = this.collection.state.firstPage; - this.showHideGoToPage(); - if (this.collection.mode == "client") { - this.collection.fullCollection.reset(this.collection.fullCollection.toJSON()); - } else { - this.collection.fetch({ - sort: false, - reset: true, - cache: false - }); - } - } - }, - /** - atlasNextBtn - **/ - onClicknextData: function() { - this.offset = this.offset + this.limit; - _.extend(this.collection.queryParams, { - offset: this.offset - }); - if (this.value) { - this.value.pageOffset = this.offset; - if (this.triggerUrl) { - this.triggerUrl(); - } - } - if (this.fetchCollection) { - this.fetchCollection({ - next: true - }); - } - }, - /** - atlasPrevBtn - **/ - onClickpreviousData: function() { - this.offset = this.offset - this.limit; - if (this.offset <= -1) { - this.offset = 0; - } - _.extend(this.collection.queryParams, { - offset: this.offset - }); - if (this.value) { - this.value.pageOffset = this.offset; - if (this.triggerUrl) { - this.triggerUrl(); - } - } - if (this.fetchCollection) { - this.fetchCollection({ - previous: true - }); - } - }, - /** - atlasPageLimit - **/ - changePageLimit: function(e, obj) { - if (!obj || (obj && !obj.skipViewChange)) { - var limit = parseInt(this.ui.showPage.val()); - if (limit == 0) { - this.ui.showPage.data('select2').$container.addClass('has-error'); - return; - } else { - this.ui.showPage.data('select2').$container.removeClass('has-error'); - } - this.limit = limit; - this.offset = 0; - if (this.value) { - this.value.pageLimit = this.limit; - this.value.pageOffset = this.offset; - if (this.triggerUrl) { - this.triggerUrl(); - } - } - _.extend(this.collection.queryParams, { limit: this.limit, offset: this.offset }); - this.fetchCollection(); - } - }, - /** - atlasGotoBtn & Local Goto Btn - **/ - gotoPagebtn: function(e) { - var that = this; - var goToPage = parseInt(this.ui.gotoPage.val()); - if (!_.isNaN(goToPage) && ((goToPage == 0) || (this.collection.state.totalPages < goToPage))) { - Utils.notifyInfo({ - content: Messages.search.noRecordForPage + "page " + goToPage - }); - this.ui.gotoPage.val('') - that.ui.gotoPagebtn.attr('disabled', true); - return; - } - if (!(_.isNaN(goToPage) || goToPage <= -1)) { - if (this.collection.mode == "client") { - return this.collection.getPage((goToPage - 1), { - reset: true - }); - } else { - this.offset = (goToPage - 1) * this.limit; - if (this.offset <= -1) { - this.offset = 0; - } - _.extend(this.collection.queryParams, { limit: this.limit, offset: this.offset }); - if (this.offset == (this.pageFrom - 1)) { - Utils.notifyInfo({ - content: Messages.search.onSamePage - }); - } else { - if (this.value) { - this.value.pageOffset = this.offset; - if (this.triggerUrl) { - this.triggerUrl(); - } - } - // this.offset is updated in gotoPagebtn function so use next button calculation. - if (this.fetchCollection) { - this.fetchCollection({ 'next': true }); - } - } - } - } - } - }); - - return FSTableLayout; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/utils/UrlLinks.js b/dashboardv2/public/js/utils/UrlLinks.js deleted file mode 100644 index eb2980c1185..00000000000 --- a/dashboardv2/public/js/utils/UrlLinks.js +++ /dev/null @@ -1,269 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', 'utils/Enums', 'utils/Utils', 'underscore'], function(require, Enums, Utils) { - 'use strict'; - - var UrlLinks = { - apiBaseUrl: Utils.getBaseUrl(window.location.pathname) - }; - _.extend(UrlLinks, { - baseUrl: UrlLinks.apiBaseUrl + '/api/atlas', - baseUrlV2: UrlLinks.apiBaseUrl + '/api/atlas/v2', - typedefsUrl: function() { - return { - defs: this.baseUrlV2 + '/types/typedefs', - def: this.baseUrlV2 + '/types/typedef' - }; - }, - entitiesDefApiUrl: function(name) { - return this.getDefApiUrl('entity', name); - }, - classificationDefApiUrl: function(name) { - return this.getDefApiUrl('classification', name); - }, - businessMetadataDefApiUrl: function(name) { - return this.getDefApiUrl('business_metadata', name); - }, - enumDefApiUrl: function(name) { - return this.getDefApiUrl('enum', name); - }, - metricsApiUrl: function() { - return this.baseUrl + '/admin/metrics' - }, - pendingTaskApiUrl: function() { - return this.baseUrl + '/admin/tasks' - }, - debugMetricsApiUrl: function() { - return this.baseUrl + '/admin/debug/metrics' - }, - migrationStatusApiUrl: function() { - return this.baseUrl + '/admin/status' - }, - rootEntityDefUrl: function(name) { - return this.baseUrlV2 + '/types/entitydef/name/' + name; - }, - rootClassificationDefUrl: function(name) { - return this.baseUrlV2 + '/types/classificationdef/name/' + name; - }, - getDefApiUrl: function(type, name) { - var defApiUrl = this.typedefsUrl(), - defUrl; - if (name) { - defUrl = defApiUrl.def + '/name/' + name; - } else { - defUrl = defApiUrl.defs; - } - if (type) { - return defUrl += '?type=' + type; - } else { - return defUrl; - } - }, - entitiesApiUrl: function(options) { - var entitiesUrl = this.baseUrlV2 + '/entity'; - if (options) { - var guid = options.guid, - associatedGuid = options.associatedGuid, - name = options.name, - minExtInfo = options.minExtInfo; - if (guid && name && associatedGuid) { - return entitiesUrl + '/guid/' + guid + '/classification/' + name + '?associatedEntityGuid=' + associatedGuid; - } else if (guid && name) { - entitiesUrl += '/guid/' + guid + '/classification/' + name; - } else if (guid && !name) { - entitiesUrl += '/guid/' + guid; - } - } - - if (!minExtInfo) { - return entitiesUrl; - } else { - return entitiesUrl += '?minExtInfo=' + (minExtInfo); - } - }, - entityLabelsAPIUrl: function(guid) { - return this.entitiesApiUrl({ guid: guid }) + "/labels"; - }, - entityHeaderApiUrl: function(guid) { - return this.entitiesApiUrl({ guid: guid }) + "/header" - }, - entitiesTraitsApiUrl: function(token) { - if (token) { - return this.baseUrlV2 + '/entity/guid/' + token + '/classifications'; - } else { - // For Multiple Assignment - return this.baseUrlV2 + '/entity/bulk/classification'; - } - }, - entitiesBusinessMetadataApiUrl: function(guid) { - if (guid) { - return this.baseUrlV2 + '/entity/guid/' + guid + '/businessmetadata?isOverwrite=true'; - } - }, - entityCollectionaudit: function(guid) { - return this.baseUrlV2 + '/entity/' + guid + '/audit'; - }, - expimpAudit: function(options) { - var url = this.baseUrl + '/admin/expimp/audit', - queryParam = []; - if (options) { - var serverName = options.serverName, - limit = options.limit, - offset = options.offset; - } - - if (serverName) { - queryParam.push("serverName=" + serverName); - } - if (limit) { - queryParam.push("limit=" + limit); - } - if (offset) { - queryParam.push("offset=" + offset); - } - if (queryParam.length > 0) { - url = url + "?" + queryParam.join("&"); - } - return url; - }, - classicationApiUrl: function(name, guid) { - var typeUrl = this.typedefsUrl(); - if (name) { - return typeUrl.def + '/name/' + name + '?type=classification'; - } else if (guid) { - return typeUrl.def + '/guid/' + guid + '?type=classification'; - } - }, - typesApiUrl: function() { - return this.typedefsUrl().defs + '/headers?excludeInternalTypesAndReferences=true' - }, - lineageApiUrl: function(guid) { - var lineageUrl = this.baseUrlV2 + '/lineage'; - if (guid) { - return lineageUrl + '/' + guid; - } else { - return lineageUrl - } - }, - relationshipApiUrl: function(guid) { - var relationshipUrl = this.baseUrlV2 + '/relationship'; - if (guid) { - return relationshipUrl + '/guid/' + guid + '?extendedInfo=true'; - } else { - return relationshipUrl - } - }, - schemaApiUrl: function(guid) { - var lineageUrl = this.baseUrl + '/lineage'; - if (guid) { - return lineageUrl + '/' + guid + '/schema' - } else { - return lineageUrl - } - }, - searchApiUrl: function(searchtype) { - var searchUrl = this.baseUrlV2 + '/search'; - if (searchtype) { - return searchUrl + '/' + searchtype; - } else { - return searchUrl; - } - }, - saveSearchApiUrl: function(saveSearchType) { - var saveSearchUrl = this.searchApiUrl() + "/saved"; - if (saveSearchType) { - return saveSearchUrl + '/' + saveSearchType; - } else { - return saveSearchUrl; - } - }, - glossaryApiUrl: function(options) { - var guid = options && options.guid, - glossaryUrl = this.baseUrlV2 + '/glossary'; - if (guid) { - return glossaryUrl + '/' + guid; - } else { - return glossaryUrl; - } - }, - glossaryImportTempUrl: function() { - return this.glossaryApiUrl() + '/import/template'; - }, - glossaryImportUrl: function() { - return this.glossaryApiUrl() + '/import'; - }, - businessMetadataImportTempUrl: function() { - return this.entitiesApiUrl() + '/businessmetadata/import/template'; - }, - businessMetadataImportUrl: function() { - return this.entitiesApiUrl() + '/businessmetadata/import'; - }, - apiDocUrl: function() { - return this.apiBaseUrl + '/apidocs/index.html'; - }, - categoryApiUrl: function(options) { - var guid = options && options.guid, - list = options && options.list, - related = options && options.related, - categoryUrl = this.glossaryApiUrl() + '/' + (list ? 'categories' : 'category'); - if (guid) { - if (related) { - return categoryUrl + '/' + guid + "/related"; - } else { - return categoryUrl + '/' + guid; - } - } else { - return categoryUrl; - } - }, - termApiUrl: function(options) { - var guid = options && options.guid, - list = options && options.list, - related = options && options.related, - termUrl = this.glossaryApiUrl() + '/' + (list ? 'terms' : 'term'); - if (guid) { - if (related) { - return termUrl + '/' + guid + "/related"; - } else { - return termUrl + '/' + guid; - } - } else { - return termUrl; - } - }, - termToEntityApiUrl: function(guid) { - var termUrl = this.termApiUrl({ list: true }); - if (guid) { - return termUrl + '/' + guid + '/assignedEntities'; - } - }, - versionApiUrl: function() { - return this.baseUrl + '/admin/version'; - }, - sessionApiUrl: function() { - return this.baseUrl + '/admin/session'; - }, - adminApiUrl: function() { - return this.baseUrl + '/admin/audits'; - } - - }); - - return UrlLinks; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/utils/Utils.js b/dashboardv2/public/js/utils/Utils.js deleted file mode 100644 index f2498d827f5..00000000000 --- a/dashboardv2/public/js/utils/Utils.js +++ /dev/null @@ -1,1225 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', 'utils/Globals', 'pnotify', 'utils/Messages', 'utils/Enums', 'moment', 'store', 'modules/Modal', 'moment-timezone', 'pnotify.buttons', 'pnotify.confirm'], function(require, Globals, pnotify, Messages, Enums, moment, store, Modal) { - 'use strict'; - - var Utils = {}; - var prevNetworkErrorTime = 0; - - Utils.generatePopover = function(options) { - if (options.el) { - var defaultObj = { - placement: 'auto bottom', - html: true, - animation: false, - container: 'body', - sanitize: false - }; - if (options.viewFixedPopover || options.contentClass) { - defaultObj.template = '

        '; - } - return options.el.popover(_.extend(defaultObj, options.popoverOptions)); - } - } - - Utils.getNumberSuffix = function(options) { - if (options && options.number) { - var n = options.number, - s = ["th", "st", "nd", "rd"], - v = n % 100, - suffix = (s[(v - 20) % 10] || s[v] || s[0]); - return n + (options.sup ? '' + suffix + '' : suffix); - } - } - - Utils.generateUUID = function() { - var d = new Date().getTime(); - if (window.performance && typeof window.performance.now === "function") { - d += performance.now(); //use high-precision timer if available - } - var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - var r = (d + Math.random() * 16) % 16 | 0; - d = Math.floor(d / 16); - return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); - }); - return uuid; - }; - Utils.getBaseUrl = function(url) { - return url.replace(/\/[\w-]+.(jsp|html)|\/+$/ig, ''); - }; - Utils.getEntityIconPath = function(options) { - var entityData = options && options.entityData, - serviceType, - status, - typeName, - iconBasePath = Utils.getBaseUrl(window.location.pathname) + Globals.entityImgPath; - if (entityData) { - typeName = entityData.typeName; - serviceType = entityData && entityData.serviceType; - status = entityData && entityData.status; - } - - function getImgPath(imageName) { - return iconBasePath + (Enums.entityStateReadOnly[status] ? "disabled/" + imageName : imageName); - } - - function getDefaultImgPath() { - if (entityData.isProcess) { - if (Enums.entityStateReadOnly[status]) { - return iconBasePath + 'disabled/process.png'; - } else { - return iconBasePath + 'process.png'; - } - } else { - if (Enums.entityStateReadOnly[status]) { - return iconBasePath + 'disabled/table.png'; - } else { - return iconBasePath + 'table.png'; - } - } - } - - if (entityData) { - if (options.errorUrl) { - var isErrorInTypeName = (options.errorUrl && options.errorUrl.match("entity-icon/" + typeName + ".png|disabled/" + typeName + ".png") ? true : false); - if (serviceType && isErrorInTypeName) { - var imageName = serviceType + ".png"; - return getImgPath(imageName); - } else { - return getDefaultImgPath(); - } - } else if (entityData.typeName) { - var imageName = entityData.typeName + ".png"; - return getImgPath(imageName); - } else { - return getDefaultImgPath(); - } - } - } - - pnotify.prototype.options.styling = "fontawesome"; - var notify = function(options) { - return new pnotify(_.extend({ - icon: true, - hide: true, - delay: 3000, - remove: true, - buttons: { - classes: { - closer: 'fa fa-times', - pin_up: 'fa fa-pause', - pin_down: 'fa fa-play' - } - } - }, options)); - } - Utils.notifyInfo = function(options) { - notify({ - type: "info", - text: (options.html ? options.content : _.escape(options.content)) || "Info message." - }); - }; - - Utils.notifyWarn = function(options) { - notify({ - type: "notice", - text: (options.html ? options.content : _.escape(options.content)) || "Info message." - }); - }; - - Utils.notifyError = function(options) { - notify({ - type: "error", - text: (options.html ? options.content : _.escape(options.content)) || "Error occurred." - }); - }; - - Utils.notifySuccess = function(options) { - notify({ - type: "success", - text: (options.html ? options.content : _.escape(options.content)) || "Error occurred." - }); - }; - - Utils.notifyConfirm = function(options) { - var modal = {}; - if (options && options.modal) { - var myStack = { "dir1": "down", "dir2": "right", "push": "top", 'modal': true }; - modal['addclass'] = 'stack-modal ' + (options.modalClass ? modalClass : 'width-500'); - modal['stack'] = myStack; - } - notify(_.extend({ - title: 'Confirmation', - hide: false, - confirm: { - confirm: true, - buttons: [{ - text: options.cancelText || 'Cancel', - addClass: 'btn-action btn-md cancel', - click: function(notice) { - options.cancel(notice); - notice.remove(); - } - }, - { - text: options.okText || 'Ok', - addClass: 'btn-atlas btn-md ok', - click: function(notice) { - if (options.ok) { - options.ok($.extend({}, notice, { - hideButtonLoader: function() { - notice.container.find("button.ok").hideButtonLoader(); - }, - showButtonLoader: function() { - notice.container.find("button.ok").showButtonLoader(); - } - })); - } - if (options.okShowLoader) { - notice.container.find("button.ok").showButtonLoader(); - } - if (options.okCloses !== false) { - notice.remove(); - } - } - } - ] - }, - buttons: { - closer: false, - sticker: false - }, - history: { - history: false - } - - }, modal, options)).get().on('pnotify.confirm', function() { - if (options.ok) { - options.ok(); - } - }).on('pnotify.cancel', function() { - if (options.cancel) { - options.cancel(); - } - }); - } - Utils.defaultErrorHandler = function(model, error, options) { - var skipDefaultError = null, - defaultErrorMessage = null; - if (options) { - skipDefaultError = options.skipDefaultError; - defaultErrorMessage = options.defaultErrorMessage; - } - var redirectToLoginPage = function() { - Utils.localStorage.setValue("last_ui_load", "v1"); - window.location = 'login.jsp'; - } - if (error && error.status) { - if (error.status == 401) { - redirectToLoginPage(); - } else if (error.status == 419) { - redirectToLoginPage(); - } else if (error.status == 403) { - Utils.serverErrorHandler(error, "You are not authorized"); - } else if (error.status == "0" && error.statusText != "abort") { - var diffTime = (new Date().getTime() - prevNetworkErrorTime); - if (diffTime > 3000) { - prevNetworkErrorTime = new Date().getTime(); - Utils.notifyError({ - content: "Network Connection Failure : " + - "It seems you are not connected to the internet. Please check your internet connection and try again" - }); - } - } else if (skipDefaultError !== true) { - Utils.serverErrorHandler(error, defaultErrorMessage); - } - } else if (skipDefaultError !== true) { - Utils.serverErrorHandler(error, defaultErrorMessage); - } - }; - Utils.serverErrorHandler = function(response, defaultErrorMessage) { - var responseJSON = response ? response.responseJSON : response, - message = defaultErrorMessage ? defaultErrorMessage : Messages.defaultErrorMessage - if (response && responseJSON) { - message = responseJSON.errorMessage || responseJSON.message || responseJSON.error || message - } - var existingError = $(".ui-pnotify-container.alert-danger .ui-pnotify-text").text(); - if (existingError !== message) { - Utils.notifyError({ - content: message - }); - } - }; - Utils.cookie = { - setValue: function(cname, cvalue) { - document.cookie = cname + "=" + cvalue + "; "; - }, - getValue: function(findString) { - var search = findString + "="; - var ca = document.cookie.split(';'); - for (var i = 0; i < ca.length; i++) { - var c = ca[i]; - while (c.charAt(0) == ' ') c = c.substring(1); - if (c.indexOf(name) == 0) { - return c.substring(name.length, c.length); - } - } - return ""; - } - }; - Utils.localStorage = function() { - this.setValue = function() { - localStorage.setItem(arguments[0], arguments[1]); - } - this.getValue = function(key, value) { - var keyValue = localStorage.getItem(key); - if ((!keyValue || keyValue == "undefined") && (value != undefined)) { - return this.setLocalStorage(key, value); - } else { - if (keyValue === "" || keyValue === "undefined" || keyValue === "null") { - return null; - } else { - return keyValue; - } - - } - } - this.removeValue = function() { - localStorage.removeItem(arguments[0]); - } - if (typeof(Storage) === "undefined") { - _.extend(this, Utils.cookie); - console.log('Sorry! No Web Storage support'); - } - } - Utils.localStorage = new Utils.localStorage(); - - Utils.setUrl = function(options) { - if (options) { - if (options.mergeBrowserUrl) { - var param = Utils.getUrlState.getQueryParams(); - if (param) { - options.urlParams = $.extend(param, options.urlParams); - } - } - if (options.urlParams) { - var urlParams = "?"; - _.each(options.urlParams, function(value, key, obj) { - if (value) { - value = encodeURIComponent(String(value)); - urlParams += key + "=" + value + "&"; - } - }); - urlParams = urlParams.slice(0, -1); - options.url += urlParams; - } - if (options.updateTabState) { - var urlUpdate = { - stateChanged: true - }; - if (Utils.getUrlState.isTagTab(options.url)) { - urlUpdate['tagUrl'] = options.url; - } else if (Utils.getUrlState.isSearchTab(options.url)) { - urlUpdate['searchUrl'] = options.url; - } else if (Utils.getUrlState.isGlossaryTab(options.url)) { - urlUpdate['glossaryUrl'] = options.url; - } else if (Utils.getUrlState.isAdministratorTab(options.url)) { - urlUpdate['administratorUrl'] = options.url; - } else if (Utils.getUrlState.isDebugMetricsTab(options.url)) { - urlUpdate['debugMetricsUrl'] = options.url; - } - $.extend(Globals.saveApplicationState.tabState, urlUpdate); - } - Backbone.history.navigate(options.url, { trigger: options.trigger != undefined ? options.trigger : true }); - } - }; - - Utils.getUrlState = { - getQueryUrl: function(url) { - var hashValue = window.location.hash; - if (url) { - hashValue = url; - } - return { - firstValue: hashValue.split('/')[1], - hash: hashValue, - queyParams: hashValue.split("?"), - lastValue: hashValue.split('/')[hashValue.split('/').length - 1] - } - }, - checkTabUrl: function(options) { - var url = options && options.url, - matchString = options && options.matchString, - quey = this.getQueryUrl(url); - return quey.firstValue == matchString || quey.queyParams[0] == "#!/" + matchString; - }, - isInitial: function() { - return this.getQueryUrl().firstValue == undefined; - }, - isTagTab: function(url) { - return this.checkTabUrl({ - url: url, - matchString: "tag" - }); - }, - isBSDetail: function(url) { - var quey = this.getQueryUrl(url); - return (quey.queyParams[0].indexOf("administrator/businessMetadata")) > -1 ? true : false; - }, - isSearchTab: function(url) { - return this.checkTabUrl({ - url: url, - matchString: "search" - }); - }, - isAdministratorTab: function(url) { - return this.checkTabUrl({ - url: url, - matchString: "administrator" - }); - }, - isDebugMetricsTab: function(url) { - return this.checkTabUrl({ - url: url, - matchString: "debugMetrics" - }); - }, - isGlossaryTab: function(url) { - return this.checkTabUrl({ - url: url, - matchString: "glossary" - }); - }, - isDetailPage: function(url) { - return this.checkTabUrl({ - url: url, - matchString: "detailPage" - }); - }, - getLastValue: function() { - return this.getQueryUrl().lastValue; - }, - getFirstValue: function() { - return this.getQueryUrl().firstValue; - }, - getQueryParams: function(url) { - var qs = this.getQueryUrl(url).queyParams[1]; - if (typeof qs == "string") { - qs = qs.split('+').join(' '); - var params = {}, - tokens, - re = /[?&]?([^=]+)=([^&]*)/g; - while (tokens = re.exec(qs)) { - params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]); - } - return params; - } - }, - getKeyValue: function(key) { - var paramsObj = this.getQueryParams(); - if (key.length) { - var values = []; - _.each(key, function(objKey) { - var obj = {}; - obj[objKey] = paramsObj[objKey] - values.push(obj); - return values; - }) - } else { - return paramsObj[key]; - } - } - } - Utils.getName = function() { - return Utils.extractKeyValueFromEntity.apply(this, arguments).name; - } - Utils.getNameWithProperties = function() { - return Utils.extractKeyValueFromEntity.apply(this, arguments); - } - Utils.extractKeyValueFromEntity = function() { - var collectionJSON = arguments[0], - priorityAttribute = arguments[1], - skipAttribute = arguments[2], - returnObj = { - name: '-', - found: true, - key: null - } - if (collectionJSON) { - if (collectionJSON.attributes && collectionJSON.attributes[priorityAttribute]) { - returnObj.name = _.escape(collectionJSON.attributes[priorityAttribute]); - returnObj.key = priorityAttribute; - return returnObj; - } - if (collectionJSON[priorityAttribute]) { - returnObj.name = _.escape(collectionJSON[priorityAttribute]); - returnObj.key = priorityAttribute; - return returnObj; - } - if (collectionJSON.attributes) { - if (collectionJSON.attributes.name) { - returnObj.name = _.escape(collectionJSON.attributes.name); - returnObj.key = 'name'; - return returnObj; - } - if (collectionJSON.attributes.displayName) { - returnObj.name = _.escape(collectionJSON.attributes.displayName); - returnObj.key = 'displayName'; - return returnObj; - } - if (collectionJSON.attributes.qualifiedName) { - returnObj.name = _.escape(collectionJSON.attributes.qualifiedName); - returnObj.key = 'qualifiedName'; - return returnObj; - } - if (collectionJSON.attributes.displayText) { - returnObj.name = _.escape(collectionJSON.attributes.displayText); - returnObj.key = 'displayText'; - return returnObj; - } - if (collectionJSON.attributes.guid) { - returnObj.name = _.escape(collectionJSON.attributes.guid); - returnObj.key = 'guid'; - return returnObj; - } - if (collectionJSON.attributes.id) { - if (_.isObject(collectionJSON.attributes.id)) { - if (collectionJSON.id.id) { - returnObj.name = _.escape(collectionJSON.attributes.id.id); - } - } else { - returnObj.name = _.escape(collectionJSON.attributes.id); - } - returnObj.key = 'id'; - return returnObj; - } - } - if (collectionJSON.name) { - returnObj.name = _.escape(collectionJSON.name); - returnObj.key = 'name'; - return returnObj; - } - if (collectionJSON.displayName) { - returnObj.name = _.escape(collectionJSON.displayName); - returnObj.key = 'displayName'; - return returnObj; - } - if (collectionJSON.qualifiedName) { - returnObj.name = _.escape(collectionJSON.qualifiedName); - returnObj.key = 'qualifiedName'; - return returnObj; - } - if (collectionJSON.displayText) { - returnObj.name = _.escape(collectionJSON.displayText); - returnObj.key = 'displayText'; - return returnObj; - } - if (collectionJSON.guid) { - returnObj.name = _.escape(collectionJSON.guid); - returnObj.key = 'guid'; - return returnObj; - } - if (collectionJSON.id) { - if (_.isObject(collectionJSON.id)) { - if (collectionJSON.id.id) { - returnObj.name = _.escape(collectionJSON.id.id); - } - } else { - returnObj.name = _.escape(collectionJSON.id); - } - returnObj.key = 'id'; - return returnObj; - } - } - returnObj.found = false; - if (skipAttribute && returnObj.key == skipAttribute) { - return { - name: '-', - found: true, - key: null - } - } else { - return returnObj; - } - - } - - Utils.backButtonClick = function() { - var queryParams = Utils.getUrlState.getQueryParams(), - urlPath = "searchUrl"; - if (queryParams && queryParams.from) { - if (queryParams.from == "classification") { - urlPath = "tagUrl"; - } else if (queryParams.from == "glossary") { - urlPath = "glossaryUrl"; - } else if (queryParams.from == "bm") { - urlPath = "administratorUrl"; - } - } - Utils.setUrl({ - url: Globals.saveApplicationState.tabState[urlPath], - mergeBrowserUrl: false, - trigger: true, - updateTabState: true - }); - } - - Utils.showTitleLoader = function(loaderEl, titleBoxEl) { - loaderEl.css ? loaderEl.css({ - 'display': 'block', - 'position': 'relative', - 'height': '85px', - 'marginTop': '85px', - 'marginLeft': '50%', - 'left': '0%' - }) : null; - titleBoxEl.hide ? titleBoxEl.hide() : null; - } - Utils.hideTitleLoader = function(loaderEl, titleBoxEl) { - loaderEl.hide ? loaderEl.hide() : null; - titleBoxEl.fadeIn ? titleBoxEl.fadeIn() : null; - } - Utils.findAndMergeRefEntity = function(options) { - var attributeObject = options.attributeObject, - referredEntities = options.referredEntities - var mergeObject = function(obj) { - if (obj) { - if (obj.attributes) { - Utils.findAndMergeRefEntity({ - "attributeObject": obj.attributes, - "referredEntities": referredEntities - }); - } else if (referredEntities[obj.guid]) { - _.extend(obj, referredEntities[obj.guid]); - } - } - } - if (attributeObject && referredEntities) { - _.each(attributeObject, function(obj, key) { - if (_.isObject(obj)) { - if (_.isArray(obj)) { - _.each(obj, function(value) { - mergeObject(value); - }); - } else { - mergeObject(obj); - } - } - }); - } - } - - Utils.findAndMergeRelationShipEntity = function(options) { - var attributeObject = options.attributeObject, - relationshipAttributes = options.relationshipAttributes; - _.each(attributeObject, function(val, key) { - var attributVal = val; - if (relationshipAttributes && relationshipAttributes[key]) { - var relationShipVal = relationshipAttributes[key]; - if (_.isObject(val)) { - if (_.isArray(val)) { - _.each(val, function(attr) { - if (attr && attr.attributes === undefined) { - var entityFound = _.find(relationShipVal, { guid: attr.guid }); - if (entityFound) { - attr.attributes = _.omit(entityFound, 'typeName', 'guid', 'entityStatus'); - attr.status = entityFound.entityStatus; - } - } - }); - } else if (relationShipVal && val.attributes === undefined) { - val.attributes = _.omit(relationShipVal, 'typeName', 'guid', 'entityStatus'); - val.status = relationShipVal.entityStatus; - } - } - } - }) - } - - Utils.getNestedSuperTypes = function(options) { - var data = options.data, - collection = options.collection, - superTypes = []; - - var getData = function(data, collection) { - if (data) { - superTypes = superTypes.concat(data.superTypes); - if (data.superTypes && data.superTypes.length) { - _.each(data.superTypes, function(superTypeName) { - if (collection.fullCollection) { - var collectionData = collection.fullCollection.findWhere({ name: superTypeName }).toJSON(); - } else { - var collectionData = collection.findWhere({ name: superTypeName }).toJSON(); - } - getData(collectionData, collection); - }); - } - } - } - getData(data, collection); - return _.uniq(superTypes); - } - Utils.getNestedSuperTypeObj = function(options) { - var mainData = options.data, - collection = options.collection, - attrMerge = options.attrMerge, - seperateRelatioshipAttr = options.seperateRelatioshipAttr || false, - mergeRelationAttributes = options.mergeRelationAttributes || (seperateRelatioshipAttr ? false : true); - - if (mergeRelationAttributes && seperateRelatioshipAttr) { - throw "Both mergeRelationAttributes & seperateRelatioshipAttr cannot be true!" - } - var attributeDefs = {}; - if (attrMerge && !seperateRelatioshipAttr) { - attributeDefs = []; - } else if (options.attrMerge && seperateRelatioshipAttr) { - attributeDefs = { - attributeDefs: [], - relationshipAttributeDefs: [] - } - } - var getRelationshipAttributeDef = function(data) { - return _.filter( - data.relationshipAttributeDefs, - function(obj, key) { - return obj; - }) - } - var getData = function(data, collection) { - if (options.attrMerge) { - if (seperateRelatioshipAttr) { - attributeDefs.attributeDefs = attributeDefs.attributeDefs.concat(data.attributeDefs); - attributeDefs.relationshipAttributeDefs = attributeDefs.relationshipAttributeDefs.concat(getRelationshipAttributeDef(data)); - } else { - attributeDefs = attributeDefs.concat(data.attributeDefs); - if (mergeRelationAttributes) { - attributeDefs = attributeDefs.concat(getRelationshipAttributeDef(data)); - } - } - } else { - if (attributeDefs[data.name]) { - attributeDefs[data.name] = _.toArrayifObject(attributeDefs[data.name]).concat(data.attributeDefs); - } else { - if (seperateRelatioshipAttr) { - attributeDefs[data.name] = { - attributeDefs: data.attributeDefs, - relationshipAttributeDefs: data.relationshipAttributeDefs - }; - } else { - attributeDefs[data.name] = data.attributeDefs; - if (mergeRelationAttributes) { - attributeDefs[data.name] = _.toArrayifObject(attributeDefs[data.name]).concat(getRelationshipAttributeDef(data)); - } - } - } - } - if (data.superTypes && data.superTypes.length) { - _.each(data.superTypes, function(superTypeName) { - if (collection.fullCollection) { - var collectionData = collection.fullCollection.findWhere({ name: superTypeName }); - } else { - var collectionData = collection.findWhere({ name: superTypeName }); - } - collectionData = collectionData && collectionData.toJSON ? collectionData.toJSON() : collectionData; - if (collectionData) { - return getData(collectionData, collection); - } else { - return; - } - }); - } - } - getData(mainData, collection); - if (attrMerge) { - if (seperateRelatioshipAttr) { - attributeDefs = { - attributeDefs: _.uniq(_.sortBy(attributeDefs.attributeDefs, 'name'), true, function(obj) { - return obj.name - }), - relationshipAttributeDefs: _.uniq(_.sortBy(attributeDefs.relationshipAttributeDefs, 'name'), true, function(obj) { - return (obj.name + obj.relationshipTypeName) - }) - } - } else { - attributeDefs = _.uniq(_.sortBy(attributeDefs, 'name'), true, function(obj) { - if (obj.relationshipTypeName) { - return (obj.name + obj.relationshipTypeName) - } else { - return (obj.name) - } - }); - } - } - return attributeDefs; - } - - Utils.getProfileTabType = function(profileData, skipData) { - var parseData = profileData.distributionData; - if (_.isString(parseData)) { - parseData = JSON.parse(parseData); - } - var createData = function(type) { - var orderValue = [], - sort = false; - if (type === "date") { - var dateObj = {}; - _.keys(parseData).map(function(key) { - var splitValue = key.split(":"); - if (!dateObj[splitValue[0]]) { - dateObj[splitValue[0]] = { - value: splitValue[0], - monthlyCounts: {}, - totalCount: 0 // use when count is null - } - } - if (dateObj[splitValue[0]] && splitValue[1] == "count") { - dateObj[splitValue[0]].count = parseData[key]; - } - if (dateObj[splitValue[0]] && splitValue[1] !== "count") { - dateObj[splitValue[0]].monthlyCounts[splitValue[1]] = parseData[key]; - if (!dateObj[splitValue[0]].count) { - dateObj[splitValue[0]].totalCount += parseData[key] - } - } - }); - return _.toArray(dateObj).map(function(obj) { - if (!obj.count && obj.totalCount) { - obj.count = obj.totalCount - } - return obj - }); - } else { - var data = []; - if (profileData.distributionKeyOrder) { - orderValue = profileData.distributionKeyOrder; - } else { - sort = true; - orderValue = _.keys(parseData); - } - _.each(orderValue, function(key) { - if (parseData[key]) { - data.push({ - value: key, - count: parseData[key] - }); - } - }); - if (sort) { - data = _.sortBy(data, function(o) { - return o.value.toLowerCase() - }); - } - return data; - } - } - if (profileData && profileData.distributionType) { - if (profileData.distributionType === "count-frequency") { - return { - type: "string", - label: Enums.profileTabType[profileData.distributionType], - actualObj: !skipData ? createData("string") : null, - xAxisLabel: "FREQUENCY", - yAxisLabel: "COUNT" - } - } else if (profileData.distributionType === "decile-frequency") { - return { - label: Enums.profileTabType[profileData.distributionType], - type: "numeric", - xAxisLabel: "DECILE RANGE", - actualObj: !skipData ? createData("numeric") : null, - yAxisLabel: "FREQUENCY" - } - } else if (profileData.distributionType === "annual") { - return { - label: Enums.profileTabType[profileData.distributionType], - type: "date", - xAxisLabel: "", - actualObj: !skipData ? createData("date") : null, - yAxisLabel: "COUNT" - } - } - } - } - - Utils.isUrl = function(url) { - var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/ - return regexp.test(url); - } - - Utils.JSONPrettyPrint = function(obj, getValue) { - var replacer = function(match, pIndent, pKey, pVal, pEnd) { - var key = ''; - var val = ''; - var str = ''; - var r = pIndent || ''; - if (pKey) - r = r + key + pKey.replace(/[": ]/g, '') + ': '; - if (pVal) - r = r + (pVal[0] == '"' ? str : val) + getValue(pVal) + ''; - return r + (pEnd || ''); - }, - jsonLine = /^( *)("[\w]+": )?("[^"]*"|[\w.+-]*)?([,[{])?$/mg; - if (obj && _.isObject(obj)) { - return JSON.stringify(obj, null, 3) - .replace(/&/g, '&').replace(/\\"/g, '"') - .replace(//g, '>') - .replace(jsonLine, replacer); - } else { - return {}; - } - }; - - $.fn.toggleAttribute = function(attributeName, firstString, secondString) { - if (this.attr(attributeName) == firstString) { - this.attr(attributeName, secondString); - } else { - this.attr(attributeName, firstString); - } - } - - Utils.millisecondsToTime = function(duration) { - var milliseconds = parseInt((duration % 1000) / 100), - seconds = parseInt((duration / 1000) % 60), - minutes = parseInt((duration / (1000 * 60)) % 60), - hours = parseInt((duration / (1000 * 60 * 60)) % 24); - - hours = (hours < 10) ? "0" + hours : hours; - minutes = (minutes < 10) ? "0" + minutes : minutes; - seconds = (seconds < 10) ? "0" + seconds : seconds; - - return hours + ":" + minutes + ":" + seconds + "." + milliseconds; - } - Utils.togglePropertyRelationshipTableEmptyValues = function(object) { - var inputSelector = object.inputType, - tableEl = object.tableEl; - if (inputSelector.prop('checked') == true) { - tableEl.removeClass('hide-empty-value'); - } else { - tableEl.addClass('hide-empty-value'); - } - } - $.fn.showButtonLoader = function() { - $(this).attr("disabled", "true").addClass('button-loader'); - $(this).siblings("button.cancel").prop("disabled", true); - } - $.fn.hideButtonLoader = function() { - $(this).removeClass('button-loader').removeAttr("disabled"); - $(this).siblings("button.cancel").prop("disabled", false); - } - Utils.formatDate = function(options) { - var dateValue = null, - dateFormat = Globals.dateTimeFormat, - isValidDate = false; - if (options && options.date) { - dateValue = options.date; - if (dateValue !== "-") { - dateValue = parseInt(dateValue); - if (_.isNaN(dateValue)) { - dateValue = options.date; - } - dateValue = moment(dateValue); - if (dateValue._isValid) { - isValidDate = true; - dateValue = dateValue.format(dateFormat); - } - } - } - if (dateValue !== "-") { - if (isValidDate === false && options && options.defaultDate !== false) { - dateValue = moment().format(dateFormat); - } - if (Globals.isTimezoneFormatEnabled) { - if (!options || options && options.zone !== false) { - dateValue += " (" + moment.tz(moment.tz.guess()).zoneAbbr() + ")"; - } - } - } - return dateValue; - } - //------------------------------------------------idleTimeout----------------------------- - $.fn.idleTimeout = function(userRuntimeConfig) { - - //############################## - //## Public Configuration Variables - //############################## - var defaultConfig = { - redirectUrl: Utils.getBaseUrl(window.location.pathname) + '/index.html?action=timeout', // redirect to this url on logout. Set to "redirectUrl: false" to disable redirect - - // idle settings - idleTimeLimit: Globals.idealTimeoutSeconds, // 'No activity' time limit in seconds. 1200 = 20 Minutes - idleCheckHeartbeat: 2, // Frequency to check for idle timeouts in seconds - - // optional custom callback to perform before logout - customCallback: false, // set to false for no customCallback - // customCallback: function () { // define optional custom js function - // perform custom action before logout - // }, - - // configure which activity events to detect - // http://www.quirksmode.org/dom/events/ - // https://developer.mozilla.org/en-US/docs/Web/Reference/Events - activityEvents: 'click keypress scroll wheel mousewheel mousemove', // separate each event with a space - - // warning dialog box configuration - enableDialog: true, // set to false for logout without warning dialog - dialogDisplayLimit: 10, // Time to display the warning dialog before logout (and optional callback) in seconds. 180 = 3 Minutes - dialogTitle: 'Your session is about to expire!', // also displays on browser title bar - dialogText: 'Your session is about to expire.', - dialogTimeRemaining: 'You will be logged out in ', - dialogStayLoggedInButton: 'Stay Logged In', - dialogLogOutNowButton: 'Logout', - - // error message if https://github.com/marcuswestin/store.js not enabled - errorAlertMessage: 'Please disable "Private Mode", or upgrade to a modern browser. Or perhaps a dependent file missing. Please see: https://github.com/marcuswestin/store.js', - - // server-side session keep-alive timer - sessionKeepAliveTimer: 600, // ping the server at this interval in seconds. 600 = 10 Minutes. Set to false to disable pings - sessionKeepAliveUrl: window.location.href // set URL to ping - does not apply if sessionKeepAliveTimer: false - }, - - //############################## - //## Private Variables - //############################## - currentConfig = $.extend(defaultConfig, userRuntimeConfig), // merge default and user runtime configuration - origTitle = document.title, // save original browser title - activityDetector, - startKeepSessionAlive, stopKeepSessionAlive, keepSession, keepAlivePing, // session keep alive - idleTimer, remainingTimer, checkIdleTimeout, checkIdleTimeoutLoop, startIdleTimer, stopIdleTimer, // idle timer - openWarningDialog, dialogTimer, checkDialogTimeout, startDialogTimer, stopDialogTimer, isDialogOpen, destroyWarningDialog, countdownDisplay, // warning dialog - logoutUser; - - //############################## - //## Public Functions - //############################## - // trigger a manual user logout - // use this code snippet on your site's Logout button: $.fn.idleTimeout().logout(); - this.logout = function() { - store.set('idleTimerLoggedOut', true); - }; - - //############################## - //## Private Functions - //############################## - - //----------- KEEP SESSION ALIVE FUNCTIONS --------------// - startKeepSessionAlive = function() { - - keepSession = function() { - $.get(currentConfig.sessionKeepAliveUrl); - startKeepSessionAlive(); - }; - - keepAlivePing = setTimeout(keepSession, (currentConfig.sessionKeepAliveTimer * 1000)); - }; - - stopKeepSessionAlive = function() { - clearTimeout(keepAlivePing); - }; - - //----------- ACTIVITY DETECTION FUNCTION --------------// - activityDetector = function() { - - $('body').on(currentConfig.activityEvents, function() { - - if (!currentConfig.enableDialog || (currentConfig.enableDialog && isDialogOpen() !== true)) { - startIdleTimer(); - $('#activity').effect('shake'); // added for demonstration page - } - }); - }; - - //----------- IDLE TIMER FUNCTIONS --------------// - checkIdleTimeout = function() { - - var timeIdleTimeout = (store.get('idleTimerLastActivity') + (currentConfig.idleTimeLimit * 1000)); - - if ($.now() > timeIdleTimeout) { - - if (!currentConfig.enableDialog) { // warning dialog is disabled - logoutUser(); // immediately log out user when user is idle for idleTimeLimit - } else if (currentConfig.enableDialog && isDialogOpen() !== true) { - openWarningDialog(); - startDialogTimer(); // start timing the warning dialog - } - } else if (store.get('idleTimerLoggedOut') === true) { //a 'manual' user logout? - logoutUser(); - } else { - - if (currentConfig.enableDialog && isDialogOpen() === true) { - destroyWarningDialog(); - stopDialogTimer(); - } - } - }; - - startIdleTimer = function() { - stopIdleTimer(); - store.set('idleTimerLastActivity', $.now()); - checkIdleTimeoutLoop(); - }; - - checkIdleTimeoutLoop = function() { - checkIdleTimeout(); - idleTimer = setTimeout(checkIdleTimeoutLoop, (currentConfig.idleCheckHeartbeat * 1000)); - }; - - stopIdleTimer = function() { - clearTimeout(idleTimer); - }; - - //----------- WARNING DIALOG FUNCTIONS --------------// - openWarningDialog = function() { - - - var dialogContent = "

        " + currentConfig.dialogText + "

        " + currentConfig.dialogTimeRemaining + ":

        secs.

        "; - - var that = this, - modalObj = { - title: currentConfig.dialogTitle, - htmlContent: dialogContent, - okText: "Stay Signed-in", - cancelText: 'Logout', - mainClass: 'modal-lg', - allowCancel: true, - okCloses: false, - escape: false, - cancellable: true, - width: "500px", - mainClass: "ideal-timeout" - }; - var modal = new Modal(modalObj); - modal.open(); - modal.on('ok', function() { - if (userRuntimeConfig && userRuntimeConfig.onModalKeepAlive) { - userRuntimeConfig.onModalKeepAlive(); //hit session API - } - destroyWarningDialog(); - modal.close(); - stopDialogTimer(); - startIdleTimer(); - CommonViewFunction.userDataFetch({ - url: UrlLinks.sessionApiUrl() - }) - - }); - modal.on('closeModal', function() { - logoutUser(); - }); - - countdownDisplay(); - - // document.title = currentConfig.dialogTitle; - - if (currentConfig.sessionKeepAliveTimer) { - stopKeepSessionAlive(); - } - }; - - checkDialogTimeout = function() { - var timeDialogTimeout = (store.get('idleTimerLastActivity') + (currentConfig.idleTimeLimit * 1000) + (currentConfig.dialogDisplayLimit * 1000)); - - if (($.now() > timeDialogTimeout) || (store.get('idleTimerLoggedOut') === true)) { - logoutUser(); - } - }; - - startDialogTimer = function() { - dialogTimer = setInterval(checkDialogTimeout, (currentConfig.idleCheckHeartbeat * 1000)); - }; - - stopDialogTimer = function() { - clearInterval(dialogTimer); - clearInterval(remainingTimer); - }; - - isDialogOpen = function() { - var dialogOpen = $("#idletimer_warning_dialog").is(":visible"); - - if (dialogOpen === true) { - return true; - } - return false; - }; - - destroyWarningDialog = function() { - if (currentConfig.sessionKeepAliveTimer) { - startKeepSessionAlive(); - } - }; - - countdownDisplay = function() { - var dialogDisplaySeconds = currentConfig.dialogDisplayLimit, - mins, secs; - - remainingTimer = setInterval(function() { - mins = Math.floor(dialogDisplaySeconds / 60); // minutes - if (mins < 10) { mins = '0' + mins; } - secs = dialogDisplaySeconds - (mins * 60); // seconds - if (secs < 10) { secs = '0' + secs; } - $('#countdownDisplay').html(mins + ':' + secs); - dialogDisplaySeconds -= 1; - }, 1000); - }; - - //----------- LOGOUT USER FUNCTION --------------// - logoutUser = function() { - store.set('idleTimerLoggedOut', true); - - if (currentConfig.sessionKeepAliveTimer) { - stopKeepSessionAlive(); - } - - if (currentConfig.customCallback) { - currentConfig.customCallback(); - } - - if (currentConfig.redirectUrl) { - window.location.href = currentConfig.redirectUrl; - } - }; - - //############################### - // Build & Return the instance of the item as a plugin - // This is your construct. - //############################### - return this.each(function() { - - if (store.enabled) { - - store.set('idleTimerLastActivity', $.now()); - store.set('idleTimerLoggedOut', false); - - activityDetector(); - - if (currentConfig.sessionKeepAliveTimer) { - startKeepSessionAlive(); - } - - startIdleTimer(); - - } else { - alert(currentConfig.errorAlertMessage); - } - - }); - }; - - //------------------------------------------------ - return Utils; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/administrator/AdministratorLayoutView.js b/dashboardv2/public/js/views/administrator/AdministratorLayoutView.js deleted file mode 100644 index 7354ca6b9d7..00000000000 --- a/dashboardv2/public/js/views/administrator/AdministratorLayoutView.js +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/administrator/AdministratorLayoutView_tmpl', - 'collection/VEntityList', - 'models/VSearch', - 'utils/Utils', - 'utils/Enums', - 'utils/UrlLinks', - 'utils/CommonViewFunction' -], function(require, Backbone, AdministratorLayoutView_tmpl, VEntityList, VSearch, Utils, Enums, UrlLinks, CommonViewFunction) { - 'use strict'; - - var AdministratorLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends AuditTableLayoutView */ - { - _viewName: 'AdministratorLayoutView', - - template: AdministratorLayoutView_tmpl, - - /** Layout sub regions */ - regions: { - RBusinessMetadataTableLayoutView: "#r_businessMetadataTableLayoutView", - REnumTableLayoutView: '#r_enumTableLayoutView', - RAdminTableLayoutView: '#r_adminTableLayoutView', - RTypeSystemTreeLayoutView: '#r_typeSystemTreeLayoutView', - - }, - - /** ui selector cache */ - ui: { - tablist: '[data-id="tab-list"] li' - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.tablist] = function(e) { - var tabValue = $(e.currentTarget).attr('role'); - Utils.setUrl({ - url: Utils.getUrlState.getQueryUrl().queyParams[0], - urlParams: { tabActive: tabValue || 'properties' }, - mergeBrowserUrl: false, - trigger: false, - updateTabState: true - }); - - }; - - return events; - }, - /** - * intialize a new AuditTableLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'value', 'entityDefCollection', 'businessMetadataDefCollection', 'enumDefCollection', 'searchTableFilters')); - - }, - onShow: function() { - if (this.value && this.value.tabActive) { - this.$('.nav.nav-tabs').find('[role="' + this.value.tabActive + '"]').addClass('active').siblings().removeClass('active'); - this.$('.tab-content').find('[role="' + this.value.tabActive + '"]').addClass('active').siblings().removeClass('active'); - $("html, body").animate({ scrollTop: (this.$('.tab-content').offset().top + 1200) }, 1000); - } - }, - bindEvents: function() { - this.renderEnumLayoutView(); - this.renderAdminLayoutView(); - this.renderTypeSystemTreeLayoutView(); - }, - onRender: function() { - this.renderBusinessMetadataLayoutView(); - this.bindEvents(); - }, - renderBusinessMetadataLayoutView: function(obj) { - var that = this; - require(['views/business_metadata/BusinessMetadataTableLayoutView'], function(BusinessMetadataTableLayoutView) { - that.RBusinessMetadataTableLayoutView.show(new BusinessMetadataTableLayoutView({ businessMetadataDefCollection: that.businessMetadataDefCollection, entityDefCollection: that.entityDefCollection })); - }); - }, - renderEnumLayoutView: function(obj) { - var that = this; - require(["views/business_metadata/EnumCreateUpdateItemView"], function(EnumCreateUpdateItemView) { - var view = new EnumCreateUpdateItemView({ - enumDefCollection: that.enumDefCollection, - businessMetadataDefCollection: that.businessMetadataDefCollection - }); - that.REnumTableLayoutView.show(view); - }); - }, - renderAdminLayoutView: function(obj) { - var that = this; - require(["views/audit/AdminAuditTableLayoutView"], function(AdminAuditTableLayoutView) { - var view = new AdminAuditTableLayoutView({ - searchTableFilters: that.searchTableFilters, - entityDefCollection: that.entityDefCollection, - enumDefCollection: that.enumDefCollection - }); - that.RAdminTableLayoutView.show(view); - }); - }, - renderTypeSystemTreeLayoutView: function(obj) { - var that = this; - require(["views/graph/TypeSystemTreeView"], function(TypeSystemTreeView) { - var view = new TypeSystemTreeView({ - entityDefCollection: that.entityDefCollection - }); - that.RTypeSystemTreeLayoutView.show(view); - }); - } - }); - return AdministratorLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/audit/AdminAuditTableLayoutView.js b/dashboardv2/public/js/views/audit/AdminAuditTableLayoutView.js deleted file mode 100644 index f7918e82f5e..00000000000 --- a/dashboardv2/public/js/views/audit/AdminAuditTableLayoutView.js +++ /dev/null @@ -1,462 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/audit/AdminAuditTableLayoutView_tmpl', - 'collection/VEntityList', - 'utils/Utils', - 'utils/UrlLinks', - 'utils/CommonViewFunction', - 'utils/Enums', - 'moment' -], function(require, Backbone, AdminAuditTableLayoutView_tmpl, VEntityList, Utils, UrlLinks, CommonViewFunction, Enums, moment) { - 'use strict'; - - var AdminAuditTableLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends AuditTableLayoutView */ - { - _viewName: 'AdminAuditTableLayoutView', - - template: AdminAuditTableLayoutView_tmpl, - - /** Layout sub regions */ - regions: { - RAuditTableLayoutView: "#r_adminAuditTableLayoutView", - RQueryBuilderAdmin: "#r_attributeQueryBuilderAdmin" - }, - - /** ui selector cache */ - ui: { - adminPurgedEntityClick: "[data-id='adminPurgedEntity']", - adminAuditEntityDetails: "[data-id='adminAuditEntityDetails']", - attrFilter: "[data-id='adminAttrFilter']", - adminRegion: "[data-id='adminRegion']", - attrApply: "[data-id='attrApply']", - showDefault: "[data-id='showDefault']", - attrClose: "[data-id='attrClose']" - - }, - /** ui events hash */ - events: function() { - var events = {}, - that = this; - events["click " + this.ui.adminPurgedEntityClick] = "onClickAdminPurgedEntity"; - events["click " + this.ui.adminAuditEntityDetails] = "showAdminAuditEntity"; - events["click " + this.ui.attrFilter] = function(e) { - this.ui.attrFilter.find('.fa-angle-right').toggleClass('fa-angle-down'); - this.$('.attributeResultContainer').addClass("overlay"); - this.$('.attribute-filter-container, .attr-filter-overlay').toggleClass('hide'); - this.onClickAttrFilter(); - }; - events["click " + this.ui.attrClose] = function(e) { - that.closeAttributeModel(); - }; - events["click " + this.ui.attrApply] = function(e) { - that.okAttrFilterButton(e); - }; - return events; - }, - /** - * intialize a new AdminTableLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'searchTableFilters', 'entityDefCollection', 'enumDefCollection')); - this.entityCollection = new VEntityList(); - this.limit = 25; - this.offset = 0; - this.entityCollection.url = UrlLinks.adminApiUrl(); - this.entityCollection.modelAttrName = "events"; - this.commonTableOptions = { - collection: this.entityCollection, - includePagination: false, - includeAtlasPagination: true, - includeFooterRecords: false, - includeColumnManager: true, - includeOrderAbleColumns: false, - includeSizeAbleColumns: false, - includeTableLoader: true, - includeAtlasPageSize: true, - includeAtlasTableSorting: true, - columnOpts: { - opts: { - initialColumnsVisible: null, - saveState: false - }, - visibilityControlOpts: { - buttonTemplate: _.template("") - }, - el: this.ui.colManager - }, - atlasPaginationOpts: { - limit: this.limit, - offset: this.offset, - fetchCollection: this.getAdminCollection.bind(this), - }, - gridOpts: { - emptyText: 'No Record found!', - className: 'table table-hover backgrid table-quickMenu colSort' - }, - filterOpts: {}, - paginatorOpts: {} - }; - this.isFilters = null; - this.adminAuditEntityData = {}; - }, - onRender: function() { - this.ui.adminRegion.hide(); - this.getAdminCollection(); - this.entityCollection.comparator = function(model) { - return -model.get('timestamp'); - } - this.renderTableLayoutView(); - }, - onShow: function() { - this.$('.fontLoader').show(); - this.$('.tableOverlay').show(); - }, - bindEvents: function() {}, - closeAttributeModel: function() { - var that = this; - that.$('.attributeResultContainer').removeClass("overlay"); - that.ui.attrFilter.find('.fa-angle-right').toggleClass('fa-angle-down'); - that.$('.attribute-filter-container, .attr-filter-overlay').toggleClass('hide'); - }, - onClickAttrFilter: function() { - var that = this; - this.ui.adminRegion.show(); - require(['views/search/QueryBuilderView'], function(QueryBuilderView) { - that.RQueryBuilderAdmin.show(new QueryBuilderView({ adminAttrFilters: true, searchTableFilters: that.searchTableFilters, entityDefCollection: that.entityDefCollection, enumDefCollection: that.enumDefCollection })); - }); - }, - okAttrFilterButton: function(options) { - var that = this, - isFilterValidate = true, - queryBuilderRef = that.RQueryBuilderAdmin.currentView.ui.builder; - if (queryBuilderRef.data("queryBuilder")) { - var queryBuilder = queryBuilderRef.queryBuilder("getRules"); - if (queryBuilder) { - that.ruleUrl = that.searchTableFilters["adminAttrFilters"] = CommonViewFunction.attributeFilter.generateUrl({ value: queryBuilder, formatedDateToLong: true }); - that.isFilters = queryBuilder.rules.length ? queryBuilder.rules : null; - } else { - isFilterValidate = false - } - } - if (isFilterValidate) { - that.closeAttributeModel(); - that.defaultPagination(); - that.getAdminCollection(); - } - }, - getAdminCollection: function(option) { - var that = this, - auditFilters = CommonViewFunction.attributeFilter.generateAPIObj(that.ruleUrl); - $.extend(that.entityCollection.queryParams, { auditFilters: that.isFilters ? auditFilters : null, limit: that.entityCollection.queryParams.limit || that.limit, offset: that.entityCollection.queryParams.offset || that.offset, sortBy: "startTime", sortOrder: "DESCENDING" }); - var apiObj = { - sort: false, - data: _.pick(that.entityCollection.queryParams, 'auditFilters', 'limit', 'offset', 'sortBy', 'sortOrder'), - success: function(dataOrCollection, response) { - that.entityCollection.state.pageSize = that.entityCollection.queryParams.limit || 25; - that.entityCollection.fullCollection.reset(dataOrCollection, option); - }, - complete: function() { - that.$('.fontLoader').hide(); - that.$('.tableOverlay').hide(); - that.$('.auditTable').show(); - }, - reset: true - } - this.entityCollection.getAdminData(apiObj); - }, - renderTableLayoutView: function() { - var that = this; - this.ui.showDefault.hide(); - require(['utils/TableLayout'], function(TableLayout) { - var cols = new Backgrid.Columns(that.getAuditTableColumns()); - that.RAuditTableLayoutView.show(new TableLayout(_.extend({}, that.commonTableOptions, { - columns: cols - }))); - }); - }, - createTableWithValues: function(tableDetails, isAdminAudit) { - var attrTable = CommonViewFunction.propertyTable({ - scope: this, - getValue: function(val, key) { - if (key && key.toLowerCase().indexOf("time") > 0) { - return Utils.formatDate({ date: val }); - } else { - return val; - } - }, - valueObject: tableDetails, - guidHyperLink: !isAdminAudit - }); - return attrTable; - }, - getAuditTableColumns: function() { - var that = this; - return this.entityCollection.constructor.getTableCols({ - result: { - label: "", - cell: "html", - editable: false, - sortable: false, - cell: Backgrid.ExpandableCell, - fixWidth: "20", - accordion: false, - alwaysVisible: true, - renderable: true, - isExpandVisible: function(el, model) { - if (Enums.serverAudits[model.get('operation')]) { - return false; - } else { - return true; - } - }, - expand: function(el, model) { - var operation = model.get('operation'), - results = model.get('result') || null, - adminText = 'No records found', - adminTypDetails = null, - auditData = { - operation: operation, - model: model, - results: results, - adminText: adminText, - adminTypDetails: adminTypDetails - }; - el.attr('colspan', '8'); - if (results) { - var adminValues = null; - if (operation == "PURGE") { - adminText = that.displayPurgeAndImportAudits(auditData); - } else if (operation == "EXPORT" || operation == "IMPORT") { - adminText = that.displayExportAudits(auditData); - } else { - adminText = that.displayCreateUpdateAudits(auditData); - } - } - $(el).append($('
        ').html(adminText)); - } - }, - userName: { - label: "Users", - cell: "html", - renderable: true, - editable: false - }, - operation: { - label: "Operation", - cell: "String", - renderable: true, - editable: false - }, - clientId: { - label: "Client ID", - cell: "String", - renderable: true, - editable: false - }, - resultCount: { - label: "Result Count", - cell: "String", - renderable: true, - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - if (Enums.serverAudits[model.get('operation')]) { - return "N/A" - } else { - return rawValue; - } - } - }) - }, - startTime: { - label: "Start Time", - cell: "html", - renderable: true, - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return Utils.formatDate({ date: rawValue }); - } - }) - }, - endTime: { - label: "End Time", - cell: "html", - renderable: true, - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return Utils.formatDate({ date: rawValue }); - } - }) - }, - duration: { - label: "Duration", - cell: "html", - renderable: false, - editable: false, - sortable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var startTime = model.get('startTime') ? parseInt(model.get('startTime')) : null, - endTime = model.get('endTime') ? parseInt(model.get('endTime')) : null; - if (_.isNumber(startTime) && _.isNumber(endTime)) { - var duration = moment.duration(moment(endTime).diff(moment(startTime))); - return Utils.millisecondsToTime(duration); - } else { - return "N/A"; - } - } - }) - } - }, this.entityCollection); - }, - defaultPagination: function() { - $.extend(this.entityCollection.queryParams, { limit: this.limit, offset: this.offset }); - this.renderTableLayoutView(); - }, - showAdminAuditEntity: function(e) { - var typeDefObj = this.adminAuditEntityData[e.target.dataset.auditentityid], - typeDetails = this.createTableWithValues(typeDefObj, true), - view = '' + typeDetails + '
        ', - modalData = { - title: Enums.category[typeDefObj.category] + " Type Details: " + typeDefObj.name, - htmlContent: view, - mainClass: "modal-full-screen", - okCloses: true, - showFooter: false, - width: "40%" - }; - this.showModal(modalData); - }, - displayPurgeAndImportAudits: function(obj) { - var adminValues = '
          ', - guids = null, - adminTypDetails = Enums.category[obj.operation]; - if (obj.operation == "PURGE") { - guids = obj.results ? obj.results.replace('[', '').replace(']', '').split(',') : guids; - } else { - guids = obj.model.get('params') ? obj.model.get('params').split(',') : guids; - } - _.each(guids, function(adminGuid, index) { - if (index % 5 == 0 && index != 0) { - adminValues += '
          '; - } - adminValues += ''; - }) - adminValues += '
        '; - return '

        ' + adminTypDetails + '

        ' + adminValues + '
        '; - }, - displayExportAudits: function(obj) { - var adminValues = "", - adminTypDetails = (obj.operation === 'IMPORT') ? Enums.category[obj.operation] : Enums.category[obj.operation] + " And Options", - resultData = obj.results ? JSON.parse(obj.results) : null, - paramsData = (obj.model && obj.model.get('params') && obj.model.get('params').length) ? { params: [obj.model.get('params')] } : null; - - if (resultData) { - adminValues += this.showImportExportTable(resultData, obj.operation); - } - if (paramsData) { - adminValues += this.showImportExportTable(_.extend(paramsData, { "paramsCount": obj.model.get('paramsCount') })); - } - adminValues = adminValues ? adminValues : obj.adminText; - return '

        ' + adminTypDetails + '

        ' + adminValues + '
        '; - }, - showImportExportTable: function(obj, operations) { - var that = this, - typeDetails = "", - view = '
          '; - if (operations && operations === "IMPORT") { - var importKeys = Object.keys(obj); - _.each(importKeys, function(key, index) { - var newObj = {}; - newObj[key] = obj[key]; - if (index % 5 === 0 && index != 0) { - view += '
          '; - } - view += that.createTableWithValues(newObj, true); - }) - } else { - view += this.createTableWithValues(obj, true); - } - return view += '
        ';; - }, - displayCreateUpdateAudits: function(obj) { - var that = this, - resultData = JSON.parse(obj.results), - typeName = obj.model ? obj.model.get('params').split(',') : null, - typeContainer = ''; - _.each(typeName, function(name) { - var typeData = resultData[name], - adminValues = (typeName.length == 1) ? '
          ' : '
            ', - adminTypDetails = Enums.category[name] + " " + Enums.auditAction[obj.operation]; - typeContainer += '

            ' + adminTypDetails + '

            '; - _.each(typeData, function(typeDefObj, index) { - if (index % 5 == 0 && index != 0 && typeName.length == 1) { - adminValues += '
            '; - } - var panelId = typeDefObj.name.split(" ").join("") + obj.model.get('startTime'); - that.adminAuditEntityData[panelId] = typeDefObj; - adminValues += ''; - }); - adminValues += '
          '; - typeContainer += adminValues + '
        '; - }) - var typeClass = (typeName.length == 1) ? null : "admin-audit-details"; - return '
        ' + typeContainer + '
        '; - }, - onClickAdminPurgedEntity: function(e) { - var that = this; - require(['views/audit/AuditTableLayoutView'], function(AuditTableLayoutView) { - var obj = { - guid: $(e.target).text(), - titleText: (e.target.dataset.operation == "PURGE") ? "Purged Entity Details: " : "Import Details: " - }, - modalData = { - title: obj.titleText + obj.guid, - content: new AuditTableLayoutView(obj), - mainClass: "modal-full-screen", - okCloses: true, - showFooter: false, - }; - that.showModal(modalData); - }); - }, - showModal: function(modalObj, title) { - var that = this; - require([ - 'modules/Modal' - ], function(Modal) { - var modal = new Modal(modalObj).open(); - modal.on('closeModal', function() { - $('.modal').css({ 'padding-right': '0px !important' }); - modal.trigger('cancel'); - }); - modal.$el.on('click', 'td a', function() { - modal.trigger('cancel'); - }); - }); - } - }); - return AdminAuditTableLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/audit/AuditTableLayoutView.js b/dashboardv2/public/js/views/audit/AuditTableLayoutView.js deleted file mode 100644 index 625ae87c5d8..00000000000 --- a/dashboardv2/public/js/views/audit/AuditTableLayoutView.js +++ /dev/null @@ -1,229 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/audit/AuditTableLayoutView_tmpl', - 'collection/VEntityList', - 'utils/Utils', - 'utils/Enums', - 'utils/UrlLinks' -], function(require, Backbone, AuditTableLayoutView_tmpl, VEntityList, Utils, Enums, UrlLinks) { - 'use strict'; - - var AuditTableLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends AuditTableLayoutView */ - { - _viewName: 'AuditTableLayoutView', - - template: AuditTableLayoutView_tmpl, - - /** Layout sub regions */ - regions: { - RAuditTableLayoutView: "#r_auditTableLayoutView", - }, - - /** ui selector cache */ - ui: {}, - /** ui events hash */ - events: function() { - var events = {}; - return events; - }, - /** - * intialize a new AuditTableLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'guid', 'entity', 'entityName', 'attributeDefs')); - this.entityCollection = new VEntityList(); - this.limit = 25; - this.offset = 0; - this.entityCollection.url = UrlLinks.entityCollectionaudit(this.guid); - this.entityCollection.modelAttrName = "events"; - this.entityModel = new this.entityCollection.model(); - this.pervOld = []; - this.commonTableOptions = { - collection: this.entityCollection, - includeFilter: false, - includePagination: false, - includeAtlasPagination: true, - includeAtlasPageSize: true, - includeTableLoader: true, - includeAtlasTableSorting: false, - showDefaultTableSorted: true, - columnSorting: false, - includeFooterRecords: false, - gridOpts: { - className: "table table-hover backgrid table-quickMenu", - emptyText: 'No records found!' - }, - sortOpts: { - sortColumn: "timestamp", - sortDirection: "descending" - }, - isApiSorting: true, - atlasPaginationOpts: this.getPaginationOptions(), - filterOpts: {}, - paginatorOpts: {} - }; - this.currPage = 1; - this.fromSort = false; - }, - onRender: function() { - $.extend(this.entityCollection.queryParams, { offset: this.offset, count: this.limit, sortKey: null, order: "sortOrder", sortBy: "timestamp", sortOrder: "desc" }); - this.fetchAuditCollection(); - this.renderTableLayoutView(); - }, - fetchAuditCollection: function() { - this.commonTableOptions['atlasPaginationOpts'] = this.getPaginationOptions(); - this.fetchCollection(); - }, - bindEvents: function() {}, - getPaginationOptions: function() { - return { - count: this.getPageCount(), - offset: this.entityCollection.queryParams.offset || this.offset, - fetchCollection: this.fetchCollection.bind(this) - }; - }, - getPageCount: function() { - return (this.entityCollection.queryParams.limit || this.entityCollection.queryParams.count) || this.limit; - }, - fetchCollection: function(options) { - var that = this; - this.$('.fontLoader').show(); - this.$('.tableOverlay').show(); - //api needs only sortOrder,count,offset, sortBy queryparams & removed extra queryparams limit,sort_by, order - this.entityCollection.queryParams.count = this.getPageCount(); - this.entityCollection.queryParams = _.omit(this.entityCollection.queryParams, 'limit'); - this.entityCollection.fetch({ - success: function(dataOrCollection, response) { - that.entityCollection.state.pageSize = that.getPageCount(); - that.entityCollection.reset(response, $.extend(options)); - }, - complete: function() { - that.$('.fontLoader').hide(); - that.$('.tableOverlay').hide(); - that.$('.auditTable').show(); - if (that.fromSort) { - that.fromSort = !that.fromSort; - } - }, - silent: true - }); - }, - renderTableLayoutView: function() { - var that = this; - require(['utils/TableLayout'], function(TableLayout) { - var cols = new Backgrid.Columns(that.getAuditTableColumns()); - that.RAuditTableLayoutView.show(new TableLayout(_.extend({}, that.commonTableOptions, { - columns: cols - }))); - - }); - }, - backgridHeaderClickHandel: function() { - var that = this; - return Backgrid.HeaderCell.extend({ - onClick: function(e) { - e.preventDefault(); - var column = this.column, - direction = "ascending", - columnName = column.get("name").toLocaleLowerCase(); - if (column.get("direction") === "ascending") direction = "descending"; - column.set("direction", direction); - var options = { - sortBy: columnName, - sortOrder: (direction === "ascending") ? "asc" : "desc", - offset: that.entityCollection.queryParams.offset || that.offset, - count: that.getPageCount() - }; - that.commonTableOptions['sortOpts'] = { - sortColumn: columnName, - sortDirection: (direction === "ascending") ? "ascending" : "descending" - }; - $.extend(that.entityCollection.queryParams, options); - that.fromSort = true; - that.fetchAuditCollection(); - } - }); - }, - getAuditTableColumns: function() { - var that = this; - return this.entityCollection.constructor.getTableCols({ - tool: { - label: "", - cell: "html", - editable: false, - sortable: false, - fixWidth: "20", - cell: Backgrid.ExpandableCell, - accordion: false, - expand: function(el, model) { - el.attr('colspan', '4'); - require([ - 'views/audit/CreateAuditTableLayoutView', - ], function(CreateAuditTableLayoutView) { - that.action = model.get('action'); - var eventModel = that.entityCollection.fullCollection.findWhere({ 'eventKey': model.get('eventKey') }).toJSON(), - collectionModel = new that.entityCollection.model(eventModel), - view = new CreateAuditTableLayoutView({ guid: that.guid, entityModel: collectionModel, action: that.action, entity: that.entity, entityName: that.entityName, attributeDefs: that.attributeDefs }); - view.render(); - $(el).append($('
        ').html(view.$el)); - }); - } - }, - user: { - label: "Users", - cell: "html", - editable: false, - headerCell: that.backgridHeaderClickHandel() - }, - timestamp: { - label: "Timestamp", - cell: "html", - editable: false, - headerCell: that.backgridHeaderClickHandel(), - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return Utils.formatDate({ date: rawValue }); - } - }) - }, - action: { - label: "Actions", - cell: "html", - editable: false, - headerCell: that.backgridHeaderClickHandel(), - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - if (Enums.auditAction[rawValue]) { - return Enums.auditAction[rawValue]; - } else { - return rawValue; - } - } - }) - } - }, this.entityCollection); - - } - }); - return AuditTableLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/audit/CreateAuditTableLayoutView.js b/dashboardv2/public/js/views/audit/CreateAuditTableLayoutView.js deleted file mode 100644 index 20eac06503e..00000000000 --- a/dashboardv2/public/js/views/audit/CreateAuditTableLayoutView.js +++ /dev/null @@ -1,214 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/audit/CreateAuditTableLayoutView_tmpl', - 'utils/Enums', - 'utils/CommonViewFunction', - 'utils/Utils' -], function(require, Backbone, CreateAuditTableLayoutViewTmpl, Enums, CommonViewFunction, Utils) { - 'use strict'; - - var CreateAuditTableLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends CreateAuditTableLayoutView */ - { - _viewName: 'CreateAuditTableLayoutView', - - template: CreateAuditTableLayoutViewTmpl, - - templateHelpers: function() { - return { - technicalPropPanelId: this.technicalPropId, - relationshipPropPanelId: this.relationshipPropId, - userdefinedPropPanelId: this.userDefinedPropId - }; - }, - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - auditValue: "[data-id='auditValue']", - name: "[data-id='name']", - noData: "[data-id='noData']", - tableAudit: "[data-id='tableAudit']", - auditHeaderValue: "[data-id='auditHeaderValue']", - attributeDetails: "[data-id='attributeDetails']", - attributeCard: "[data-id='attribute-card']", - labelsDetailsTable: "[data-id='labelsDetails']", - labelCard: "[data-id='label-card']", - customAttributeDetails: "[data-id='customAttributeDetails']", - customAttrCard: "[data-id='custom-attr-card']", - relationShipAttributeDetails: "[data-id='relationShipAttributeDetails']", - relationshipAttrCard: "[data-id='relationship-attr-card']", - attributeDetailCard: "[data-id='attributeDetail-card']", - detailsAttribute: "[data-id='detailsAttribute']", - panelAttrHeading: "[data-id='panel-attr-heading']", - nameUpdate: "[data-id='name-update']" - - }, - /** ui events hash */ - events: function() { - var events = {}; - return events; - }, - /** - * intialize a new CreateAuditTableLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'guid', 'entityModel', 'action', 'entity', 'entityName', 'attributeDefs')); - var modelID = this.entityModel.cid || parseInt((Math.random() * 100)); - this.technicalPropId = this.getRandomID(modelID); - this.relationshipPropId = this.getRandomID(modelID, this.technicalPropId); - this.userDefinedPropId = this.getRandomID(modelID, this.technicalPropId, this.userDefinedPropId); - }, - bindEvents: function() {}, - onRender: function() { - this.auditTableGenerate(); - }, - getRandomID: function(modelID, technicalPropId, relationshipPropId) { - var randomIdObj = CommonViewFunction.getRandomIdAndAnchor(); - randomIdObj.id = randomIdObj.id + modelID; - randomIdObj.anchor = randomIdObj.anchor + modelID; - return (randomIdObj === technicalPropId || randomIdObj === relationshipPropId) ? this.getRandomID(technicalPropId, relationshipPropId) : randomIdObj; - }, - createTableWithValues: function(tableDetails) { - var attrTable = CommonViewFunction.propertyTable({ - scope: this, - getValue: function(val, key) { - if (key && key.toLowerCase().indexOf("time") > 0) { - return Utils.formatDate({ date: val }); - } else { - return val; - } - }, - valueObject: tableDetails - }); - return attrTable; - - }, - updateName: function(name) { - this.ui.name.html("Name: " + name + ""); - }, - noDetailsShow: function() { - this.ui.noData.removeClass('hide'); - }, - auditTableGenerate: function() { - var that = this, - table = ""; - var detailObj = this.entityModel.get('details'); - if (detailObj) { - if (detailObj.search(':') >= 0) { - var parseDetailsObject = detailObj.split(':'), - type = "", - auditData = ""; - if (parseDetailsObject.length > 1) { - type = parseDetailsObject[0]; - parseDetailsObject.shift(); - auditData = parseDetailsObject.join(":"); - } - if (auditData.search('{') === -1) { - if (type.trim() === "Added labels" || type.trim() === "Deleted labels") { - this.updateName(auditData.trim().split(" ").join(",")); - } else { - this.updateName(auditData); - } - } else { - try { - parseDetailsObject = JSON.parse(auditData); - var skipAttribute = parseDetailsObject.typeName ? "guid" : null, - name = Utils.getName(parseDetailsObject, null, skipAttribute); - if (name == "-") { - name = _.escape(parseDetailsObject.typeName); - } - var name = ((name ? name : this.entityName)); - that.updateName(name); - if (parseDetailsObject) { - var attributesDetails = $.extend(true, {}, parseDetailsObject.attributes), - customAttr = parseDetailsObject.customAttributes, - labelsDetails = parseDetailsObject.labels, - relationshipAttributes = parseDetailsObject.relationshipAttributes, - bmAttributesDeails = that.entity.businessAttributes ? that.entity.businessAttributes[parseDetailsObject.typeName] : null; - if (attributesDetails) { - if (bmAttributesDeails) { - _.each(Object.keys(attributesDetails), function(key) { - if (bmAttributesDeails[key].typeName.toLowerCase().indexOf("date") > -1) { - if (attributesDetails[key].length) { // multiple date values - attributesDetails[key] = _.map(attributesDetails[key], function(dateValue) { - return Utils.formatDate({ date: dateValue }) - }); - } else { - attributesDetails[key] = Utils.formatDate({ date: attributesDetails[key] }); - } - } - }) - } - that.ui.attributeDetails.removeClass('hide'); - that.action.indexOf("Classification") === -1 ? that.ui.panelAttrHeading.html("Technical properties ") : that.ui.panelAttrHeading.html("Properties "); - var attrTable = that.createTableWithValues(attributesDetails); - that.ui.attributeCard.html( - attrTable); - } - if (!_.isEmpty(customAttr)) { - that.ui.customAttributeDetails.removeClass('hide'); - var customAttrTable = that.createTableWithValues(customAttr); - that.ui.customAttrCard.html( - customAttrTable); - } - if (!_.isEmpty(labelsDetails)) { - this.ui.labelsDetailsTable.removeClass('hide'); - var labelsTable = ''; - _.each(labelsDetails, function(value, key, list) { - labelsTable += ""; - }); - that.ui.labelCard.html( - labelsTable); - } - if (!_.isEmpty(relationshipAttributes)) { - that.ui.relationShipAttributeDetails.removeClass('hide'); - var relationshipAttrTable = that.createTableWithValues(relationshipAttributes); - that.ui.relationshipAttrCard.html( - relationshipAttrTable); - } - if (!attributesDetails && !customAttr && !labelsDetails && !relationshipAttributes) { - that.ui.detailsAttribute.removeClass('hide'); - var attrDetailTable = that.createTableWithValues(parseDetailsObject); - that.ui.attributeDetailCard.html( - attrDetailTable); - } - } else { - that.noDetailsShow(); - } - } catch (err) { - if (_.isArray(parseDetailsObject)) { - var name = _.escape(parseDetailsObject[0]); - } - that.updateName(name); - that.noDetailsShow(); - } - } - } else if (detailObj == "Deleted entity" || detailObj == "Purged entity") { - this.entityName ? this.updateName(this.entityName) : (this.ui.name.hide() && this.ui.noData.removeClass("hide")); - } - } - } - }); - return CreateAuditTableLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/audit/ReplicationAuditTableLayoutView.js b/dashboardv2/public/js/views/audit/ReplicationAuditTableLayoutView.js deleted file mode 100644 index 095d3b73c72..00000000000 --- a/dashboardv2/public/js/views/audit/ReplicationAuditTableLayoutView.js +++ /dev/null @@ -1,195 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/audit/ReplicationAuditTableLayoutView_tmpl', - 'utils/CommonViewFunction', - 'utils/Utils', - 'collection/VSearchList', - 'collection/VEntityList', - 'utils/Messages', - 'utils/UrlLinks' -], function(require, Backbone, ReplicationAuditTableLayoutView_tmpl, CommonViewFunction, Utils, VSearchList, VEntityList, Messages, UrlLinks) { - 'use strict'; - - var ReplicationAuditTableLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends ReplicationAuditTableLayoutView */ - { - _viewName: 'ReplicationAuditTableLayoutView', - - template: ReplicationAuditTableLayoutView_tmpl, - - /** Layout sub regions */ - regions: { - RReplicationAuditTableLayoutView: "#r_replicationAuditTableLayoutView" - }, - - /** ui selector cache */ - ui: {}, - /** ui events hash */ - events: function() { - var events = {} - return events; - }, - /** - * intialize a new ReplicationAuditTableLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'entity', 'entityName', 'attributeDefs')); - this.searchCollection = new VSearchList(); - this.entityModel = new(new VEntityList()).model(); - this.limit = 25; - this.offset = 0; - this.name = Utils.getName(this.entity); - this.commonTableOptions = { - collection: this.searchCollection, - includePagination: false, - includeAtlasPagination: true, - includeFooterRecords: false, - includeColumnManager: false, - includeOrderAbleColumns: false, - includeSizeAbleColumns: false, - includeTableLoader: true, - includeAtlasPageSize: true, - includeAtlasTableSorting: true, - atlasPaginationOpts: { - limit: this.limit, - offset: this.offset, - fetchCollection: this.fetchCollection.bind(this), - }, - gridOpts: { - emptyText: 'No Record found!', - className: 'table table-hover backgrid table-quickMenu colSort' - }, - filterOpts: {}, - paginatorOpts: {} - }; - }, - bindEvents: function() {}, - onRender: function() { - this.renderTableLayoutView(); - }, - fetchCollection: function(options) { - var that = this; - - this.searchCollection.getExpimpAudit(this.searchCollection.queryParams, { - success: function(response) { - that.searchCollection.reset(response, options); - } - }); - }, - renderTableLayoutView: function() { - var that = this; - require(['utils/TableLayout'], function(TableLayout) { - var columnCollection = Backgrid.Columns.extend({ - sortKey: "displayOrder", - comparator: function(item) { - return item.get(this.sortKey) || 999; - }, - setPositions: function() { - _.each(this.models, function(model, index) { - model.set("displayOrder", index + 1, { silent: true }); - }); - return this; - } - }); - var columns = new columnCollection(that.getColumn()); - columns.setPositions().sort(); - that.RReplicationAuditTableLayoutView.show(new TableLayout(_.extend({}, that.commonTableOptions, { - columns: columns - }))); - _.extend(that.searchCollection.queryParams, { limit: that.limit, offset: that.offset, "serverName": that.name }); - that.fetchCollection(_.extend({ 'fromUrl': true })); - }); - }, - getColumn: function(argument) { - var that = this, - col = {}; - col['tools'] = { - label: "", - cell: "html", - editable: false, - sortable: false, - fixWidth: "20", - cell: Backgrid.ExpandableCell, - accordion: false, - expand: function(el, model) { - el.attr('colspan', '6'); - var result = JSON.parse(model.get("resultSummary")), - view = "" + CommonViewFunction.propertyTable({ scope: that, valueObject: result, attributeDefs: that.attributeDefs }) + "
        "; - $(el).append($('
        ').html(view)); - } - }; - col['operation'] = { - label: "Operation", - cell: "string", - editable: false, - sortable: false, - className: "searchTableName" - }; - col['sourceServerName'] = { - label: "Source Server", - cell: "string", - editable: false, - sortable: false, - className: "searchTableName" - }; - col['targetServerName'] = { - label: "Target Server", - cell: "string", - editable: false, - sortable: false, - className: "searchTableName" - }; - col['startTime'] = { - label: "Operation StartTime", - cell: "html", - editable: false, - sortable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - if (rawValue) { - return Utils.formatDate({ date: rawValue }); - } else { - return '-'; - } - } - }) - }; - col['endTime'] = { - label: "Operation EndTime", - cell: "html", - editable: false, - sortable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - if (rawValue) { - return Utils.formatDate({ date: rawValue }); - } else { - return '-'; - } - } - }) - }; - return this.searchCollection.constructor.getTableCols(col, this.searchCollection); - } - }); - return ReplicationAuditTableLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/business_metadata/BusinessMetadataAttrTableLayoutView.js b/dashboardv2/public/js/views/business_metadata/BusinessMetadataAttrTableLayoutView.js deleted file mode 100644 index 37058bbe2e5..00000000000 --- a/dashboardv2/public/js/views/business_metadata/BusinessMetadataAttrTableLayoutView.js +++ /dev/null @@ -1,247 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/business_metadata/BusinessMetadataAttrTableLayoutView_tmpl', - 'collection/VEntityList' -], function(require, Backbone, BusinessMetadataAttrTableLayoutView_tmpl, VEntityList) { - 'use strict'; - - var BusinessMetadataAttrTableLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends BusinessMetadataAttrTableLayoutView */ - { - _viewName: 'BusinessMetadataAttrTableLayoutView', - - template: BusinessMetadataAttrTableLayoutView_tmpl, - - /** Layout sub regions */ - regions: { - RBusinessMetadataAttrTableLayoutView: "#r_businessMetadataAttrTableLayoutView", - RModal: "#r_modal" - }, - - /** ui selector cache */ - ui: { - attributeEdit: "[data-id='attributeEdit']", - addAttribute: '[data-id="addAttribute"]', - businessMetadataAttrPage: "[data-id='businessMetadataAttrPage']", - businessMetadataAttrPageTitle: "[data-id='businessMetadataAttrPageTitle']", - businessMetadataDetailPage: "[data-id='businessMetadataDetailPage']", - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.attributeEdit] = "onEditAttr"; - events["click " + this.ui.addAttribute] = "onEditAttr"; - return events; - }, - /** - * intialize a new BusinessMetadataAttrTableLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'guid', 'model', 'typeHeaders', 'businessMetadataDefCollection', 'entityDefCollection')); - this.businessMetadataAttr = new VEntityList(this.model.get("attributeDefs") || []); - this.commonTableOptions = { - collection: this.businessMetadataAttr, - includeFilter: false, - includePagination: false, - includePageSize: false, - includeAtlasTableSorting: true, - includeFooterRecords: false, - gridOpts: { - className: "table table-hover backgrid table-quickMenu", - emptyText: 'No records found!' - }, - filterOpts: {}, - paginatorOpts: {} - }; - this.showDetails = true; - }, - onRender: function() { - this.renderTableLayoutView(); - this.toggleBusinessMetadataDetailsAttrView(); - }, - bindEvents: function() {}, - toggleBusinessMetadataDetailsAttrView: function() { - var that = this; - if (that.showDetails) { - that.ui.businessMetadataAttrPage.hide(); - that.ui.businessMetadataDetailPage.show(); - } else { - that.ui.businessMetadataAttrPage.show(); - that.ui.businessMetadataDetailPage.hide(); - } - }, - onEditAttr: function(e) { - var that = this, - isAttrEdit = false, - selectedBusinessMetadata = that.model, - attrributes = selectedBusinessMetadata ? selectedBusinessMetadata.get('attributeDefs') : null, - attrName = e.target.dataset.name ? e.target.dataset.name : null, - attrDetails = { name: attrName }; - if (e.target.dataset.action == 'attributeEdit') { - isAttrEdit = true - } - if (selectedBusinessMetadata) { - that.newAttr = isAttrEdit ? false : true; - _.each(attrributes, function(attrObj) { - if (attrObj.name === attrName) { - attrDetails = $.extend(true, {}, attrObj); - if (attrObj.typeName.includes('array')) { - attrDetails.typeName = attrObj.typeName.replace("array<", "").replace(">", ""); - attrDetails.multiValued = true; - } - } - }); - this.showDetails = false; - that.toggleBusinessMetadataDetailsAttrView(); - require(["views/business_metadata/CreateBusinessMetadataLayoutView"], function(CreateBusinessMetadataLayoutView) { - that.view = new CreateBusinessMetadataLayoutView({ - onEditCallback: function() { - enumDefCollection.fetch({ reset: true }); - that.businessMetadataAttr.reset(that.model.get("attributeDefs")); - }, - onUpdateBusinessMetadata: function(fetch) { - that.showDetails = true; - that.toggleBusinessMetadataDetailsAttrView(); - if (fetch) { - that.entityDefCollection.fetch({ silent: true }); - } - }, - parent: that.$el, - businessMetadataDefCollection: that.businessMetadataDefCollection, - enumDefCollection: enumDefCollection, - isAttrEdit: isAttrEdit, - attrDetails: attrDetails, - typeHeaders: typeHeaders, - selectedBusinessMetadata: that.model, - guid: that.guid, - isNewAttr: that.newAttr - }); - if (isAttrEdit) { - that.ui.businessMetadataAttrPageTitle.text("Update Attribute of: " + selectedBusinessMetadata.get('name')); - } else { - that.ui.businessMetadataAttrPageTitle.text("Add Business Metadata Attribute for: " + selectedBusinessMetadata.get('name')); - } - that.RModal.show(that.view); - }); - } - - }, - renderTableLayoutView: function() { - var that = this; - require(['utils/TableLayout'], function(TableLayout) { - var cols = new Backgrid.Columns(that.getBusinessMetadataTableColumns()); - that.RBusinessMetadataAttrTableLayoutView.show(new TableLayout(_.extend({}, that.commonTableOptions, { - columns: cols - }))); - }); - }, - getBusinessMetadataTableColumns: function() { - var that = this; - return this.businessMetadataAttr.constructor.getTableCols({ - name: { - label: "Attribute Name", - cell: "html", - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return _.escape(model.get('name')); - } - }) - }, - typeName: { - label: "Type Name", - cell: "html", - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return _.escape(model.get('typeName')); - } - }) - }, - searchWeight: { - label: "Search Weight", - cell: "String", - editable: false - }, - enableMultipleValue: { - label: "Enable Multivalues", - cell: "html", - editable: false, - sortable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var enableMultipleValue = ''; - if (model.get('typeName').indexOf('array<') > -1) { - enableMultipleValue = 'checked'; - } - return ''; - } - }) - }, - maxStrLength: { - label: "Max Length", - cell: "html", - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var maxString = "NA"; - if (model.get('typeName').indexOf('string') > -1) { - maxString = model.get('options').maxStrLength || maxString; - } - return maxString; - } - }) - }, - applicableEntityTypes: { - label: "Entity Type(s)", - cell: "html", - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var options = model.get('options') - if (options && options.applicableEntityTypes) { - var applicableEntityTypes = '', - attrEntityTypes = JSON.parse(options.applicableEntityTypes); - _.each(attrEntityTypes, function(values) { - applicableEntityTypes += ''; - }); - return applicableEntityTypes; - } - } - }) - }, - tool: { - label: "Action", - cell: "html", - editable: false, - sortable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return '
        Edit
        '; - } - }) - } - }, this.businessMetadataAttr); - } - }); - return BusinessMetadataAttrTableLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/business_metadata/BusinessMetadataAttributeItemView.js b/dashboardv2/public/js/views/business_metadata/BusinessMetadataAttributeItemView.js deleted file mode 100644 index 5190db0319a..00000000000 --- a/dashboardv2/public/js/views/business_metadata/BusinessMetadataAttributeItemView.js +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -define(['require', - 'backbone', - 'hbs!tmpl/business_metadata/BusinessMetadataAttributeItemView_tmpl' -], function(require, Backbone, BusinessMetadataAttributeItemViewTmpl) { - 'use strict'; - - return Backbone.Marionette.ItemView.extend( - /** @lends GlobalExclusionListView */ - { - - template: BusinessMetadataAttributeItemViewTmpl, - templateHelpers: function() { - return { - modalID: this.viewId - }; - }, - - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - attributeInput: "[data-id='attributeInput']", - close: "[data-id='close']", - dataTypeSelector: "[data-id='dataTypeSelector']", - searchWeightSelector: "[data-id='searchWeightSelector']", - entityTypeSelector: "[data-id='entityTypeSelector']", - enumTypeSelectorContainer: "[data-id='enumTypeSelectorContainer']", - enumTypeSelector: "[data-id='enumTypeSelector']", - enumValueSelectorContainer: "[data-id='enumValueSelectorContainer']", - enumValueSelector: "[data-id='enumValueSelector']", - multiValueSelect: "[data-id='multiValueSelect']", - multiValueSelectStatus: "[data-id='multiValueSelectStatus']", - stringLengthContainer: "[data-id='stringLengthContainer']", - stringLengthValue: "[data-id='stringLength']", - createNewEnum: "[data-id='createNewEnum']" - }, - /** ui events hash */ - events: function() { - var events = {}; - events["keyup " + this.ui.attributeInput] = function(e) { - this.model.set({ "name": e.target.value.trim() }); - }; - events["change " + this.ui.searchWeightSelector] = function(e) { - this.model.set({ "searchWeight": e.target.value.trim() }); - }; - events["change " + this.ui.dataTypeSelector] = function(e) { - var obj = { options: this.model.get('options') || {} }; - delete obj.enumValues; - delete obj.options.maxStrLength; - if (e.target.value.trim().toLowerCase() === 'enumeration') { - this.ui.enumTypeSelectorContainer.show(); - this.ui.enumTypeSelector.show(); - this.emumTypeSelectDisplay(); - this.ui.stringLengthContainer.hide(); - this.ui.stringLengthValue.hide(); - } else { - obj.typeName = e.target.value.trim(); - if (e.target.value.trim().toLowerCase() === 'string') { - this.ui.stringLengthContainer.show(); - this.ui.stringLengthValue.show(); - this.ui.enumTypeSelectorContainer.hide(); - this.ui.enumTypeSelector.hide(); - this.ui.enumValueSelectorContainer.hide(); - obj.options["maxStrLength"] = this.ui.stringLengthValue.val() - } else { - this.ui.enumTypeSelectorContainer.hide(); - this.ui.enumTypeSelector.hide(); - this.ui.enumValueSelectorContainer.hide(); - this.ui.stringLengthContainer.hide(); - this.ui.stringLengthValue.hide(); - } - } - this.model.set(obj); - if (e.target.value.trim() != 'enumeration') { - this.ui.multiValueSelectStatus.trigger('change'); - } - }; - events["change " + this.ui.enumTypeSelector] = function(e) { - this.model.set({ "enumValues": e.target.value.trim() }); - }; - events["change " + this.ui.stringLengthContainer] = function(e) { - var options = this.model.get('options') || {}; - if (this.ui.dataTypeSelector.val() == 'string') { - options["maxStrLength"] = e.target.value.trim(); - } - this.model.set({ "options": options }); - - }; - events["change " + this.ui.enumTypeSelector] = function(e) { - var emumValue = this.ui.enumTypeSelector.select2('data')[0] ? this.ui.enumTypeSelector.select2('data')[0].text : this.ui.enumTypeSelector.val(); - - this.model.set({ "typeName": emumValue }); - if (this.model.get("multiValueSelect")) { - this.model.set({ "typeName": "array<" + emumValue + ">" }); - } - if (emumValue == '' || emumValue == null) { - this.ui.enumValueSelectorContainer.hide(); - } else { - this.ui.enumValueSelectorContainer.show(); - this.showEnumValues(_.escape(emumValue)); - } - }; - events["change " + this.ui.enumValueSelector] = function(e) { - this.model.set({ "enumValues": this.ui.enumValueSelector.val() }); - }; - events["change " + this.ui.multiValueSelectStatus] = function(e) { - this.model.set({ "multiValueSelect": e.target.checked }); - var typename = this.model.get('typeName'); - if (e.target.checked) { - typename = "array<" + typename + ">"; - } else { - typename = typename.replace('array<', '').replace('>', ''); - } - this.model.set({ "typeName": typename }); - }; - events["change " + this.ui.entityTypeSelector] = function(e) { - var options = this.model.get('options') || {}; - options.applicableEntityTypes = JSON.stringify(this.ui.entityTypeSelector.val()); - this.model.set({ "options": options }); - } - events["click " + this.ui.close] = 'onCloseButton'; - events["click " + this.ui.createNewEnum] = 'onCreateUpdateEnum'; - return events; - }, - - /** - * intialize a new GlobalExclusionComponentView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, "typeHeaders", "businessMetadataDefCollection", "enumDefCollection", "isAttrEdit", "viewId", "collection")); - this.viewId = options.model ? options.model.cid : this.viewId; - }, - onRender: function() { - var that = this, - entitytypes = '', - enumTypes = [], - searchWeightValue = '5', - stringLengthValue = '50', - applicableEntityType = ''; - this.typeHeaders.fullCollection.each(function(model) { - if (model.toJSON().category == "ENTITY") { - that.ui.entityTypeSelector.append(""); - entitytypes += ''; - } - }); - this.ui.entityTypeSelector.select2({ - placeholder: "Select Entity type", - allowClear: true, - multiple: true, - selectionAdapter: $.fn.select2.amd.require("TagHideDeleteButtonAdapter") - }); - this.ui.entityTypeSelector.html(entitytypes); - this.ui.entityTypeSelector.on('select2:open', function(e) { // to make selected option disable in dropdown added remove-from-list class - $('.select2-dropdown--below').addClass('remove-from-list'); - }); - if (this.model.get("searchWeight")) { - searchWeightValue = this.model.get("searchWeight") === -1 ? 0 : this.model.get("searchWeight"); - } - if (this.model.get("options")) { - stringLengthValue = this.model.get("options").maxStrLength || '50'; - applicableEntityType = this.model.get("options").applicableEntityTypes ? JSON.parse(this.model.get("options").applicableEntityTypes) : null; - } - this.ui.stringLengthValue.val(stringLengthValue).trigger('change'); //default length for string is 50 - this.ui.searchWeightSelector.val(searchWeightValue).trigger('change'); - this.ui.enumValueSelector.attr("disabled", "false"); // cannot edit the values - this.emumTypeSelectDisplay(); - this.ui.enumTypeSelectorContainer.hide(); - this.ui.enumTypeSelector.hide(); - this.ui.enumValueSelectorContainer.hide(); - if (this.isAttrEdit) { - var typeName = this.model.get("typeName"); - this.ui.close.hide(); - this.ui.createNewEnum.hide(); // cannot add new businessMetadata on edit view - this.ui.attributeInput.val(this.model.get("name")); - this.ui.attributeInput.attr("disabled", "false"); - this.ui.dataTypeSelector.attr("disabled", "false"); - this.ui.dataTypeSelector.attr("disabled", "false"); - this.ui.multiValueSelect.hide(); - this.ui.dataTypeSelector.val(typeName); - if (typeName == "string") { - this.ui.stringLengthContainer.show(); - this.ui.stringLengthValue.show(); - } else { - this.ui.stringLengthContainer.hide(); - this.ui.stringLengthValue.hide(); - } - if (applicableEntityType) { - _.each(applicableEntityType, function(valName) { - that.ui.entityTypeSelector.find('option').each(function(o) { - var $el = $(this) - if ($el.data("name") === valName) { - $el.attr("data-allowremove", "false"); - } - }) - }); - } - this.ui.entityTypeSelector.val(applicableEntityType).trigger('change'); - if (typeName != "string" && typeName != "boolean" && typeName != "byte" && typeName != "short" && typeName != "int" && typeName != "float" && typeName != "double" && typeName != "long" && typeName != "date") { - this.ui.enumTypeSelector.attr("disabled", "false"); - this.ui.dataTypeSelector.val("enumeration").trigger('change'); - this.ui.enumTypeSelector.val(typeName).trigger('change'); - } - if (this.model.get("multiValued")) { - this.ui.multiValueSelect.show(); - $(this.ui.multiValueSelectStatus).prop('checked', true).trigger('change'); - this.ui.multiValueSelectStatus.attr("disabled", "false"); - } - } - }, - showEnumValues: function(enumName) { - var enumValues = '', - selectedValues = [], - selectedEnum = this.enumDefCollection.fullCollection.findWhere({ name: enumName }), - selectedEnumValues = selectedEnum ? selectedEnum.get('elementDefs') : null, - savedValues = []; - _.each(selectedEnumValues, function(enumVal, index) { - selectedValues.push(enumVal.value); - enumValues += ""; - }); - this.ui.enumValueSelector.empty(); - this.ui.enumValueSelector.append(enumValues); - this.ui.enumValueSelector.val(selectedValues); - this.ui.enumValueSelector.select2({ - placeholder: "Select Enum value", - allowClear: false, - tags: false, - multiple: true - }); - this.model.set({ "enumValues": this.ui.enumValueSelector.val() }); - }, - emumTypeSelectDisplay: function() { - var enumTypes = ''; - this.enumDefCollection.fullCollection.each(function(model, index) { - enumTypes += ""; - }); - this.ui.enumTypeSelector.empty(); - this.ui.enumTypeSelector.append(enumTypes); - this.ui.enumTypeSelector.val(''); - this.ui.enumTypeSelector.select2({ - placeholder: "Select Enum name", - tags: false, - allowClear: true, - multiple: false - }); - }, - onCreateUpdateEnum: function(e) { - var that = this; - require(["views/business_metadata/EnumCreateUpdateItemView", "modules/Modal"], function(EnumCreateUpdateItemView, Modal) { - var view = new EnumCreateUpdateItemView({ - onUpdateEnum: function() { - that.ui.enumValueSelectorContainer.hide(); - that.emumTypeSelectDisplay(); - that.ui.enumValueSelector.empty(); - }, - closeModal: function() { - modal.trigger("cancel"); - that.enumDefCollection.fetch({ - success: function() { - that.ui.enumTypeSelector.val(that.model.get('typeName')).trigger('change'); - } - }); - }, - enumDefCollection: that.enumDefCollection, - businessMetadataDefCollection: that.businessMetadataDefCollection - }), - modal = new Modal({ - title: "Create/ Update Enum", - content: view, - cancelText: "Cancel", - okCloses: false, - okText: "Update", - allowCancel: true, - showFooter: false - }).open(); - modal.on('closeModal', function() { - modal.trigger('cancel'); - }); - }); - }, - onCloseButton: function() { - var tagName = this.$el.find('[data-id="tagName"]').val(); - if (this.collection.models.length > 0) { - this.model.destroy(); - } - if (this.collection.models.length == 0 && tagName != "") { - this.$el.parent().next().find('button.ok').removeAttr("disabled"); - } - } - }); -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/business_metadata/BusinessMetadataContainerLayoutView.js b/dashboardv2/public/js/views/business_metadata/BusinessMetadataContainerLayoutView.js deleted file mode 100644 index 6ae97f985d7..00000000000 --- a/dashboardv2/public/js/views/business_metadata/BusinessMetadataContainerLayoutView.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define([ - "require", - "backbone", - "hbs!tmpl/business_metadata/BusinessMetadataContainerLayoutView_tmpl" -], function(require, Backbone, BusinessMetadataContainerLayoutViewTmpl) { - "use strict"; - - var BusinessMetadataContainerLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends BusinessMetadataContainerLayoutView */ - { - _viewName: "BusinessMetadataContainerLayoutView", - - template: BusinessMetadataContainerLayoutViewTmpl, - - /** Layout sub regions */ - regions: { - RBusinessMetadataDetailContainer: "#r_businessMetadataDetailContainer", - RBusinessMetadataAttrContainer: "#r_businessMetadataAttrContainer" - }, - - /** ui selector cache */ - ui: {}, - /** ui events hash */ - events: function() {}, - /** - * intialize a new TagLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, options); - }, - bindEvents: function() {}, - onRender: function() { - this.updateView(); - }, - updateView: function() { - this.model = this.businessMetadataDefCollection.fullCollection.findWhere({ guid: this.guid }); - this.renderBusinessMetadataDetailLayoutView(); - this.renderBusinessMetadataAttrLayoutView(); - }, - renderBusinessMetadataDetailLayoutView: function() { - var that = this; - require(["views/business_metadata/BusinessMetadataDetailLayoutView"], function(BusinessMetadataDetailLayoutView) { - if (that.isDestroyed) { - return; - } - that.RBusinessMetadataDetailContainer.show(new BusinessMetadataDetailLayoutView({ - businessMetadataDefCollection: that.businessMetadataDefCollection, - guid: that.guid, - model: that.model, - enumDefCollection: that.enumDefCollection, - typeHeaders: that.typeHeaders - })); - }); - }, - renderBusinessMetadataAttrLayoutView: function() { - var that = this; - require(["views/business_metadata/BusinessMetadataAttrTableLayoutView"], function(BusinessMetadataAttrTableLayoutView) { - if (that.isDestroyed) { - return; - } - that.RBusinessMetadataAttrContainer.show(new BusinessMetadataAttrTableLayoutView({ - businessMetadataDefCollection: that.businessMetadataDefCollection, - model: that.model, - guid: that.guid, - typeHeaders: that.typeHeaders, - enumDefCollection: that.enumDefCollection, - entityDefCollection: that.entityDefCollection - })); - }); - } - } - ); - return BusinessMetadataContainerLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js b/dashboardv2/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js deleted file mode 100644 index 422808b82ca..00000000000 --- a/dashboardv2/public/js/views/business_metadata/BusinessMetadataDetailLayoutView.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/business_metadata/BusinessMetadataDetailLayoutView_tmpl', - 'utils/Utils', -], function(require, Backbone, BusinessMetadataDetailLayoutViewTmpl, Utils) { - 'use strict'; - - var BusinessMetadataDetailLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends BusinessMetadataDetailLayoutView */ - { - template: BusinessMetadataDetailLayoutViewTmpl, - /** Layout sub regions */ - regions: {}, - /** ui selector cache */ - ui: { - title: '[data-id="title"]', - description: '[data-id="description"]' - }, - /** ui events hash */ - events: function() { - var events = {}; - return events; - }, - /** - * intialize a new BusinessMetadataDetailLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'model')); - $('body').addClass("detail-page"); - }, - onRender: function() { - this.renderDetail(); - }, - renderDetail: function() { - this.ui.title.html('' + this.model.get('name') + ''); - if (this.model.get('description')) { - this.ui.description.text(this.model.get('description')); - } - }, - onDestroy: function() { - if (!Utils.getUrlState.isBSDetail()) { - $('body').removeClass("detail-page"); - } - } - }); - return BusinessMetadataDetailLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js b/dashboardv2/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js deleted file mode 100644 index 6527eeb272f..00000000000 --- a/dashboardv2/public/js/views/business_metadata/BusinessMetadataTableLayoutView.js +++ /dev/null @@ -1,405 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/business_metadata/BusinessMetadataTableLayoutView_tmpl', - 'utils/Utils', - 'utils/Messages' -], function(require, Backbone, BusinessMetadataTableLayoutView_tmpl, Utils, Messages) { - 'use strict'; - - var BusinessMetadataTableLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends BusinessMetadataTableLayoutView */ - { - _viewName: 'BusinessMetadataTableLayoutView', - - template: BusinessMetadataTableLayoutView_tmpl, - - /** Layout sub regions */ - regions: { - RBusinessMetadataTableLayoutView: "#r_businessMetadataTableLayoutView", - RModal: "#r_modal" - }, - - /** ui selector cache */ - ui: { - businessMetadataAttrPage: "[data-id='businessMetadataAttrPage']", - businessMetadataAttrPageTitle: "[data-id='businessMetadataAttrPageTitle']", - businessMetadataDetailPage: "[data-id='businessMetadataDetailPage']", - createBusinessMetadata: "[data-id='createBusinessMetadata']", - attributeEdit: "[data-id='attributeEdit']", - addAttribute: '[data-id="addAttribute"]', - businessMetadataAttrPageOk: '[data-id="businessMetadataAttrPageOk"]', - colManager: "[data-id='colManager']", - deleteBusinessMetadata: '[data-id="deleteBusinessMetadata"]' - }, - /** ui events hash */ - events: function() { - var events = {}, - that = this; - events["click " + this.ui.createBusinessMetadata] = "onClickCreateBusinessMetadata"; - events["click " + this.ui.addAttribute] = "onEditAttr"; - events["click " + this.ui.attributeEdit] = "onEditAttr"; - events["click " + this.ui.deleteBusinessMetadata] = function(e) { - that.guid = e.target.dataset.guid; - that.deleteBusinessMetadataElement(); - }; - return events; - }, - /** - * intialize a new BusinessMetadataTableLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'guid', 'entity', 'entityName', 'attributeDefs', 'typeHeaders', 'businessMetadataDefCollection', 'entityDefCollection', 'businessMetadataAttr', 'selectedBusinessMetadata')); - this.limit = 10; - this.newAttr = false; - this.commonTableOptions = { - collection: this.businessMetadataDefCollection, - includeFilter: false, - includePagination: true, - includeFooterRecords: true, - includePageSize: true, - includeGotoPage: true, - includeAtlasTableSorting: true, - includeTableLoader: true, - includeColumnManager: true, - gridOpts: { - className: "table table-hover backgrid table-quickMenu", - emptyText: 'No records found!' - }, - columnOpts: { - opts: { - initialColumnsVisible: null, - saveState: false - }, - visibilityControlOpts: { - buttonTemplate: _.template("") - }, - el: this.ui.colManager - }, - filterOpts: {}, - paginatorOpts: {} - }; - this.guid = null; - this.showDetails = true; // toggle between sttribute page and detail page - }, - onRender: function() { - this.toggleBusinessMetadataDetailsAttrView(); - $.extend(this.businessMetadataDefCollection.queryParams, { count: this.limit }); - this.businessMetadataDefCollection.fullCollection.sort({ silent: true }); - this.renderTableLayoutView(); - this.$('.tableOverlay').hide(); - this.$('.auditTable').show(); // Only for first time table show because we never hide after first render. - this.businessMetadataDefCollection.comparator = function(model) { - return -model.get('timestamp'); - } - }, - toggleBusinessMetadataDetailsAttrView: function() { - var that = this; - if (that.showDetails) { - that.ui.businessMetadataAttrPage.hide(); - that.ui.businessMetadataDetailPage.show(); - } else { - that.ui.businessMetadataAttrPage.show(); - that.ui.businessMetadataDetailPage.hide(); - } - }, - bindEvents: function() {}, - loaderStatus: function(isActive) { - var that = this; - if (isActive) { - that.$('.businessMetadata-attr-tableOverlay').show(); - that.$('.business-metadata-attr-fontLoader').show(); - } else { - that.$('.businessMetadata-attr-tableOverlay').hide(); - that.$('.business-metadata-attr-fontLoader').hide(); - } - }, - onEditAttr: function(e) { - var that = this, - isAttrEdit = e.currentTarget.dataset && e.currentTarget.dataset.id === 'attributeEdit' ? true : false, - guid = e.currentTarget.dataset && e.currentTarget.dataset.guid ? e.currentTarget.dataset.guid : null, - selectedBusinessMetadata = that.businessMetadataDefCollection.fullCollection.findWhere({ guid: guid }), - attrributes = selectedBusinessMetadata ? selectedBusinessMetadata.get('attributeDefs') : null, - attrName = e.currentTarget.dataset.name ? e.currentTarget.dataset.name : null, - attrDetails = { name: attrName }; - if (selectedBusinessMetadata) { - that.ui.businessMetadataAttrPageOk.text("Save"); - that.newAttr = e.currentTarget && e.currentTarget.dataset.action === "createAttr" ? true : false; - that.guid = guid; - _.each(attrributes, function(attrObj) { - if (attrObj.name === attrName) { - attrDetails = $.extend(true, {}, attrObj); - if (attrObj.typeName.includes('array')) { - attrDetails.typeName = attrObj.typeName.replace("array<", "").replace(">", ""); - attrDetails.multiValued = true; - } - } - }); - - that.showDetails = false; - that.toggleBusinessMetadataDetailsAttrView(); - that.ui.businessMetadataAttrPageOk.attr('data-action', e.currentTarget.dataset.id); - require(["views/business_metadata/CreateBusinessMetadataLayoutView"], function(CreateBusinessMetadataLayoutView) { - that.view = new CreateBusinessMetadataLayoutView({ - onEditCallback: function() { - that.businessMetadataDefCollection.fullCollection.sort({ silent: true }); - that.renderTableLayoutView(); - }, - onUpdateBusinessMetadata: function(fetch) { - that.showDetails = true; - that.toggleBusinessMetadataDetailsAttrView(); - if (fetch) { - enumDefCollection.fetch({ reset: true }); - that.entityDefCollection.fetch({ silent: true }); - } - }, - parent: that.$el, - businessMetadataDefCollection: that.businessMetadataDefCollection, - enumDefCollection: enumDefCollection, - isAttrEdit: isAttrEdit, - typeHeaders: typeHeaders, - attrDetails: attrDetails, - selectedBusinessMetadata: selectedBusinessMetadata, - guid: that.guid, - isNewAttr: that.newAttr - }); - if (isAttrEdit) { - that.ui.businessMetadataAttrPageTitle.text("Update Attribute of: " + selectedBusinessMetadata.get('name')); - } else { - that.ui.businessMetadataAttrPageTitle.text("Add Business Metadata Attribute for: " + selectedBusinessMetadata.get('name')); - } - - that.RModal.show(that.view); - }); - } - }, - onClickCreateBusinessMetadata: function(e) { - var that = this, - isNewBusinessMetadata = true; - that.showDetails = false; - that.ui.businessMetadataAttrPageOk.text("Create"); - that.ui.businessMetadataAttrPageOk.attr('data-action', 'createBusinessMetadata'); - that.ui.businessMetadataAttrPageTitle.text("Create Business Metadata"); - that.toggleBusinessMetadataDetailsAttrView(); - require(["views/business_metadata/CreateBusinessMetadataLayoutView"], function(CreateBusinessMetadataLayoutView) { - that.view = new CreateBusinessMetadataLayoutView({ - onUpdateBusinessMetadata: function(fetch) { - that.showDetails = true; - that.toggleBusinessMetadataDetailsAttrView(); - if (fetch) { - enumDefCollection.fetch({ reset: true }); - that.entityDefCollection.fetch({ silent: true }); - } - }, - businessMetadataDefCollection: that.businessMetadataDefCollection, - enumDefCollection: enumDefCollection, - typeHeaders: typeHeaders, - isNewBusinessMetadata: isNewBusinessMetadata - }); - that.RModal.show(that.view); - }); - }, - renderTableLayoutView: function() { - var that = this; - require(['utils/TableLayout'], function(TableLayout) { - var cols = new Backgrid.Columns(that.getBusinessMetadataTableColumns()); - that.RBusinessMetadataTableLayoutView.show(new TableLayout(_.extend({}, that.commonTableOptions, { - columns: cols - }))); - if (!(that.businessMetadataDefCollection.models.length < that.limit)) { - that.RBusinessMetadataTableLayoutView.$el.find('table tr').last().hide(); - } - - }); - }, - getBusinessMetadataTableColumns: function() { - var that = this; - return this.businessMetadataDefCollection.constructor.getTableCols({ - attributeDefs: { - label: "", - cell: "html", - editable: false, - sortable: false, - cell: Backgrid.ExpandableCell, - fixWidth: "20", - accordion: false, - alwaysVisible: true, - expand: function(el, model) { - el.attr('colspan', '8'); - var attrValues = '', - attrTable = $('table'), - attrTableBody = $('tbody'), - attrTableHeading = "AttributeTypeSearch WeightEnable MultivaluesMax LengthApplicable Type(s)Action", - attrRow = '', - attrTableDetails = ''; - if (model.attributes && model.attributes.attributeDefs.length) { - _.each(model.attributes.attributeDefs, function(attrObj) { - var applicableEntityTypes = '', - typeName = attrObj.typeName, - multiSelect = '', - maxString = 'NA'; - if (attrObj.options && attrObj.options.applicableEntityTypes) { - var entityTypes = JSON.parse(attrObj.options.applicableEntityTypes); - _.each(entityTypes, function(values) { - applicableEntityTypes += ''; - }) - } - if (typeName.includes('array')) { - typeName = _.escape(typeName); - multiSelect = 'checked'; - } - if (typeName.includes('string') && attrObj.options && attrObj.options.maxStrLength) { - maxString = attrObj.options.maxStrLength; - } - - attrRow += " " + _.escape(attrObj.name) + "" + typeName + "" + _.escape(attrObj.searchWeight) + " " + maxString + "" + applicableEntityTypes + "
        Edit
        "; - }); - var adminText = '
        ' + attrTableHeading + attrRow + '
        '; - $(el).append($('
        ').html(adminText)); - } else { - var adminText = '
        No attributes to show.
        '; - $(el).append($('
        ').html(adminText)); - } - } - }, - name: { - label: "Name", - cell: "html", - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return '' + model.get('name') + ''; - } - }) - }, - description: { - label: "Description", - cell: "html", - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return _.escape(model.get('description')); - } - }) - }, - createdBy: { - label: "Created by", - cell: "html", - renderable: false, - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return model.get('updatedBy'); - } - }) - }, - createTime: { - label: "Created on", - cell: "html", - renderable: false, - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return Utils.formatDate({ date: model.get('createTime') }); - } - }) - }, - updatedBy: { - label: "Updated by", - cell: "html", - renderable: false, - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return model.get('updatedBy'); - } - }) - }, - updateTime: { - label: "Updated on", - cell: "html", - renderable: false, - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return Utils.formatDate({ date: model.get('updateTime') }); - } - }) - }, - tools: { - label: "Action", - cell: "html", - sortable: false, - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return ""; - } - }) - } - }, this.businessMetadataDefCollection); - }, - deleteBusinessMetadataElement: function(businessMetadataName) { - var that = this, - notifyObj = { - modal: true, - ok: function(argument) { - that.onNotifyDeleteOk(); - }, - cancel: function(argument) {} - }; - var text = "Are you sure you want to delete the business metadata"; - notifyObj["text"] = text; - Utils.notifyConfirm(notifyObj); - }, - onNotifyDeleteOk: function(data) { - var that = this, - deleteBusinessMetadataData = that.businessMetadataDefCollection.fullCollection.findWhere({ guid: that.guid }); - that.$('.tableOverlay').show(); - if (deleteBusinessMetadataData) { - var businessMetadataName = deleteBusinessMetadataData.get("name"); - deleteBusinessMetadataData.deleteBusinessMetadata({ - typeName: businessMetadataName, - success: function() { - Utils.notifySuccess({ - content: "Business Metadata " + businessMetadataName + Messages.getAbbreviationMsg(false, 'deleteSuccessMessage') - }); - that.businessMetadataDefCollection.fullCollection.remove(deleteBusinessMetadataData); - that.businessMetadataDefCollection.fullCollection.sort({ silent: true }); - that.renderTableLayoutView(); - that.showDetails = true; - that.toggleBusinessMetadataDetailsAttrView(); - that.loaderStatus(false); - }, - complete: function() { - that.$('.tableOverlay').hide(); - that.$('.position-relative .fontLoader').removeClass('show'); - } - }); - } else { - Utils.notifyError({ - content: Messages.defaultErrorMessage - }); - } - } - }); - return BusinessMetadataTableLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/business_metadata/CreateBusinessMetadataLayoutView.js b/dashboardv2/public/js/views/business_metadata/CreateBusinessMetadataLayoutView.js deleted file mode 100644 index 21bb663ab25..00000000000 --- a/dashboardv2/public/js/views/business_metadata/CreateBusinessMetadataLayoutView.js +++ /dev/null @@ -1,321 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/business_metadata/CreateBusinessMetadataLayoutView_tmpl', - 'utils/Utils', - 'utils/Messages', - 'views/business_metadata/BusinessMetadataAttributeItemView', - 'models/VEntity' -], function(require, Backbone, CreateBusinessMetadataLayoutViewTmpl, Utils, Messages, BusinessMetadataAttributeItemView, VEntity) { - - var CreateBusinessMetadataLayoutView = Backbone.Marionette.CompositeView.extend( - /** @lends CreateBusinessMetadataLayoutView */ - { - _viewName: 'CreateBusinessMetadataLayoutView', - - template: CreateBusinessMetadataLayoutViewTmpl, - - templateHelpers: function() { - return { - create: this.create, - description: this.description, - fromTable: this.fromTable, - isEditAttr: this.isEditAttr - }; - }, - - /** Layout sub regions */ - regions: {}, - - childView: BusinessMetadataAttributeItemView, - - childViewContainer: "[data-id='addAttributeDiv']", - - childViewOptions: function() { - return { - typeHeaders: this.typeHeaders, - businessMetadataDefCollection: this.businessMetadataDefCollection, - enumDefCollection: this.enumDefCollection, - isAttrEdit: this.isAttrEdit, - viewId: this.cid, - collection: this.collection - }; - }, - /** ui selector cache */ - ui: { - name: "[data-id='name']", - description: "[data-id='description']", - title: "[data-id='title']", - attributeData: "[data-id='attributeData']", - addAttributeDiv: "[data-id='addAttributeDiv']", - createForm: '[data-id="createForm"]', - businessMetadataAttrPageCancle: '[data-id="businessMetadataAttrPageCancle"]', - businessMetadataAttrPageOk: '[data-id="businessMetadataAttrPageOk"]' - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.attributeData] = "onClickAddAttriBtn"; - events["click " + this.ui.businessMetadataAttrPageOk] = function(e) { - var that = this, - modal = that.$el; - if (e.target.dataset.action == "attributeEdit" || e.target.dataset.action == "addAttribute") { - that.onUpdateAttr(); - } else { - that.onCreateBusinessMetadata(); - } - - }; - events["click " + this.ui.businessMetadataAttrPageCancle] = function(e) { - this.options.onUpdateBusinessMetadata(); - }; - return events; - }, - /** - * intialize a new CreateBusinessMetadataLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'businessMetadataDefCollection', 'selectedBusinessMetadata', 'enumDefCollection', 'model', 'isNewBusinessMetadata', 'isAttrEdit', 'typeHeaders', 'attrDetails')); - this.fromTable = this.isNewBusinessMetadata ? true : false; - this.isEditAttr = this.isAttrEdit ? false : true; - this.businessMetadataModel = new VEntity(); - if (this.model) { - this.description = this.model.get('description'); - } else { - this.create = true; - } - if (!this.isNewBusinessMetadata) { - this.collection = this.isAttrEdit ? new Backbone.Collection([ - this.attrDetails - ]) : new Backbone.Collection([{ - "name": "", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": true - }]); - } else { - this.collection = new Backbone.Collection(); - } - - }, - bindEvents: function() {}, - onRender: function() { - var that = this; - this.$('.fontLoader').show(); - if (!('placeholder' in HTMLInputElement.prototype)) { - this.ui.createForm.find('input,textarea').placeholder(); - } - if (this.isNewBusinessMetadata == true) { - that.ui.businessMetadataAttrPageOk.text("Create"); - that.ui.businessMetadataAttrPageOk.attr('data-action', 'newBusinessMetadata'); - } else { - that.ui.businessMetadataAttrPageOk.text("Save"); - that.ui.businessMetadataAttrPageOk.attr('data-action', 'attributeEdit'); - } - this.hideLoader(); - }, - hideLoader: function() { - this.$('.fontLoader').hide(); - this.$('.hide').removeClass('hide'); - }, - collectionAttribute: function() { - this.collection.add(new Backbone.Model({ - "name": "", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": true - })); - }, - onClickAddAttriBtn: function() { - this.collectionAttribute(); - if (!('placeholder' in HTMLInputElement.prototype)) { - this.ui.addAttributeDiv.find('input,textarea').placeholder(); - } - }, - loaderStatus: function(isActive) { - var that = this; - if (isActive) { - parent.$('.business-metadata-attr-tableOverlay').show(); - parent.$('.business-metadata-attr-fontLoader').show(); - } else { - parent.$('.business-metadata-attr-tableOverlay').hide(); - parent.$('.business-metadata-attr-fontLoader').hide(); - } - }, - validateValues: function(attributeDefs) { - var isValidate = true, - isAttrDuplicate = true, - validationFileds = this.$el.find('.require'), - attrNames = []; - if (attributeDefs && !this.isAttrEdit) { - attrNames = _.map(attributeDefs, function(model) { - return model.name.toLowerCase(); - }); - } - validationFileds.each(function(elements) { - $(this).removeClass('errorValidate'); - if (validationFileds[elements].value.trim() == '' || validationFileds[elements].value == null) { - if (validationFileds[elements].style.display != 'none') { - $(validationFileds[elements]).addClass('errorValidate'); - $(this).addClass('errorValidate'); - if (isValidate) { isValidate = false; } - } - } - }); - if (isValidate) { - this.$el.find('.attributeInput').each(function(element) { - var attrValue = this.value.toLowerCase(); - if (attrNames.indexOf(attrValue) > -1) { - Utils.notifyInfo({ - content: "Attribute name already exist" - }); - $(this).addClass('errorValidate'); - if (isAttrDuplicate) { isAttrDuplicate = false; } - } else { - if (attrValue.length) { - attrNames.push(attrValue); - } - } - }); - } - - if (!isValidate) { - Utils.notifyInfo({ - content: "Please fill the details" - }); - return true; - } - if (!isAttrDuplicate) { - return true; - } - - }, - onCreateBusinessMetadata: function() { - var that = this; - if (this.validateValues()) { - return; - }; - this.loaderStatus(true); - var name = this.ui.name.val(), - description = this.ui.description.val(); - var attributeObj = this.collection.toJSON(); - if (this.collection.length === 1 && this.collection.first().get("name") === "") { - attributeObj = []; - } - this.json = { - "enumDefs": [], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [], - "businessMetadataDefs": [{ - "category": "BUSINESS_METADATA", - "createdBy": "admin", - "updatedBy": "admin", - "version": 1, - "typeVersion": "1.1", - "name": name.trim(), - "description": description.trim(), - "attributeDefs": attributeObj - }] - }; - var apiObj = { - sort: false, - data: this.json, - success: function(model, response) { - var nameSpaveDef = model.businessMetadataDefs; - if (nameSpaveDef) { - that.businessMetadataDefCollection.fullCollection.add(nameSpaveDef); - Utils.notifySuccess({ - content: "Business Metadata " + name + Messages.getAbbreviationMsg(false, 'addSuccessMessage') - }); - } - that.options.onUpdateBusinessMetadata(true); - }, - silent: true, - reset: true, - complete: function(model, status) { - that.loaderStatus(false); - } - } - apiObj.type = "POST"; - that.businessMetadataModel.saveBusinessMetadata(apiObj); - }, - onUpdateAttr: function() { - var that = this, - selectedBusinessMetadataClone = $.extend(true, {}, that.selectedBusinessMetadata.toJSON()), - attributeDefs = selectedBusinessMetadataClone['attributeDefs'], - isvalidName = true; - if (this.validateValues(attributeDefs)) { - return; - }; - if (this.collection.length > 0) { - this.loaderStatus(true); - if (selectedBusinessMetadataClone.attributeDefs === undefined) { - selectedBusinessMetadataClone.attributeDefs = []; - } - selectedBusinessMetadataClone.attributeDefs = selectedBusinessMetadataClone.attributeDefs.concat(this.collection.toJSON()); - this.json = { - "enumDefs": [], - "structDefs": [], - "classificationDefs": [], - "entityDefs": [], - "businessMetadataDefs": [selectedBusinessMetadataClone] - }; - var apiObj = { - sort: false, - data: this.json, - success: function(model, response) { - Utils.notifySuccess({ - content: "One or more Business Metadata attribute" + Messages.getAbbreviationMsg(true, 'editSuccessMessage') - }); - if (model.businessMetadataDefs && model.businessMetadataDefs.length) { - that.selectedBusinessMetadata.set(model.businessMetadataDefs[0]); - } - that.options.onEditCallback(); - that.options.onUpdateBusinessMetadata(true); - }, - silent: true, - reset: true, - complete: function(model, status) { - that.loaderStatus(false); - } - } - apiObj.type = "PUT"; - that.businessMetadataModel.saveBusinessMetadata(apiObj); - } else { - Utils.notifySuccess({ - content: "No attribute updated" - }); - this.loaderStatus(false); - that.options.onUpdateBusinessMetadata(); - } - } - }); - return CreateBusinessMetadataLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/business_metadata/EnumCreateUpdateItemView.js b/dashboardv2/public/js/views/business_metadata/EnumCreateUpdateItemView.js deleted file mode 100644 index 9cbebbe12a6..00000000000 --- a/dashboardv2/public/js/views/business_metadata/EnumCreateUpdateItemView.js +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -define(["require", "backbone", "hbs!tmpl/business_metadata/EnumCreateUpdateItemView_tmpl", "utils/Utils", "utils/UrlLinks"], function( - require, - Backbone, - EnumCreateUpdateItemViewTmpl, - Utils, - UrlLinks -) { - "use strict"; - - return Backbone.Marionette.ItemView.extend( - /** @lends GlobalExclusionListView */ - { - template: EnumCreateUpdateItemViewTmpl, - - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - enumTypeSelectorContainer: "[data-id='enumTypeSelectorContainer']", - enumSelector: "[data-id='enumSelector']", - enumValueSelectorContainer: "[data-id='enumValueSelectorContainer']", - valueSelector: "[data-id='valueSelector']", - enumCancleBtn: "[data-id='enumCancleBtn']", - enumOkBtn: "[data-id='enumOkBtn']" - }, - /** ui events hash */ - events: function() { - var events = {}; - events["change " + this.ui.enumSelector] = function(e) { - this.model.set({ enumValues: e.target.value.trim() }); - }; - events["change " + this.ui.enumSelector] = function(e) { - var emumValue = this.ui.enumSelector.select2("data")[0] ? - this.ui.enumSelector.select2("data")[0].text : - this.ui.enumSelector.val(); - if (emumValue == "" || emumValue == null) { - this.ui.enumValueSelectorContainer.hide(); - } else { - this.ui.enumValueSelectorContainer.show(); - this.showEnumValues(emumValue); - } - }; - events["change " + this.ui.valueSelector] = function(e) {}; - events["click " + this.ui.enumCancleBtn] = function(e) { - if (this.options.closeModal) { - this.options.closeModal(); - return; - } - this.ui.enumValueSelectorContainer.hide(); - this.ui.enumSelector.val("").trigger("change"); - this.ui.enumCancleBtn.attr("disabled", "true"); - }; - events["click " + this.ui.enumOkBtn] = function(e) { - this.ui.enumCancleBtn.attr("disabled", "true"); - this.onUpdateEnum(); - }; - return events; - }, - - /** - * intialize a new GlobalExclusionComponentView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, "businessMetadataDefCollection", "enumDefCollection")); - }, - onRender: function() { - this.ui.enumValueSelectorContainer.hide(); - this.bindEvents(); - this.emumTypeSelectDisplay(); - if (!this.options.closeModal) { - this.ui.enumCancleBtn.attr("disabled", "true"); - this.ui.enumCancleBtn.text("Clear"); - } - }, - bindEvents: function() { - var that = this; - this.listenTo(this.enumDefCollection, 'reset', function() { - that.emumTypeSelectDisplay(); - }) - }, - - showEnumValues: function(enumName) { - var enumValues = "", - selectedValues = [], - selectedEnum = this.enumDefCollection.fullCollection.findWhere({ name: enumName }), - selectedEnumValues = selectedEnum ? selectedEnum.get("elementDefs") : null; - _.each(selectedEnumValues, function(enumVal, index) { - selectedValues.push(enumVal.value); - enumValues += ""; - }); - - this.ui.enumCancleBtn.removeAttr("disabled"); - this.ui.valueSelector.empty(); - this.ui.valueSelector.append(enumValues); - this.ui.valueSelector.val(selectedValues); - this.ui.valueSelector.select2({ - placeholder: "Select Enum value", - allowClear: false, - tags: true, - multiple: true - }); - }, - emumTypeSelectDisplay: function() { - var enumTypes = ""; - this.enumDefCollection.fullCollection.each(function(model, index) { - enumTypes += ""; - }); - this.ui.enumSelector.empty(); - this.ui.enumSelector.append(enumTypes); - this.ui.enumSelector.val(""); - this.ui.enumSelector.select2({ - placeholder: "Select Enum name", - tags: true, - allowClear: true, - multiple: false, - templateResult: this.formatSearchResult - }); - }, - formatSearchResult: function(state) { - if (!state.id) { - return state.text; - } - if (!state.element) { - return $("Create new enum : " + _.escape(state.text) + ""); - } else { - return $("" + _.escape(state.text) + ""); - } - }, - validationEnum: function() { - var selectedEnumName = this.ui.enumSelector.val(), - selectedEnumValues = this.ui.valueSelector.val(); - - if (selectedEnumName == "" || selectedEnumName == null) { - this.ui.enumOkBtn.hideButtonLoader(); - Utils.notifyInfo({ - content: "Please enter the Enumeration Name" - }); - return true; - } - if (selectedEnumValues == "" || selectedEnumValues == null) { - this.ui.enumOkBtn.hideButtonLoader(); - Utils.notifyInfo({ - content: "Please enter the Enum values" - }); - return true; - } - }, - onUpdateEnum: function(view, modal) { - var that = this, - selectedEnumName = this.ui.enumSelector.val(), - selectedEnumValues = this.ui.valueSelector.val(), - enumName = this.enumDefCollection.fullCollection.findWhere({ name: selectedEnumName }), - isPutCall = false, - isPostCallEnum = false, - enumDefs = []; - if (this.validationEnum()) { - return; - } - this.ui.enumOkBtn.showButtonLoader(); - this.ui.enumSelector.attr("disabled", "true"); - this.ui.valueSelector.attr("disabled", "true"); - this.ui.enumCancleBtn.attr("disabled", "true"); - if (enumName) { - var enumDef = enumName.get("elementDefs"); - if (enumDef.length === selectedEnumValues.length) { - _.each(enumDef, function(enumVal, index) { - if (selectedEnumValues.indexOf(enumVal.value) === -1) { - isPutCall = true; - } - }); - } else { - isPutCall = true; - } - } else { - isPostCallEnum = true; - } - var elementValues = []; - _.each(selectedEnumValues, function(inputEnumVal, index) { - elementValues.push({ - ordinal: index + 1, - value: inputEnumVal - }); - }); - - enumDefs.push({ - name: selectedEnumName, - elementDefs: elementValues - }); - - this.json = { - enumDefs: enumDefs - }; - var apiObj = { - sort: false, - success: function(model, response) { - that.ui.enumValueSelectorContainer.hide(); - if (isPostCallEnum) { - that.enumDefCollection.add(model.enumDefs[0]); - Utils.notifySuccess({ - content: "Enumeration " + selectedEnumName + " added successfully" - }); - } else { - var foundEnum = that.enumDefCollection.fullCollection.find({ guid: model.enumDefs[0].guid }) - if (foundEnum) { - foundEnum.set(model.enumDefs[0]); - } - Utils.notifySuccess({ - content: "Enumeration " + selectedEnumName + " updated successfully" - }); - } - that.enumDefCollection.fetch({ reset: true }); - if (that.options.onUpdateEnum) { //callback from BusinessMetadataAttributeItemView - that.options.onUpdateEnum(); - } - that.ui.enumCancleBtn.attr("disabled", "true"); - }, - silent: true, - reset: true, - complete: function(model, status) { - that.emumTypeSelectDisplay(); - that.ui.enumOkBtn.hideButtonLoader(); - that.ui.enumSelector.removeAttr("disabled"); - that.ui.valueSelector.removeAttr("disabled"); - if (that.options.closeModal) { - that.options.closeModal(); - } - } - }; - $.extend(apiObj, { contentType: "application/json", dataType: "json", data: JSON.stringify(this.json) }); - if (isPostCallEnum) { - this.businessMetadataDefCollection.constructor.nonCrudOperation.call(this, UrlLinks.typedefsUrl().defs, "POST", apiObj); - } else if (isPutCall) { - this.businessMetadataDefCollection.constructor.nonCrudOperation.call(this, UrlLinks.typedefsUrl().defs, "PUT", apiObj); - } else { - Utils.notifySuccess({ - content: "No updated values" - }); - that.ui.enumOkBtn.hideButtonLoader(); - that.ui.enumSelector.removeAttr("disabled"); - that.ui.valueSelector.removeAttr("disabled"); - if (that.options.closeModal) { - that.options.closeModal(); - } - } - } - } - ); -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/common/BackgridHeader.js b/dashboardv2/public/js/views/common/BackgridHeader.js deleted file mode 100644 index 69354ffcf9a..00000000000 --- a/dashboardv2/public/js/views/common/BackgridHeader.js +++ /dev/null @@ -1,267 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'underscore', - 'utils/Utils', - 'utils/Globals', - 'backgrid-filter', - 'backgrid-paginator', - 'select2', -], function(require, Backbone, _, Utils) { - 'use strict'; - - var HeaderSearchCell = Backbone.View.extend({ - - tagName: 'td', - - className: 'backgrid-filter', - - template: _.template(' placeholder="<%- placeholder %>" <% } %> name="<%- name %>" <% if (style) { %> style="<%- style %>" <% } %> />'), - //×'), - - placeholder: '', - - events: { - 'keyup input': 'evKeyUp', - 'submit': 'search' - }, - - initialize: function(options) { - _.extend(this, _.pick(options, 'column')); - this.name = this.column.get('name'); - if (this.column.get('reName') !== undefined) - this.name = this.column.get('reName'); - - var collection = this.collection, - self = this; - if (Backbone.PageableCollection && collection instanceof Backbone.PageableCollection) { - collection.queryParams[this.name] = function() { - return self.searchBox().val() || null; - }; - } - }, - - render: function() { - this.$el.empty().append(this.template({ - name: this.column.get('name'), - placeholder: this.column.get('placeholder') || 'Search', - style: this.column.get('headerSearchStyle') - })); - this.$el.addClass('renderable'); - this.delegateEvents(); - return this; - - }, - - evKeyUp: function(e) { - var $clearButton = this.clearButton(); - var searchTerms = this.searchBox().val(); - - if (!e.shiftKey) { - this.search(); - } - - if (searchTerms) { - $clearButton.show(); - } else { - $clearButton.hide(); - } - }, - - searchBox: function() { - return this.$el.find('input[type=search]'); - }, - - clearButton: function() { - return this.$el.find('.clear'); - }, - - search: function() { - var data = {}; - // go back to the first page on search - var collection = this.collection; - if (Backbone.PageableCollection && - collection instanceof Backbone.PageableCollection && - collection.mode === 'server') { - collection.state.currentPage = collection.state.firstPage; - } - var query = this.searchBox().val(); - if (query) data[this.name] = query; - if (collection.extraSearchParams) { - _.extend(data, collection.extraSearchParams); - } - if (collection.mode === 'server') { - collection.fetch({ - data: data, - reset: true, - success: function() {}, - error: function(msResponse) { - Utils.notifyError('Error', 'Invalid input data!'); - } - }); - } else if (collection.mode === 'client') { - - } - }, - - clear: function(e) { - if (e) e.preventDefault(); - this.searchBox().val(null); - this.collection.fetch({ - reset: true - }); - } - }); - - var HeaderFilterCell = Backbone.View.extend({ - - tagName: 'td', - - className: 'backgrid-filter', - - template: _.template(''), - - placeholder: '', - events: { - 'click': function() {}, - }, - initialize: function(options) { - _.extend(this, _.pick(options, 'column')); - this.name = this.column.get('name'); - this.headerFilterOptions = this.column.get('headerFilterOptions'); - }, - render: function() { - var that = this; - this.$el.empty().append(this.template({ - name: this.column.get('name'), - list: this.headerFilterOptions.filterList, - })); - - this.$el.find('select').select2({ - allowClear: true, - closeOnSelect: false, - width: this.headerFilterOptions.filterWidth || '100%', - height: this.headerFilterOptions.filterHeight || '20px', - }); - - this.$el.addClass('renderable'); - - this.$el.find('select').on('click', function(e) { - that.search(e.currentTarget.value); - }); - return this; - }, - search: function(selectedOptionValue) { - var data = {}, - query; - // go back to the first page on search - var collection = this.collection; - if (Backbone.PageableCollection && - collection instanceof Backbone.PageableCollection && - collection.mode === 'server') { - collection.state.currentPage = collection.state.firstPage; - } - if (selectedOptionValue !== 'ALL') { - query = selectedOptionValue; - } - if (query) { - data[this.name] = query; - } - if (collection.extraSearchParams) { - _.extend(data, collection.extraSearchParams); - } - collection.fetch({ - data: data, - reset: true - }); - }, - /*clear: function (e) { - if (e) e.preventDefault(); - this.searchBox().val(null); - this.collection.fetch({reset: true}); - }*/ - }); - var HeaderRow = Backgrid.Row.extend({ - requiredOptions: ['columns', 'collection'], - - initialize: function() { - Backgrid.Row.prototype.initialize.apply(this, arguments); - }, - makeCell: function(column, options) { - var headerCell; - switch (true) { - case (column.has('canHeaderSearch') && column.get('canHeaderSearch') === true): - headerCell = new HeaderSearchCell({ - column: column, - collection: this.collection, - }); - break; - case (column.has('canHeaderFilter') && column.get('canHeaderFilter') === true): - headerCell = new HeaderFilterCell({ - column: column, - collection: this.collection, - }); - break; - default: - headerCell = new Backbone.View({ - tagName: 'td' - }); - } - return headerCell; - } - }); - var Header = Backgrid.Header.extend({ - - initialize: function(options) { - var args = Array.prototype.slice.apply(arguments); - Backgrid.Header.prototype.initialize.apply(this, args); - - this.searchRow = new HeaderRow({ - columns: this.columns, - collection: this.collection - }); - }, - /** - Renders this table head with a single row of header cells. - */ - render: function() { - var args = Array.prototype.slice.apply(arguments); - Backgrid.Header.prototype.render.apply(this, args); - - this.$el.append(this.searchRow.render().$el); - return this; - }, - remove: function() { - var args = Array.prototype.slice.apply(arguments); - Backgrid.Header.prototype.remove.apply(this, args); - - this.searchRow.remove.apply(this.searchRow, arguments); - return Backbone.View.prototype.remove.apply(this, arguments); - } - }); - return Header; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js b/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js deleted file mode 100644 index bb629b4e4ac..00000000000 --- a/dashboardv2/public/js/views/detail_page/DetailPageLayoutView.js +++ /dev/null @@ -1,679 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/detail_page/DetailPageLayoutView_tmpl', - 'utils/Utils', - 'utils/CommonViewFunction', - 'utils/Globals', - 'utils/Enums', - 'utils/Messages', - 'utils/UrlLinks', - 'collection/VEntityList' -], function(require, Backbone, DetailPageLayoutViewTmpl, Utils, CommonViewFunction, Globals, Enums, Messages, UrlLinks, VEntityList) { - 'use strict'; - - var DetailPageLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends DetailPageLayoutView */ - { - _viewName: 'DetailPageLayoutView', - - template: DetailPageLayoutViewTmpl, - - /** Layout sub regions */ - regions: { - REntityDetailTableLayoutView: "#r_entityDetailTableLayoutView", - RSchemaTableLayoutView: "#r_schemaTableLayoutView", - RTagTableLayoutView: "#r_tagTableLayoutView", - RLineageLayoutView: "#r_lineageLayoutView", - RAuditTableLayoutView: "#r_auditTableLayoutView", - RPendingTaskTableLayoutView: "#r_pendingTaskTableLayoutView", - RReplicationAuditTableLayoutView: "#r_replicationAuditTableLayoutView", - RProfileLayoutView: "#r_profileLayoutView", - RRelationshipLayoutView: "#r_relationshipLayoutView", - REntityUserDefineView: "#r_entityUserDefineView", - REntityLabelDefineView: "#r_entityLabelDefineView", - REntityBusinessMetadataView: "#r_entityBusinessMetadataView" - }, - /** ui selector cache */ - ui: { - tagClick: '[data-id="tagClick"]', - pTagCountClick: '[data-id="pTagCountClick"]', - termClick: '[data-id="termClick"]', - propagatedTagDiv: '[data-id="propagatedTagDiv"]', - title: '[data-id="title"]', - description: '[data-id="description"]', - editBox: '[data-id="editBox"]', - deleteTag: '[data-id="deleteTag"]', - deleteTerm: '[data-id="deleteTerm"]', - addTag: '[data-id="addTag"]', - addTerm: '[data-id="addTerm"]', - tagList: '[data-id="tagList"]', - termList: '[data-id="termList"]', - propagatedTagList: '[data-id="propagatedTagList"]', - tablist: '[data-id="tab-list"] li', - entityIcon: '[data-id="entityIcon"]' - }, - templateHelpers: function() { - return { - entityUpdate: Globals.entityUpdate, - isTasksEnabled: Globals.isTasksEnabled - }; - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.tagClick] = function(e) { - if (e.target.nodeName.toLocaleLowerCase() != "i") { - Utils.setUrl({ - url: '#!/tag/tagAttribute/' + e.currentTarget.textContent, - mergeBrowserUrl: false, - trigger: true - }); - } - }; - events["click " + this.ui.pTagCountClick] = function(e) { - var tag = $(e.currentTarget).parent().children().first().text(); - Utils.setUrl({ - url: '#!/detailPage/' + this.id + '?tabActive=classification&filter=' + tag, - mergeBrowserUrl: false, - trigger: true - }); - }; - events["click " + this.ui.termClick] = function(e) { - if (e.target.nodeName.toLocaleLowerCase() != "i") { - Utils.setUrl({ - url: '#!/glossary/' + $(e.currentTarget).find('i').data('guid'), - mergeBrowserUrl: false, - urlParams: { gType: "term", viewType: "term", fromView: "entity" }, - trigger: true - }); - } - }; - events["click " + this.ui.addTerm] = 'onClickAddTermBtn'; - events["click " + this.ui.deleteTag] = 'onClickTagCross'; - events["click " + this.ui.deleteTerm] = 'onClickTermCross'; - events["click " + this.ui.addTag] = 'onClickAddTagBtn'; - events["click " + this.ui.tablist] = function(e) { - var tabValue = $(e.currentTarget).attr('role'); - Utils.setUrl({ - url: Utils.getUrlState.getQueryUrl().queyParams[0], - urlParams: { tabActive: tabValue || 'properties' }, - mergeBrowserUrl: false, - trigger: false, - updateTabState: true - }); - - }; - - return events; - }, - /** - * intialize a new DetailPageLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'value', 'collection', 'id', 'entityDefCollection', 'typeHeaders', 'enumDefCollection', 'classificationDefCollection', 'glossaryCollection', 'businessMetadataDefCollection', 'searchVent')); - $('body').addClass("detail-page"); - this.collection = new VEntityList([], {}); - this.collection.url = UrlLinks.entitiesApiUrl({ guid: this.id, minExtInfo: true }); - this.fetchCollection(); - }, - bindEvents: function() { - var that = this; - this.listenTo(this.collection, 'reset', function() { - this.entityObject = this.collection.first().toJSON(); - var collectionJSON = this.entityObject.entity; - this.activeEntityDef = this.entityDefCollection.fullCollection.find({ name: collectionJSON.typeName }); - if (!this.activeEntityDef) { - Utils.backButtonClick(); - Utils.notifyError({ - content: "Unknown Entity-Type" - }); - return true; - } - if (collectionJSON && _.startsWith(collectionJSON.typeName, "AtlasGlossary")) { - this.$(".termBox").hide(); - } - // MergerRefEntity. - Utils.findAndMergeRefEntity({ - attributeObject: collectionJSON.attributes, - referredEntities: this.entityObject.referredEntities - }); - - Utils.findAndMergeRefEntity({ - attributeObject: collectionJSON.relationshipAttributes, - referredEntities: this.entityObject.referredEntities - }); - - Utils.findAndMergeRelationShipEntity({ - attributeObject: collectionJSON.attributes, - relationshipAttributes: collectionJSON.relationshipAttributes - }); - - // check if entity is process - var isProcess = false, - typeName = Utils.getName(collectionJSON, 'typeName'), - superTypes = Utils.getNestedSuperTypes({ data: this.activeEntityDef.toJSON(), collection: this.entityDefCollection }), - isLineageRender = _.find(superTypes, function(type) { - if (type === "DataSet" || type === "Process") { - if (type === "Process") { - isProcess = true; - } - return true; - } - }); - if (!isLineageRender) { - isLineageRender = (typeName === "DataSet" || typeName === "Process") ? true : null; - } - - if (collectionJSON && collectionJSON.guid) { - var tagGuid = collectionJSON.guid; - this.readOnly = Enums.entityStateReadOnly[collectionJSON.status]; - } else { - var tagGuid = this.id; - } - if (this.readOnly) { - this.$el.addClass('readOnly'); - } else { - this.$el.removeClass('readOnly'); - } - if (collectionJSON) { - this.name = Utils.getName(collectionJSON); - if (collectionJSON.attributes) { - if (collectionJSON.typeName) { - collectionJSON.attributes.typeName = _.escape(collectionJSON.typeName); - } - if (this.name && collectionJSON.typeName) { - this.name = this.name + ' (' + _.escape(collectionJSON.typeName) + ')'; - } - if (!this.name && collectionJSON.typeName) { - this.name = _.escape(collectionJSON.typeName); - } - this.description = collectionJSON.attributes.description; - if (this.name) { - this.ui.title.show(); - var titleName = '' + this.name + ''; - if (this.readOnly) { - titleName += ''; - } - this.ui.title.html(titleName); - if (collectionJSON.attributes.serviceType === undefined) { - if (Globals.serviceTypeMap[collectionJSON.typeName] === undefined && this.activeEntityDef) { - Globals.serviceTypeMap[collectionJSON.typeName] = this.activeEntityDef.get('serviceType'); - } - } else if (Globals.serviceTypeMap[collectionJSON.typeName] === undefined) { - Globals.serviceTypeMap[collectionJSON.typeName] = collectionJSON.attributes.serviceType; - } - var entityData = _.extend({ "serviceType": Globals.serviceTypeMap[collectionJSON.typeName], "isProcess": isProcess }, collectionJSON); - if (this.readOnly) { - this.ui.entityIcon.addClass('disabled'); - } else { - this.ui.entityIcon.removeClass('disabled'); - } - this.ui.entityIcon.attr('title', _.escape(collectionJSON.typeName)).html('').find("img").on('error', function() { - this.src = Utils.getEntityIconPath({ entityData: entityData, errorUrl: this.src }); - }); - } else { - this.ui.title.hide(); - } - if (this.description) { - this.ui.description.show(); - this.ui.description.html('' + _.escape(this.description) + ''); - } else { - this.ui.description.hide(); - } - } - var tags = { - 'self': [], - 'propagated': [], - 'propagatedMap': {}, - 'combineMap': {} - }; - if (collectionJSON.classifications) { - var tagObject = collectionJSON.classifications; - _.each(tagObject, function(val) { - var typeName = val.typeName; - if (val.entityGuid === that.id) { - tags['self'].push(val) - } else { - tags['propagated'].push(val); - if (tags.propagatedMap[typeName]) { - tags.propagatedMap[typeName]["count"]++; - } else { - tags.propagatedMap[typeName] = val; - tags.propagatedMap[typeName]["count"] = 1; - } - } - if (tags.combineMap[typeName] === undefined) { - tags.combineMap[typeName] = val; - } - }); - tags.self = _.sortBy(tags.self, "typeName"); - tags.propagated = _.sortBy(tags.propagated, "typeName"); - this.generateTag(tags); - } else { - this.generateTag([]); - } - if (collectionJSON.relationshipAttributes && collectionJSON.relationshipAttributes.meanings) { - this.generateTerm(collectionJSON.relationshipAttributes.meanings); - } - if (Globals.entityTypeConfList && _.isEmptyArray(Globals.entityTypeConfList)) { - this.editEntity = true; - } else { - if (_.contains(Globals.entityTypeConfList, collectionJSON.typeName)) { - this.editEntity = true; - } - } - if (collectionJSON.attributes && collectionJSON.attributes.columns) { - var valueSorted = _.sortBy(collectionJSON.attributes.columns, function(val) { - return val.attributes && val.attributes.position - }); - collectionJSON.attributes.columns = valueSorted; - } - } - this.hideLoader(); - var obj = { - entity: collectionJSON, - guid: this.id, - entityName: this.name, - typeHeaders: this.typeHeaders, - tags: tags, - entityDefCollection: this.entityDefCollection, - fetchCollection: this.fetchCollection.bind(that), - enumDefCollection: this.enumDefCollection, - classificationDefCollection: this.classificationDefCollection, - glossaryCollection: this.glossaryCollection, - businessMetadataCollection: this.activeEntityDef.get('businessAttributeDefs'), - searchVent: this.searchVent, - attributeDefs: (function() { - return that.getEntityDef(collectionJSON); - })(), - editEntity: this.editEntity || false - } - obj["renderAuditTableLayoutView"] = function() { - that.renderAuditTableLayoutView(obj); - }; - this.renderEntityDetailTableLayoutView(obj); - this.renderEntityUserDefineView(obj); - this.renderEntityLabelDefineView(obj); - if (obj.businessMetadataCollection) { - this.renderEntityBusinessMetadataView(obj); - } - this.renderRelationshipLayoutView(obj); - this.renderAuditTableLayoutView(obj); - this.renderTagTableLayoutView(obj); - if (Globals.isTasksEnabled) { this.renderPendingTaskTableLayoutView(); } - - // To render profile tab check for attribute "profileData" or typeName = "hive_db","hbase_namespace" - if (collectionJSON && (!_.isUndefined(collectionJSON.attributes['profileData']) || collectionJSON.typeName === "hive_db" || collectionJSON.typeName === "hbase_namespace")) { - if (collectionJSON.typeName === "hive_db" || collectionJSON.typeName === "hbase_namespace") { - this.$('.profileTab a').text("Tables") - } - this.$('.profileTab').show(); - this.renderProfileLayoutView(_.extend({}, obj, { - entityDetail: collectionJSON.attributes, - profileData: collectionJSON.attributes.profileData, - typeName: collectionJSON.typeName, - value: that.value - })); - } else { - this.$('.profileTab').hide(); - this.redirectToDefaultTab("profile"); - } - - if (this.activeEntityDef) { - //to display ReplicationAudit tab - if (collectionJSON && collectionJSON.typeName === "AtlasServer") { - this.$('.replicationTab').show(); - this.renderReplicationAuditTableLayoutView(obj); - } else { - this.$('.replicationTab').hide(); - this.redirectToDefaultTab("raudits"); - } - // To render Schema check attribute "schemaElementsAttribute" - var schemaOptions = this.activeEntityDef.get('options'); - var schemaElementsAttribute = schemaOptions && schemaOptions.schemaElementsAttribute; - if (!_.isEmpty(schemaElementsAttribute)) { - this.$('.schemaTable').show(); - this.renderSchemaLayoutView(_.extend({}, obj, { - attribute: collectionJSON.relationshipAttributes[schemaElementsAttribute] || collectionJSON.attributes[schemaElementsAttribute] - })); - } else { - this.$('.schemaTable').hide(); - this.redirectToDefaultTab("schema"); - } - - if (isLineageRender) { - this.$('.lineageGraph').show(); - this.renderLineageLayoutView(_.extend(obj, { - processCheck: isProcess, - fetchCollection: this.fetchCollection.bind(this), - })); - } else { - this.$('.lineageGraph').hide(); - this.redirectToDefaultTab("lineage"); - } - } - - }, this); - this.listenTo(this.collection, 'error', function(model, response) { - this.$('.fontLoader-relative').removeClass('show'); - if (response.responseJSON) { - Utils.notifyError({ - content: response.responseJSON.errorMessage || response.responseJSON.error - }); - } - }, this); - }, - onRender: function() { - var that = this; - this.bindEvents(); - Utils.showTitleLoader(this.$('.page-title .fontLoader'), this.$('.entityDetail')); - this.$('.fontLoader-relative').addClass('show'); // to show tab loader - }, - redirectToDefaultTab: function(tabName) { - var regionRef = null; - switch (tabName) { - case "schema": - regionRef = this.RSchemaTableLayoutView; - break; - case "lineage": - regionRef = this.RLineageLayoutView; - break; - case "raudits": - regionRef = this.RReplicationAuditTableLayoutView; - break; - case "profile": - regionRef = this.RProfileLayoutView; - break; - } - if (regionRef) { - regionRef.destroy(); - regionRef.$el.empty(); - } - if (this.value && this.value.tabActive == tabName || this.$(".tab-content .tab-pane.active").attr("role") === tabName) { - Utils.setUrl({ - url: Utils.getUrlState.getQueryUrl().queyParams[0], - urlParams: { tabActive: 'properties' }, - mergeBrowserUrl: false, - trigger: true, - updateTabState: true - }); - } - }, - manualRender: function(options) { - if (options) { - var oldId = this.id; - _.extend(this, _.pick(options, 'value', 'id')); - if (this.id !== oldId) { - this.collection.url = UrlLinks.entitiesApiUrl({ guid: this.id, minExtInfo: true }); - this.fetchCollection(); - } - this.updateTab(); - } - }, - updateTab: function() { - if (this.value && this.value.tabActive) { - this.$('.nav.nav-tabs').find('[role="' + this.value.tabActive + '"]').addClass('active').siblings().removeClass('active'); - this.$('.tab-content').find('[role="' + this.value.tabActive + '"]').addClass('active').siblings().removeClass('active'); - $("html, body").animate({ scrollTop: (this.$('.tab-content').offset().top + 1200) }, 1000); - } - }, - onShow: function() { - this.updateTab(); - }, - onDestroy: function() { - if (!Utils.getUrlState.isDetailPage()) { - $('body').removeClass("detail-page"); - } - }, - fetchCollection: function() { - this.collection.fetch({ reset: true }); - if (this.searchVent) { - this.searchVent.trigger('entityList:refresh'); - } - }, - getEntityDef: function(entityObj) { - if (this.activeEntityDef) { - var data = this.activeEntityDef.toJSON(); - var attributeDefs = Utils.getNestedSuperTypeObj({ - data: data, - attrMerge: true, - collection: this.entityDefCollection - }); - return attributeDefs; - } else { - return []; - } - }, - onClickTagCross: function(e) { - var that = this, - tagName = $(e.currentTarget).parent().text(), - entityGuid = $(e.currentTarget).data("entityguid"); - CommonViewFunction.deleteTag(_.extend({}, { - guid: that.id, - associatedGuid: that.id != entityGuid ? entityGuid : null, - msg: "
        Remove: " + "" + _.escape(tagName) + " assignment from " + this.name + "?
        ", - titleMessage: Messages.removeTag, - okText: "Remove", - showLoader: that.showLoader.bind(that), - hideLoader: that.hideLoader.bind(that), - tagName: tagName, - callback: function() { - that.fetchCollection(); - } - })); - }, - onClickTermCross: function(e) { - var $el = $(e.currentTarget), - termGuid = $el.data('guid'), - termName = $el.text(), - that = this, - termObj = _.find(this.collection.first().get('entity').relationshipAttributes.meanings, { guid: termGuid }); - CommonViewFunction.removeCategoryTermAssociation({ - termGuid: termGuid, - model: { - guid: that.id, - relationshipGuid: termObj.relationshipGuid - }, - collection: that.glossaryCollection, - msg: "
        Remove: " + "" + _.escape(termName) + " assignment from " + this.name + "?
        ", - titleMessage: Messages.glossary.removeTermfromEntity, - isEntityView: true, - buttonText: "Remove", - showLoader: that.showLoader.bind(that), - hideLoader: that.hideLoader.bind(that), - callback: function() { - that.fetchCollection(); - } - }); - }, - generateTag: function(tagObject) { - var that = this, - tagData = "", - propagatedTagListData = ""; - _.each(tagObject.self, function(val) { - tagData += '' + val.typeName + ''; - }); - _.each(tagObject.propagatedMap, function(val, key) { - propagatedTagListData += '' + val.typeName + '' + (val.count > 1 ? '(' + val.count + ')' : "") + ''; - }); - propagatedTagListData !== "" ? this.ui.propagatedTagDiv.show() : this.ui.propagatedTagDiv.hide(); - this.ui.tagList.find("span.btn").remove(); - this.ui.propagatedTagList.find("span.btn").remove(); - this.ui.tagList.prepend(tagData); - this.ui.propagatedTagList.html(propagatedTagListData); - }, - generateTerm: function(data) { - var that = this, - termData = ""; - _.each(data, function(val) { - termData += '' + _.escape(val.displayText) + ''; - }); - this.ui.termList.find("span.btn").remove(); - this.ui.termList.prepend(termData); - }, - hideLoader: function() { - Utils.hideTitleLoader(this.$('.page-title .fontLoader'), this.$('.entityDetail')); - }, - showLoader: function() { - Utils.showTitleLoader(this.$('.page-title .fontLoader'), this.$('.entityDetail')); - }, - onClickAddTagBtn: function(e) { - var that = this; - require(['views/tag/AddTagModalView'], function(AddTagModalView) { - var tagList = []; - _.map(that.entityObject.entity.classifications, function(obj) { - if (obj.entityGuid === that.id) { - tagList.push(obj.typeName); - } - }); - var view = new AddTagModalView({ - guid: that.id, - tagList: tagList, - callback: function() { - that.fetchCollection(); - }, - showLoader: that.showLoader.bind(that), - hideLoader: that.hideLoader.bind(that), - collection: that.classificationDefCollection, - enumDefCollection: that.enumDefCollection - }); - view.modal.on('ok', function() { - Utils.showTitleLoader(that.$('.page-title .fontLoader'), that.$('.entityDetail')); - }); - }); - }, - assignTermModalView: function(glossaryCollection, obj) { - var that = this, - terms = 0; - _.each(glossaryCollection.fullCollection.models, function(model) { - if (model.get('terms')) { - terms += model.get('terms').length; - }; - }); - if (terms) { - require(['views/glossary/AssignTermLayoutView'], function(AssignTermLayoutView) { - var view = new AssignTermLayoutView({ - guid: obj.guid, - callback: function() { - that.fetchCollection(); - }, - associatedTerms: obj.associatedTerms, - showLoader: that.showLoader.bind(that), - hideLoader: that.hideLoader.bind(that), - glossaryCollection: glossaryCollection - }); - view.modal.on('ok', function() { - Utils.showTitleLoader(that.$('.page-title .fontLoader'), that.$('.entityDetail')); - }); - }); - } else { - Utils.notifyInfo({ - content: "There are no available terms that can be associated with this entity" - }); - } - }, - onClickAddTermBtn: function(e) { - var entityObj = this.collection.first().get('entity'), - obj = { - guid: this.id, - associatedTerms: [], - }; - this.assignTermModalView(this.glossaryCollection, obj); - if (entityObj && entityObj.relationshipAttributes && entityObj.relationshipAttributes.meanings) { - obj.associatedTerms = entityObj.relationshipAttributes.meanings; - } - }, - renderEntityDetailTableLayoutView: function(obj) { - var that = this; - require(['views/entity/EntityDetailTableLayoutView'], function(EntityDetailTableLayoutView) { - that.REntityDetailTableLayoutView.show(new EntityDetailTableLayoutView(obj)); - }); - }, - renderEntityUserDefineView: function(obj) { - var that = this; - require(['views/entity/EntityUserDefineView'], function(EntityUserDefineView) { - that.REntityUserDefineView.show(new EntityUserDefineView(obj)); - }); - }, - renderEntityLabelDefineView: function(obj) { - var that = this; - require(['views/entity/EntityLabelDefineView'], function(EntityLabelDefineView) { - that.REntityLabelDefineView.show(new EntityLabelDefineView(obj)); - }); - }, - renderEntityBusinessMetadataView: function(obj) { - var that = this; - require(['views/entity/EntityBusinessMetaDataView'], function(EntityBusinessMetaDataView) { - that.REntityBusinessMetadataView.show(new EntityBusinessMetaDataView(obj)); - }); - }, - renderTagTableLayoutView: function(obj) { - var that = this; - require(['views/tag/TagDetailTableLayoutView'], function(TagDetailTableLayoutView) { - that.RTagTableLayoutView.show(new TagDetailTableLayoutView(obj)); - }); - }, - renderPendingTaskTableLayoutView: function() { - var that = this; - require(['views/detail_page/PendingTaskTableLayoutView'], function(PendingTaskTableLayoutView) { - that.RPendingTaskTableLayoutView.show(new PendingTaskTableLayoutView()); - }); - }, - renderLineageLayoutView: function(obj) { - var that = this; - require(['views/graph/LineageLayoutView'], function(LineageLayoutView) { - that.RLineageLayoutView.show(new LineageLayoutView(obj)); - }); - }, - renderRelationshipLayoutView: function(obj) { - var that = this; - require(['views/graph/RelationshipLayoutView'], function(RelationshipLayoutView) { - that.RRelationshipLayoutView.show(new RelationshipLayoutView(obj)); - }); - }, - renderSchemaLayoutView: function(obj) { - var that = this; - require(['views/schema/SchemaLayoutView'], function(SchemaLayoutView) { - that.RSchemaTableLayoutView.show(new SchemaLayoutView(obj)); - }); - }, - renderAuditTableLayoutView: function(obj) { - var that = this; - require(['views/audit/AuditTableLayoutView'], function(AuditTableLayoutView) { - that.RAuditTableLayoutView.show(new AuditTableLayoutView(obj)); - }); - }, - renderReplicationAuditTableLayoutView: function(obj) { - var that = this; - require(['views/audit/ReplicationAuditTableLayoutView'], function(ReplicationAuditTableLayoutView) { - that.RReplicationAuditTableLayoutView.show(new ReplicationAuditTableLayoutView(obj)); - }); - }, - renderProfileLayoutView: function(obj) { - var that = this; - require(['views/profile/ProfileLayoutView'], function(ProfileLayoutView) { - that.RProfileLayoutView.show(new ProfileLayoutView(obj)); - }); - } - }); - return DetailPageLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/detail_page/PendingTaskTableLayoutView.js b/dashboardv2/public/js/views/detail_page/PendingTaskTableLayoutView.js deleted file mode 100644 index 0e32ebe7a34..00000000000 --- a/dashboardv2/public/js/views/detail_page/PendingTaskTableLayoutView.js +++ /dev/null @@ -1,218 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/detail_page/PendingTaskTableLayoutView_tmpl', - 'collection/VEntityList', - 'utils/Utils', - 'utils/Enums', - 'utils/UrlLinks', - 'utils/CommonViewFunction' -], function(require, Backbone, PendingTaskTableLayoutView_tmpl, VEntityList, Utils, Enums, UrlLinks, CommonViewFunction) { - 'use strict'; - - var PendingTaskTableLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends PendingTaskTableLayoutView */ - { - _viewName: 'PendingTaskTableLayoutView', - - template: PendingTaskTableLayoutView_tmpl, - - /** Layout sub regions */ - regions: { - RPendingTaskTableLayoutView: "#r_pendingTaskTableLayoutView", - }, - - /** ui selector cache */ - ui: { - refreshPendingTask: "[data-id='refreshPendingTask']" - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.refreshPendingTask] = function(e) { - this.fetchPendingTaskCollection(); - }; - return events; - }, - /** - * intialize a new PendingTaskTableLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'guid', 'entity', 'entityName', 'attributeDefs')); - this.pendingTaskCollection = new VEntityList(); - this.limit = 25; - this.offset = 0; - this.pendingTaskCollection.url = UrlLinks.pendingTaskApiUrl(); - this.entityModel = new this.pendingTaskCollection.model(); - this.pervOld = []; - this.commonTableOptions = { - collection: this.pendingTaskCollection, - includeFilter: false, - includePagination: false, - includeAtlasPagination: true, - includeAtlasPageSize: true, - includeTableLoader: true, - includeAtlasTableSorting: false, - showDefaultTableSorted: false, - columnSorting: false, - includeFooterRecords: false, - gridOpts: { - className: "table table-hover backgrid table-quickMenu", - emptyText: 'No records found!' - }, - isApiSorting: false, - atlasPaginationOpts: this.getPaginationOptions(), - filterOpts: {}, - paginatorOpts: {} - }; - this.currPage = 1; - this.fromSort = false; - }, - onRender: function() { - this.fetchPendingTaskCollection(); - }, - fetchPendingTaskCollection: function() { - this.commonTableOptions['atlasPaginationOpts'] = this.getPaginationOptions(); - this.fetchCollection(); - this.pendingTaskCollection.comparator = function(model) { - return -model.get('createdBy'); - } - }, - bindEvents: function() {}, - getPaginationOptions: function() { - return { - count: this.getPageCount(), - offset: this.pendingTaskCollection.queryParams.offset || this.offset, - fetchCollection: this.fetchCollection.bind(this) - }; - }, - getPageCount: function() { - return (this.pendingTaskCollection.queryParams.limit || this.pendingTaskCollection.queryParams.count) || this.limit; - }, - fetchCollection: function(options) { - var that = this; - - this.pendingTaskCollection.fetch({ - success: function(dataOrCollection, response) { - that.pendingTaskCollection.state.pageSize = that.getPageCount(); - that.pendingTaskCollection.fullCollection.reset(response); - }, - complete: function() { - that.$('.fontLoader').hide(); - that.$('.tableOverlay').hide(); - that.$('.auditTable').show(); - that.renderTableLayoutView(); - }, - silent: true - }); - - }, - renderTableLayoutView: function() { - var that = this; - require(['utils/TableLayout'], function(TableLayout) { - var cols = new Backgrid.Columns(that.getAuditTableColumns()); - that.RPendingTaskTableLayoutView.show(new TableLayout(_.extend({}, that.commonTableOptions, { - columns: cols - }))); - - }); - }, - getAuditTableColumns: function() { - var that = this; - return this.pendingTaskCollection.constructor.getTableCols({ - tool: { - label: "", - cell: "html", - editable: false, - sortable: false, - fixWidth: "20", - cell: Backgrid.ExpandableCell, - accordion: false, - expand: function(el, model) { - el.attr('colspan', '8'); - var count = model.get('attemptCount'), - parameters = _.omit(_.extend(model.get('parameters'), { 'attemptCount': model.get('attemptCount'), 'createdBy': model.get('createdBy') }),"entityGuid"), - memoryTable = CommonViewFunction.propertyTable({ - scope: this, - formatStringVal: false, - valueObject: parameters - }), - tableData = '
        ' + - '
        Parameters
        ' + - '' + - '' + - memoryTable + - '' + - '
        '; - $(el).append($('
        ').html(tableData)); - } - }, - type: { - label: "Type", - cell: "html", - sortable: false, - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return Enums.auditAction[model.get('type')] || rawValue; - } - }) - }, - guid: { - label: "Guid", - cell: "html", - sortable: false, - editable: false - }, - status: { - label: "Status", - cell: "html", - sortable: false, - editable: false - }, - createdTime: { - label: "Created Time", - cell: "html", - editable: false, - sortable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return Utils.formatDate({ date: rawValue }); - } - }) - }, - updatedTime: { - label: "Updated Time", - cell: "html", - editable: false, - sortable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return Utils.formatDate({ date: rawValue }); - } - }) - } - }, this.pendingTaskCollection); - - } - }); - return PendingTaskTableLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/dev_debug/DebugMetricsLayoutView.js b/dashboardv2/public/js/views/dev_debug/DebugMetricsLayoutView.js deleted file mode 100644 index 375d551c2f6..00000000000 --- a/dashboardv2/public/js/views/dev_debug/DebugMetricsLayoutView.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/dev_debug/DebugMetricsLayoutView_tmpl', - 'utils/Utils' -], function(require, Backbone, DebugMetricsLayoutView_tmpl, Utils) { - 'use strict'; - - var DebugMetricsLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends DebugMetricsLayoutView */ - { - _viewName: 'DebugMetricsLayoutView', - - template: DebugMetricsLayoutView_tmpl, - - /** Layout sub regions */ - regions: { - RDebugMetricsLayoutView: "#r_debugMetricsLayoutView" - }, - - /** ui selector cache */ - ui: { - tablist: '[data-id="tab-list"] li' - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.tablist] = function(e) { - var tabValue = $(e.currentTarget).attr('role'); - Utils.setUrl({ - url: Utils.getUrlState.getQueryUrl().queyParams[0], - urlParams: { tabActive: tabValue || 'properties' }, - mergeBrowserUrl: false, - trigger: false, - updateTabState: true - }); - - }; - - return events; - }, - /** - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'value')); - }, - onShow: function() { - if (this.value && this.value.tabActive) { - this.$('.nav.nav-tabs').find('[role="' + this.value.tabActive + '"]').addClass('active').siblings().removeClass('active'); - this.$('.tab-content').find('[role="' + this.value.tabActive + '"]').addClass('active').siblings().removeClass('active'); - $("html, body").animate({ scrollTop: (this.$('.tab-content').offset().top + 1200) }, 1000); - } - }, - bindEvents: function() {}, - onRender: function() { - this.metrice2LayoutView(); - this.bindEvents(); - }, - metrice2LayoutView: function(obj) { - var that = this; - require(['views/site/DebugMetricsTableLayoutView'], function(DebugMetricsTableLayoutView) { - that.RDebugMetricsLayoutView.show(new DebugMetricsTableLayoutView()); - }); - - } - }); - return DebugMetricsLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/entity/CreateEntityLayoutView.js b/dashboardv2/public/js/views/entity/CreateEntityLayoutView.js deleted file mode 100644 index 5e53475c9a0..00000000000 --- a/dashboardv2/public/js/views/entity/CreateEntityLayoutView.js +++ /dev/null @@ -1,969 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/entity/CreateEntityLayoutView_tmpl', - 'utils/Utils', - 'collection/VTagList', - 'collection/VEntityList', - 'models/VEntity', - 'modules/Modal', - 'utils/Messages', - 'moment', - 'utils/UrlLinks', - 'collection/VSearchList', - 'utils/Enums', - 'utils/Globals', - 'daterangepicker' -], function(require, Backbone, CreateEntityLayoutViewTmpl, Utils, VTagList, VEntityList, VEntity, Modal, Messages, moment, UrlLinks, VSearchList, Enums, Globals) { - - var CreateEntityLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends CreateEntityLayoutView */ - { - _viewName: 'CreateEntityLayoutView', - - template: CreateEntityLayoutViewTmpl, - - templateHelpers: function() { - return { - guid: this.guid - }; - }, - - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - entityName: "[data-id='entityName']", - entityList: "[data-id='entityList']", - entityInputData: "[data-id='entityInputData']", - toggleRequired: 'input[name="toggleRequired"]', - assetName: "[data-id='assetName']", - entityInput: "[data-id='entityInput']", - entitySelectionBox: "[data-id='entitySelectionBox']" - }, - /** ui events hash */ - events: function() { - var events = {}; - events["change " + this.ui.entityList] = "onEntityChange"; - events["change " + this.ui.toggleRequired] = function(e) { - this.requiredAllToggle(e.currentTarget.checked) - }; - return events; - }, - /** - * intialize a new CreateEntityLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'guid', 'callback', 'showLoader', 'entityDefCollection', 'typeHeaders', 'searchVent')); - var that = this, - entityTitle, okLabel; - this.selectStoreCollection = new Backbone.Collection(); - this.collection = new VEntityList(); - this.entityModel = new VEntity(); - if (this.guid) { - this.collection.modelAttrName = "createEntity" - } - this.asyncReferEntityCounter = 0; - this.required = true; - if (this.guid) { - entityTitle = 'Edit entity'; - okLabel = 'Update'; - } else { - entityTitle = 'Create entity'; - okLabel = 'Create'; - } - this.modal = new Modal({ - title: entityTitle, - content: this, - cancelText: "Cancel", - okText: okLabel, - allowCancel: true, - okCloses: false, - width: '50%' - }).open(); - this.modal.$el.find('button.ok').attr("disabled", true); - this.modal.on('ok', function(e) { - that.modal.$el.find('button.ok').showButtonLoader(); - that.okButton(); - }); - this.modal.on('closeModal', function() { - that.modal.trigger('cancel'); - }); - }, - bindEvents: function() { - var that = this; - this.listenTo(this.collection, "reset", function() { - this.entityCollectionList(); - }, this); - this.listenTo(this.collection, 'error', function() { - this.hideLoader(); - }, this); - }, - onRender: function() { - this.bindEvents(); - if (!this.guid) { - this.bindRequiredField(); - } - this.showLoader(); - this.fetchCollections(); - this.$('.toggleRequiredSwitch').hide(); - }, - bindRequiredField: function() { - var that = this; - this.ui.entityInputData.on("keyup change", "textarea", function(e) { - var value = this.value; - if (!value.length && $(this).hasClass('false')) { - $(this).removeClass('errorClass'); - that.modal.$el.find('button.ok').prop("disabled", false); - } else { - try { - if (value && value.length) { - JSON.parse(value); - $(this).removeClass('errorClass'); - that.modal.$el.find('button.ok').prop("disabled", false); - } - } catch (err) { - $(this).addClass('errorClass'); - that.modal.$el.find('button.ok').prop("disabled", true); - } - } - }); - - this.ui.entityInputData.on('keyup change', 'input.true,select.true', function(e) { - if (this.value.trim() !== "") { - if ($(this).data('select2')) { - $(this).data('select2').$container.find('.select2-selection').removeClass("errorClass"); - } else { - $(this).removeClass('errorClass'); - } - if (that.ui.entityInputData.find('.errorClass').length === 0) { - that.modal.$el.find('button.ok').prop("disabled", false); - } - } else { - that.modal.$el.find('button.ok').prop("disabled", true); - if ($(this).data('select2')) { - $(this).data('select2').$container.find('.select2-selection').addClass("errorClass"); - } else { - $(this).addClass('errorClass'); - } - } - }); - }, - bindNonRequiredField: function() { - var that = this; - this.ui.entityInputData.off('keyup change', 'input.false,select.false').on('keyup change', 'input.false,select.false', function(e) { - if (that.modal.$el.find('button.ok').prop('disabled') && that.ui.entityInputData.find('.errorClass').length === 0) { - that.modal.$el.find('button.ok').prop("disabled", false); - } - }); - }, - decrementCounter: function(counter) { - if (this[counter] > 0) { - --this[counter]; - } - }, - fetchCollections: function() { - if (this.guid) { - this.collection.url = UrlLinks.entitiesApiUrl({ guid: this.guid }); - this.collection.fetch({ reset: true }); - } else { - this.entityCollectionList(); - } - }, - entityCollectionList: function() { - this.ui.entityList.empty(); - var that = this, - name = "", - value; - if (this.guid) { - this.collection.each(function(val) { - name += Utils.getName(val.get("entity")); - that.entityData = val; - }); - this.ui.assetName.html(name); - var referredEntities = this.entityData.get('referredEntities'); - var attributes = this.entityData.get('entity').attributes; - _.map(_.keys(attributes), function(key) { - if (_.isObject(attributes[key])) { - var attrObj = attributes[key]; - if (_.isObject(attrObj) && !_.isArray(attrObj)) { - attrObj = [attrObj]; - } - _.each(attrObj, function(obj) { - if (obj.guid && !referredEntities[obj.guid]) { - ++that.asyncReferEntityCounter; - that.collection.url = UrlLinks.entitiesApiUrl({ guid: obj.guid }); - that.collection.fetch({ - success: function(data, response) { - referredEntities[obj.guid] = response.entity; - }, - complete: function() { - that.decrementCounter('asyncReferEntityCounter'); - if (that.asyncReferEntityCounter === 0) { - that.onEntityChange(null, that.entityData); - } - }, - silent: true - }); - } - }); - } - }); - if (this.asyncReferEntityCounter === 0) { - this.onEntityChange(null, this.entityData); - } - } else { - var str = ''; - this.entityDefCollection.fullCollection.each(function(val) { - var name = Utils.getName(val.toJSON()); - if (Globals.entityTypeConfList && name.indexOf("__") !== 0) { - if (_.isEmptyArray(Globals.entityTypeConfList)) { - str += ''; - } else { - if (_.contains(Globals.entityTypeConfList, val.get("name"))) { - str += ''; - } - } - } - }); - this.ui.entityList.html(str); - this.ui.entityList.select2({}); - this.hideLoader(); - } - }, - capitalize: function(string) { - return string.charAt(0).toUpperCase() + string.slice(1); - }, - requiredAllToggle: function(checked) { - if (checked) { - this.ui.entityInputData.addClass('all').removeClass('required'); - this.ui.entityInputData.find('div.true').show(); - this.ui.entityInputData.find('fieldset div.true').show(); - this.ui.entityInputData.find('fieldset').show(); - this.required = false; - } else { - this.ui.entityInputData.addClass('required').removeClass('all'); - this.ui.entityInputData.find('fieldset').each(function() { - if (!$(this).find('div').hasClass('false')) { - $(this).hide(); - } - }); - this.ui.entityInputData.find('div.true').hide(); - this.ui.entityInputData.find('fieldset div.true').hide(); - this.required = true; - } - - }, - onEntityChange: function(e, value) { - var that = this, - typeName = value && value.get('entity') ? value.get('entity').typeName : null; - if (!this.guid) { - this.showLoader(); - } - this.ui.entityInputData.empty(); - if (typeName) { - this.collection.url = UrlLinks.entitiesDefApiUrl(typeName); - } else if (e) { - this.collection.url = UrlLinks.entitiesDefApiUrl(e.target.value); - this.collection.modelAttrName = 'attributeDefs'; - } - this.collection.fetch({ - success: function(model, data) { - that.supuertypeFlag = 0; - that.subAttributeData(data) - }, - complete: function() { - that.modal.$el.find('button.ok').prop("disabled", true); - //that.initilizeElements(); - }, - silent: true - }); - }, - renderAttribute: function(object) { - var that = this, - visitedAttr = {}, - attributeObj = object.attributeDefs, - isAllAttributeOptinal = true, - isAllRelationshipAttributeOptinal = true, - attributeDefList = attributeObj.attributeDefs, - relationshipAttributeDefsList = attributeObj.relationshipAttributeDefs, - attributeHtml = "", - relationShipAttributeHtml = "", - fieldElemetHtml = '', - commonInput = function(object) { - var value = object.value, - containerHtml = ''; - containerHtml += that.getContainer(object); - return containerHtml; - }; - if (attributeDefList.length || relationshipAttributeDefsList.length) { - _.each(attributeDefList, function(value) { - if (value.isOptional === false) { - isAllAttributeOptinal = false; - } - attributeHtml += commonInput({ - "value": value, - "duplicateValue": false, - "isAttribute": true - }); - }); - _.each(relationshipAttributeDefsList, function(value) { - if (value.isOptional === false) { - isAllRelationshipAttributeOptinal = false; - } - if (visitedAttr[value.name] === null) { - // on second visited set it to true;and now onwords ignore if same value come. - var duplicateRelationship = _.where(relationshipAttributeDefsList, { name: value.name }); - var str = ''; - _.each(duplicateRelationship, function(val, index, list) { - str += ''; - }); - var isOptional = value.isOptional; - visitedAttr[value.name] = '
        '; - } else { - relationShipAttributeHtml += commonInput({ - "value": value, - "duplicateValue": true, - "isRelation": true - }); - // once visited set it to null; - visitedAttr[value.name] = null; - } - }); - if (attributeHtml.length) { - fieldElemetHtml += that.getFieldElementContainer({ - "htmlField": attributeHtml, - "attributeType": true, - "alloptional": isAllAttributeOptinal - }); - } - if (relationShipAttributeHtml.length) { - fieldElemetHtml += that.getFieldElementContainer({ - "htmlField": relationShipAttributeHtml, - "relationshipType": true, - "alloptional": isAllRelationshipAttributeOptinal - }); - } - if (fieldElemetHtml.length) { - that.ui.entityInputData.append(fieldElemetHtml); - _.each(_.keys(visitedAttr), function(key) { - if (visitedAttr[key] === null) { - return; - } - var elFound = that.ui.entityInputData.find('[data-key="' + key + '"]'); - elFound.prop('disabled', true); - elFound.parent().prepend(visitedAttr[key]); - }); - } else { - fieldElemetHtml = "

        Defination not found

        "; - that.ui.entityInputData.append(fieldElemetHtml); - } - - } - that.ui.entityInputData.find("select[data-for-key]").select2({}).on('change', function() { - var forKey = $(this).data('forKey'), - forKeyEl = null; - if (forKey && forKey.length) { - forKeyEl = that.ui.entityInputData.find('[data-key="' + forKey + '"]'); - if (forKeyEl) { - if (this.value == "") { - forKeyEl.val(null).trigger('change'); - forKeyEl.prop("disabled", true); - } else { - forKeyEl.prop("disabled", false); - } - } - } - }); - return false; - }, - subAttributeData: function(data) { - var that = this, - attributeInput = "", - alloptional = false, - attributeDefs = Utils.getNestedSuperTypeObj({ - seperateRelatioshipAttr: true, - attrMerge: true, - data: data, - collection: this.entityDefCollection - }); - if (attributeDefs && attributeDefs.relationshipAttributeDefs.length) { - attributeDefs.attributeDefs = _.filter(attributeDefs.attributeDefs, function(obj) { - if (_.find(attributeDefs.relationshipAttributeDefs, { name: obj.name }) === undefined) { - return true; - } - }) - } - if (attributeDefs.attributeDefs.length || attributeDefs.relationshipAttributeDefs.length) { - this.$('.toggleRequiredSwitch').show(); - } else { - this.$('.toggleRequiredSwitch').hide(); - } - //make a function call. - this.renderAttribute({ - attributeDefs: attributeDefs - }); - - if (this.required) { - this.ui.entityInputData.find('fieldset div.true').hide() - this.ui.entityInputData.find('div.true').hide(); - } - if (!('placeholder' in HTMLInputElement.prototype)) { - this.ui.entityInputData.find("input,select,textarea").placeholder(); - } - that.initilizeElements(); - }, - initilizeElements: function() { - var that = this, - $createTime = this.modal.$el.find('input[name="createTime"]'), - dateObj = { - "singleDatePicker": true, - "showDropdowns": true, - "startDate": new Date(), - locale: { - format: Globals.dateFormat - } - }; - this.$('input[data-type="date"]').each(function() { - if (!$(this).data('daterangepicker')) { - if (that.guid && this.value.length) { - dateObj["startDate"] = new Date(Number(this.value)); - } - if ($(this).attr('name') === "modifiedTime") { - dateObj["minDate"] = $createTime.val(); - } - $(this).daterangepicker(dateObj); - } - }); - modifiedDateObj = _.extend({}, dateObj); - $createTime.on('apply.daterangepicker', function(ev, picker) { - that.modal.$el.find('input[name="modifiedTime"]').daterangepicker(_.extend(modifiedDateObj, { "minDate": $createTime.val() })); - }); - this.initializeValidation(); - if (this.ui.entityInputData.find('fieldset').length > 0 && this.ui.entityInputData.find('select.true,input.true').length === 0) { - this.requiredAllToggle(this.ui.entityInputData.find('select.true,input.true').length === 0); - if (!this.guid) { - // For create entity bind keyup for non-required field when all elements are optional - this.bindNonRequiredField(); - } - } - this.$('select[data-type="boolean"]').each(function(value, key) { - var dataKey = $(key).data('key'); - if (that.entityData) { - var setValue = that.entityData.get("entity").attributes[dataKey]; - this.value = setValue; - } - }); - this.addJsonSearchData(); - }, - initializeValidation: function() { - // IE9 allow input type number - var regex = /^[0-9]*((?=[^.]|$))?$/, // allow only numbers [0-9] - removeText = function(e, value) { - if (!regex.test(value)) { - var txtfld = e.currentTarget; - var newtxt = txtfld.value.slice(0, txtfld.value.length - 1); - txtfld.value = newtxt; - } - } - this.$('input[data-type="int"],input[data-type="long"]').on('keydown', function(e) { - // allow only numbers [0-9] - if (!regex.test(e.currentTarget.value)) { - return false; - } - }); - this.$('input[data-type="int"],input[data-type="long"]').on('paste', function(e) { - return false; - }); - - this.$('input[data-type="long"],input[data-type="int"]').on('keyup click', function(e) { - removeText(e, e.currentTarget.value); - }); - - this.$('input[data-type="date"]').on('hide.daterangepicker keydown', function(event) { - if (event.type) { - if (event.type == 'hide') { - this.blur(); - } else if (event.type == 'keydown') { - return false; - } - } - }); - }, - getContainer: function(object) { - var value = object.value, - entityLabel = this.capitalize(_.escape(value.name)); - - return '
        ' + - '' + - '' + (this.getElement(object)) + - '
        '; - }, - getFieldElementContainer: function(object) { - var htmlField = object.htmlField, - attributeType = object.attributeType ? object.attributeType : false, - relationshipType = object.relationshipType ? object.relationshipType : false, - alloptional = object.alloptional, - typeOfDefination = (relationshipType ? "Relationships" : "Attributes"); - return '
        ' + (typeOfDefination) + '' + htmlField + '
        '; - }, - getSelect: function(object) { - var value = object.value, - name = _.escape(value.name), - entityValue = _.escape(object.entityValue), - isAttribute = object.isAttribute, - isRelation = object.isRelation; - if (value.typeName === "boolean") { - return ''; - } else { - var splitTypeName = value.typeName.split("<"); - if (splitTypeName.length > 1) { - splitTypeName = splitTypeName[1].split(">")[0]; - } else { - splitTypeName = value.typeName; - } - return ''; - } - - }, - getTextArea: function(object) { - var value = object.value, - name = _.escape(value.name), - setValue = _.escape(object.entityValue), - isAttribute = object.isAttribute, - isRelation = object.isRelation, - structType = object.structType; - try { - if (structType && entityValue && entityValue.length) { - var parseValue = JSON.parse(entityValue); - if (_.isObject(parseValue) && !_.isArray(parseValue) && parseValue.attributes) { - setValue = JSON.stringify(parseValue.attributes); - } - } - } catch (err) {} - - return ''; - - }, - getInput: function(object) { - var value = object.value, - name = _.escape(value.name), - entityValue = _.escape(object.entityValue), - isAttribute = object.isAttribute, - isRelation = object.isRelation; - return ''; - }, - getElement: function(object) { - var value = object.value, - isAttribute = object.isAttribute, - isRelation = object.isRelation, - typeName = value.typeName, - entityValue = ""; - if (this.guid) { - var dataValue = this.entityData.get("entity").attributes[value.name]; - if (_.isObject(dataValue)) { - entityValue = JSON.stringify(dataValue); - } else { - if (dataValue) { - entityValue = dataValue; - } - if (value.typeName === "date") { - if (dataValue) { - entityValue = moment(dataValue); - } else { - entityValue = Utils.formatDate({ zone: false, dateFormat: Globals.dateFormat }); - } - } - } - } - if ((typeName && this.entityDefCollection.fullCollection.find({ name: typeName })) || typeName === "boolean" || typeName.indexOf("array") > -1) { - return this.getSelect({ - "value": value, - "entityValue": entityValue, - "isAttribute": isAttribute, - "isRelation": isRelation - - }); - } else if (typeName.indexOf("map") > -1) { - return this.getTextArea({ - "value": value, - "entityValue": entityValue, - "isAttribute": isAttribute, - "isRelation": isRelation, - "structType": false - }); - } else { - var typeNameCategory = this.typeHeaders.fullCollection.findWhere({ name: typeName }); - if (typeNameCategory && typeNameCategory.get('category') === 'STRUCT') { - return this.getTextArea({ - "value": value, - "entityValue": entityValue, - "isAttribute": isAttribute, - "isRelation": isRelation, - "structType": true - }); - } else { - return this.getInput({ - "value": value, - "entityValue": entityValue, - "isAttribute": isAttribute, - "isRelation": isRelation, - }); - } - } - }, - okButton: function() { - var that = this; - this.showLoader({ - editVisiblityOfEntitySelectionBox: true - }); - this.parentEntity = this.ui.entityList.val(); - var entityAttribute = {}, - referredEntities = {}, - relationshipAttribute = {}; - var extractValue = function(value, typeName) { - if (!value) { - return value; - } - if (_.isArray(value)) { - var parseData = []; - _.map(value, function(val) { - parseData.push({ 'guid': val, 'typeName': typeName }); - }); - } else { - var parseData = { 'guid': value, 'typeName': typeName }; - } - return parseData; - } - try { - this.ui.entityInputData.find("input,select,textarea").each(function() { - var value = $(this).val(), - el = this; - if ($(this).val() && $(this).val().trim) { - value = $(this).val().trim(); - } - if (this.nodeName === "TEXTAREA") { - try { - if (value && value.length) { - JSON.parse(value); - $(this).removeClass('errorClass'); - } - } catch (err) { - throw new Error(err.message); - $(this).addClass('errorClass'); - } - } - // validation - if ($(this).hasClass("true")) { - if (value == "" || value == undefined) { - if ($(this).data('select2')) { - $(this).data('select2').$container.find('.select2-selection').addClass("errorClass") - } else { - $(this).addClass('errorClass'); - } - that.hideLoader(); - that.modal.$el.find('button.ok').hideButtonLoader(); - throw new Error("Please fill the required fields"); - return; - } - } - var dataTypeEnitity = $(this).data('type'), - datakeyEntity = $(this).data('key'), - typeName = $(this).data('querydata'), - attribute = $(this).data('attribute') == 'undefined' ? false : true, - relation = $(this).data('relation') == 'undefined' ? false : true, - typeNameCategory = that.typeHeaders.fullCollection.findWhere({ name: dataTypeEnitity }), - val = null; - // Extract Data - if (dataTypeEnitity && datakeyEntity) { - if (that.entityDefCollection.fullCollection.find({ name: dataTypeEnitity })) { - val = extractValue(value, typeName); - } else if (dataTypeEnitity === 'date' || dataTypeEnitity === 'time') { - val = Date.parse(value); - } else if (dataTypeEnitity.indexOf("map") > -1 || (typeNameCategory && typeNameCategory.get('category') === 'STRUCT')) { - try { - if (value && value.length) { - parseData = JSON.parse(value); - val = parseData; - } - } catch (err) { - $(this).addClass('errorClass'); - throw new Error(datakeyEntity + " : " + err.message); - return; - } - } else if (dataTypeEnitity.indexOf("array") > -1 && dataTypeEnitity.indexOf("string") === -1) { - val = extractValue(value, typeName); - } else { - if (_.isString(value)) { - if (value.length) { - val = value; - } else { - val = null; - } - } else { - val = value; - } - } - if (attribute) { - entityAttribute[datakeyEntity] = val; - } else if (relation) { - relationshipAttribute[datakeyEntity] = val; - } - } else { - var dataRelEntity = $(this).data('forKey'); - if (dataRelEntity && relationshipAttribute[dataRelEntity]) { - if (_.isArray(relationshipAttribute[dataRelEntity])) { - _.each(relationshipAttribute[dataRelEntity], function(obj) { - if (obj) { - obj["relationshipType"] = $(el).val(); - } - }); - } else { - relationshipAttribute[dataRelEntity]["relationshipType"] = $(this).val(); - } - - } - } - }); - var entityJson = { - "entity": { - "typeName": (this.guid ? this.entityData.get("entity").typeName : this.parentEntity), - "attributes": entityAttribute, - "relationshipAttributes": relationshipAttribute, - "guid": (this.guid ? this.guid : -1) - }, - "referredEntities": referredEntities - }; - this.entityModel.createOreditEntity({ - data: JSON.stringify(entityJson), - type: "POST", - success: function(model, response) { - that.modal.$el.find('button.ok').hideButtonLoader(); - that.modal.close(); - var msgType = (model.mutatedEntities && model.mutatedEntities.UPDATE) ? 'editSuccessMessage' : 'addSuccessMessage'; - Utils.notifySuccess({ - content: "Entity " + Messages.getAbbreviationMsg(false, msgType) - }); - if (that.guid && that.callback) { - that.callback(); - } else { - if (model.mutatedEntities) { - var mutatedEntities = model.mutatedEntities.CREATE || model.mutatedEntities.UPDATE; - if (mutatedEntities && _.isArray(mutatedEntities) && mutatedEntities[0] && mutatedEntities[0].guid) { - Utils.setUrl({ - url: '#!/detailPage/' + (mutatedEntities[0].guid), - mergeBrowserUrl: false, - trigger: true - }); - } - if (that.searchVent) { - that.searchVent.trigger('entityList:refresh'); - } - } - } - }, - complete: function() { - that.hideLoader({ - editVisiblityOfEntitySelectionBox: true - }); - that.modal.$el.find('button.ok').hideButtonLoader(); - } - }); - } catch (e) { - Utils.notifyError({ - content: e.message - }); - that.hideLoader({ - editVisiblityOfEntitySelectionBox: true - }); - } - }, - showLoader: function(options) { - var editVisiblityOfEntitySelectionBox = options && options.editVisiblityOfEntitySelectionBox; - this.$('.entityLoader').addClass('show'); - this.$('.entityInputData').hide(); - if (this.guid || editVisiblityOfEntitySelectionBox) { - this.ui.entitySelectionBox.hide(); - } - }, - hideLoader: function(options) { - var editVisiblityOfEntitySelectionBox = options && options.editVisiblityOfEntitySelectionBox - this.$('.entityLoader').removeClass('show'); - this.$('.entityInputData').show(); - if (this.guid || editVisiblityOfEntitySelectionBox) { - this.ui.entitySelectionBox.show(); - } - // To enable scroll after selecting value from select2. - this.ui.entityList.select2('open'); - this.ui.entityList.select2('close'); - }, - addJsonSearchData: function() { - var that = this; - this.$('select[data-id="entitySelectData"]').each(function(value, key) { - var $this = $(this), - keyData = $(this).data("key"), - typeData = $(this).data("type"), - queryData = $(this).data("querydata"), - skip = $(this).data('skip'), - placeholderName = "Select a " + typeData + " from the dropdown list"; - $this.attr("multiple", ($this.data('type').indexOf("array") === -1 ? false : true)); - - // Select Value. - if (that.guid) { - var dataValue = that.entityData.get("entity").attributes[keyData], - entities = that.entityData.get("entity").attributes, - relationshipType = that.entityData.get("entity").relationshipAttributes ? that.entityData.get("entity").relationshipAttributes[keyData] : null, - referredEntities = that.entityData.get("referredEntities"), - selectedValue = [], - select2Options = []; - if (dataValue) { - if (_.isObject(dataValue) && !_.isArray(dataValue)) { - dataValue = [dataValue]; - } - _.each(dataValue, function(obj) { - if (_.isObject(obj) && obj.guid && referredEntities[obj.guid]) { - var refEntiyFound = referredEntities[obj.guid]; - refEntiyFound['id'] = refEntiyFound.guid; - if (!Enums.entityStateReadOnly[refEntiyFound.status]) { - select2Options.push(refEntiyFound); - selectedValue.push(refEntiyFound.guid); - } - } - }); - if (!_.isUndefined(relationshipType)) { - if (relationshipType && relationshipType.relationshipAttributes && relationshipType.relationshipAttributes.typeName) { - that.$("select[data-for-key=" + keyData + "]").val(relationshipType.relationshipAttributes.typeName).trigger("change"); - } - - } - } - - // Array of string. - if (selectedValue.length === 0 && dataValue && dataValue.length && ($this.data('querydata') === "string")) { - var str = ""; - _.each(dataValue, function(obj) { - if (_.isString(obj)) { - selectedValue.push(obj); - str += ''; - } - }); - $this.html(str); - } - - } else { - $this.val([]); - } - var select2Option = { - placeholder: placeholderName, - allowClear: true, - tags: ($this.data('querydata') == "string" ? true : false) - } - var getTypeAheadData = function(data, params) { - var dataList = data.entities, - foundOptions = []; - _.each(dataList, function(obj) { - if (obj) { - if (obj.guid) { - obj['id'] = obj.guid; - } - foundOptions.push(obj); - } - }); - return foundOptions; - } - if ($this.data('querydata') !== "string") { - _.extend(select2Option, { - ajax: { - url: UrlLinks.searchApiUrl('attribute'), - dataType: 'json', - delay: 250, - data: function(params) { - return { - attrValuePrefix: params.term, // search term - typeName: queryData, - limit: 10, - offset: 0 - }; - }, - processResults: function(data, params) { - return { - results: getTypeAheadData(data, params) - }; - }, - cache: true - }, - templateResult: function(option) { - var name = Utils.getName(option, 'qualifiedName'); - return name === "-" ? option.text : name; - }, - templateSelection: function(option) { - var name = Utils.getName(option, 'qualifiedName'); - return name === "-" ? option.text : name; - }, - escapeMarkup: function(markup) { - return markup; - }, - data: select2Options, - minimumInputLength: 1 - }); - } - $this.select2(select2Option); - if (selectedValue) { - $this.val(selectedValue).trigger("change"); - } - - }); - if (this.guid) { - this.bindRequiredField(); - this.bindNonRequiredField(); - } - this.hideLoader(); - } - }); - return CreateEntityLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/entity/EntityBusinessMetaDataItemView.js b/dashboardv2/public/js/views/entity/EntityBusinessMetaDataItemView.js deleted file mode 100644 index ff285068d15..00000000000 --- a/dashboardv2/public/js/views/entity/EntityBusinessMetaDataItemView.js +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -define(['require', - 'backbone', - 'utils/Utils', - 'hbs!tmpl/entity/EntityBusinessMetaDataItemView_tmpl', - 'moment', - 'utils/Globals', - 'daterangepicker' -], function(require, Backbone, Utils, EntityBusinessMetaDataItemViewTmpl, moment, Globals) { - 'use strict'; - - return Backbone.Marionette.ItemView.extend({ - _viewName: 'EntityBusinessMetaDataItemView', - - template: EntityBusinessMetaDataItemViewTmpl, - - templateHelpers: function() { - return { - editMode: this.editMode, - entity: this.entity, - getValue: this.getValue.bind(this), - getBusinessMetadataDroupdown: this.getBusinessMetadataDroupdown.bind(this), - businessMetadataCollection: this.businessMetadataCollection, - model: this.model.toJSON() - } - }, - tagName: 'li', - className: "business-metadata-tree-child", - - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - keyEl: "[data-id='key']", - valueEl: "[data-type='value']", - addItem: "[data-id='addItem']", - deleteItem: "[data-id='deleteItem']", - editMode: "[data-id='editMode']" - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.deleteItem] = 'onDeleteItem'; - events["change " + this.ui.keyEl] = 'onAttrChange'; - return events; - }, - - /** - * intialize a new EntityBusinessMetaDataItemView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, options); - }, - onRender: function() { - var that = this; - this.ui.keyEl.val(""); - this.ui.keyEl.select2({ placeholder: "Select Attribute" }); - - if (this.editMode && (!this.model.has("isNew"))) { - this.getEditBusinessMetadataEl(); - } - this.initializeElement(); - this.bindEvent(); - }, - initializeElement: function() {}, - bindEvent: function() { - var that = this; - if (this.editMode) { - this.listenTo(this.model.collection, 'destroy unset:attr', function() { - if (this.model.has("isNew")) { - this.render(); - } - }); - this.listenTo(this.model.collection, 'selected:attr', function(value, model) { - if (model.cid !== this.model.cid && this.model.has("isNew")) { - var $select2el = that.$el.find('.custom-col-1:first-child>select[data-id="key"]'); - $select2el.find('option[value="' + value + '"]').remove(); - var select2val = $select2el.select2("val"); - $select2el.select2({ placeholder: "Select Attribute" }); - if (this.model.keys().length <= 2) { - $select2el.val("").trigger("change", true); - } - } - }); - this.$el.off("change", ".custom-col-1[data-id='value']>[data-key]").on("change", ".custom-col-1[data-id='value']>[data-key]", function(e) { - var key = $(this).data("key"), - businessMetadata = $(this).data("businessMetadata"), - typeName = $(this).data("typename"), - multi = $(this).data("multi"), - updateObj = that.model.toJSON(); - if (_.isUndefinedNull(updateObj[key])) { - updateObj[key] = { value: null, typeName: typeName }; - } - updateObj[key].value = e.currentTarget.value; - if (multi && typeName.indexOf("date") == -1) { - updateObj[key].value = $(this).select2("val"); - } - if (!that.model.has("__internal_UI_businessMetadataName")) { - updateObj["__internal_UI_businessMetadataName"] = businessMetadata; - } - if (typeName === "date" || typeName === "array") { - if (multi && updateObj[key].value) { - var dateValues = updateObj[key].value.split(','), - dateStr = []; - if (dateValues.length) { - _.each(dateValues, function(selectedDate) { - dateStr.push(new Date(selectedDate.trim()).getTime()); - }); - updateObj[key].value = dateStr; - } - } else { - updateObj[key].value = new Date(updateObj[key].value).getTime() - } - } - that.model.set(updateObj); - }); - this.$el.on('keypress', '.select2_only_number .select2-search__field', function() { - var typename = $(this).parents(".select2_only_number").find("select[data-typename]").data("typename") - if ((typename === "float" || typename === "array") && event.which == 46) { - return; - } - if ((event.which < 48 || event.which > 57) && event.key !== "-") { - event.preventDefault(); - } - }); - } - }, - getAttrElement: function(opt) { - var that = this, - returnEL = "N/A", - options = $.extend(true, {}, opt); - if (options) { - var key = options.key, - typeName = options.val.typeName || "", - val = options.val.value, - isMultiValued = typeName && typeName.indexOf("array<") === 0, - businessMetadata = options.businessMetadata, - allowOnlyNum = false, - isEnum = false; - var elType = isMultiValued ? "select" : "input"; - if (!isMultiValued && !_.isEmpty(val)) { - val = _.escape(val); - } - if (!_.isUndefinedNull(val) && (typeName === "boolean" || typeName === "array")) { - val = String(val); - } - if (typeName === "date" || typeName === "array") { - if (isMultiValued && val && val.length) { - var dateStr = []; - _.each(val, function(selectedDate) { - selectedDate = parseInt(selectedDate); - dateStr.push(Utils.formatDate({ date: selectedDate, zone: false, dateFormat: Globals.dateFormat })); - }); - val = dateStr.join(','); - } else if (!isMultiValued && val) { - val = parseInt(val); - val = Utils.formatDate({ date: val, zone: false, dateFormat: Globals.dateFormat }); - } - } - if (typeName === "string" || typeName === "array") { - returnEL = '<' + elType + ' type="text" data-key="' + key + '" data-businessMetadata="' + businessMetadata + '" data-typename="' + typeName + '" data-multi="' + isMultiValued + '" data-tags="true" placeholder="Enter String" class="form-control" ' + (isMultiValued === false && !_.isUndefinedNull(val) ? 'value="' + val + '"' : "") + '>'; - } else if (typeName === "boolean" || typeName === "array") { - returnEL = ''; - } else if (typeName === "date" || typeName === "array") { - returnEL = '<' + (isMultiValued ? "textarea" : "input") + ' type="text" data-key="' + key + '" data-businessMetadata="' + businessMetadata + '" data-typename="' + typeName + '"data-multi="' + isMultiValued + '" data-type="date" class="form-control" ' + (isMultiValued === false && !_.isUndefinedNull(val) ? 'value="' + val + '"' : "") + '>' + (isMultiValued === true && !_.isUndefinedNull(val) ? val : "") + (isMultiValued ? "" : ""); - setTimeout(function() { - var dateObj = { singleDatePicker: true, showDropdowns: true, autoUpdateInput: isMultiValued ? false : true, locale: { format: Globals.dateFormat } }, - dateEl = that.$el.find('[data-type="date"][data-key="' + key + '"]').daterangepicker(dateObj); - if (isMultiValued) { - dateEl.on("apply.daterangepicker", function(ev, picker) { - var val = picker.element.val(); - if (val !== "") { - val += ", "; - } - picker.element.val(val += Utils.formatDate({ date: picker.startDate, zone: false, dateFormat: Globals.dateFormat })); - that.$el.find(".custom-col-1[data-id='value']>[data-key]").trigger('change'); - }); - } - }, 0); - } else if (typeName === "byte" || typeName === "array" || typeName === "short" || typeName === "array" || typeName === "int" || typeName === "array" || typeName === "float" || typeName === "array" || typeName === "double" || typeName === "array" || typeName === "long" || typeName === "array") { - allowOnlyNum = true; - returnEL = '<' + elType + ' data-key="' + key + '" data-businessMetadata="' + businessMetadata + '" data-typename="' + typeName + '" type="number" data-multi="' + isMultiValued + '" data-tags="true" placeholder="Enter Number" class="form-control" ' + (!_.isUndefinedNull(val) ? 'value="' + val + '"' : "") + '>'; - } else if (typeName) { - isEnum = true; - var modTypeName = typeName; - if (isMultiValued) { - var multipleType = typeName.match("array<(.*)>"); - if (multipleType && multipleType[1]) { - modTypeName = multipleType[1]; - } - } - var foundEnumType = this.enumDefCollection.fullCollection.find({ name: modTypeName }); - if (foundEnumType) { - var enumOptions = ""; - _.forEach(foundEnumType.get("elementDefs"), function(obj) { - enumOptions += '' - }); - returnEL = ''; - } - } - if (isEnum || elType === "select") { - setTimeout(function() { - var selectEl = that.$el.find('.custom-col-1[data-id="value"] select[data-key="' + key + '"]'); - var data = []; - if (selectEl.data("multi")) { - data = val && val.length && (_.isArray(val) ? val : val.split(",")) || []; - } else { - data = _.unescape(val); - } - if (allowOnlyNum) { - selectEl.parent().addClass("select2_only_number"); - } - var opt = { - tags: selectEl.data("tags") ? true : false, - multiple: selectEl.data("multi"), - createTag: function(params) { - var option = params.term; - if ($.isNumeric(option) || (typeName === "array" && _.isString(option))) { - return { - id: option, - text: option - } - } - } - } - if (!selectEl.data("enum")) { - opt.data = data; - } - selectEl.select2(opt); - selectEl.val(data).trigger("change"); - }, 0); - } - } - return returnEL; - }, - onAttrChange: function(e, manual) { - var key = e.currentTarget.value.split(":"); - if (key.length && key.length === 3) { - var valEl = $(e.currentTarget).parent().siblings(".custom-col-1"), - hasModalData = this.model.get(key[1]); - if (!hasModalData) { - var tempObj = { - "__internal_UI_businessMetadataName": key[0] - }; - if (this.model.has("isNew")) { - tempObj["isNew"] = true; - } - tempObj[key[1]] = null; - this.model.clear({ silent: true }).set(tempObj) - } - valEl.html(this.getAttrElement({ businessMetadata: key[0], key: key[1], val: hasModalData ? hasModalData : { typeName: key[2] } })); - if (manual === undefined) { - this.model.collection.trigger("selected:attr", e.currentTarget.value, this.model); - } - } - }, - getValue: function(value, key, businessMetadataName) { - var typeName = value.typeName, - value = value.value; - if (typeName === "date") { - return Utils.formatDate({ date: value, zone: false, dateFormat: Globals.dateFormat }); - } else { - return value; - } - }, - getBusinessMetadataDroupdown: function(businessMetadataCollection) { - var optgroup = ""; - var that = this; - var model = that.model.omit(["isNew", "__internal_UI_businessMetadataName"]), - keys = _.keys(model), - isSelected = false, - selectdVal = null; - if (keys.length === 1) { - isSelected = true; - } - _.each(businessMetadataCollection, function(obj, key) { - var options = ""; - if (obj.length) { - _.each(obj, function(attrObj) { - var entityBusinessMetadata = that.model.collection.filter({ __internal_UI_businessMetadataName: key }), - hasAttr = false; - if (entityBusinessMetadata) { - var found = entityBusinessMetadata.find(function(eObj) { - return eObj.attributes.hasOwnProperty(attrObj.name); - }); - if (found) { - hasAttr = true; - } - } - if ((isSelected && keys[0] === attrObj.name) || !(hasAttr)) { - var value = key + ":" + attrObj.name + ":" + attrObj.typeName; - if (isSelected && keys[0] === attrObj.name) { selectdVal = value }; - options += ''; - } - }); - if (options.length) { - optgroup += '' + options + ''; - } - } - }); - - setTimeout(function() { - if (selectdVal) { - that.$el.find('.custom-col-1:first-child>select[data-id="key"]').val(selectdVal).trigger("change", true); - } else { - that.$el.find('.custom-col-1:first-child>select[data-id="key"]').val("").trigger("change", true); - } - }, 0); - return ''; - }, - getEditBusinessMetadataEl: function() { - var that = this, - trs = ""; - _.each(this.model.attributes, function(val, key) { - if (key !== "__internal_UI_businessMetadataName" && key !== "isNew") { - var td = '' + key + ' (' + _.escape(val.typeName) + '):' + that.getAttrElement({ businessMetadata: that.model.get("__internal_UI_businessMetadataName"), key: key, val: val }) + ''; - - td += '' + - ''; - trs += "" + td + ""; - } - }) - this.$("[data-id='businessMetadataTreeChild']").html("" + trs + "
        "); - }, - onDeleteItem: function(e) { - var key = $(e.currentTarget).data("key"); - if (this.model.has(key)) { - if (this.model.keys().length === 2) { - this.model.destroy(); - } else { - this.model.unset(key); - if (!this.model.has("isNew")) { - this.$el.find("tr>td:first-child[data-key='" + key + "']").parent().remove() - } - this.model.collection.trigger("unset:attr"); - } - } else { - this.model.destroy(); - } - } - }); -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/entity/EntityBusinessMetaDataView.js b/dashboardv2/public/js/views/entity/EntityBusinessMetaDataView.js deleted file mode 100644 index 213e7cc01e5..00000000000 --- a/dashboardv2/public/js/views/entity/EntityBusinessMetaDataView.js +++ /dev/null @@ -1,295 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define([ - "require", - "backbone", - "hbs!tmpl/entity/EntityBusinessMetaDataView_tmpl", - "views/entity/EntityBusinessMetaDataItemView", - "models/VEntity", - "utils/Utils", - "utils/Messages", - "utils/Enums", - "utils/CommonViewFunction", - "moment", - "utils/Globals" -], function(require, Backbone, EntityBusinessMetaDataView_tmpl, EntityBusinessMetaDataItemView, VEntity, Utils, Messages, Enums, CommonViewFunction, moment, Globals) { - "use strict"; - - return Backbone.Marionette.CompositeView.extend({ - _viewName: "EntityBusinessMetaDataView", - template: EntityBusinessMetaDataView_tmpl, - childView: EntityBusinessMetaDataItemView, - childViewContainer: "[data-id='itemView']", - childViewOptions: function() { - return { - editMode: this.editMode, - entity: this.entity, - businessMetadataCollection: this.businessMetadataCollection, - enumDefCollection: this.enumDefCollection - }; - }, - templateHelpers: function() { - return { - readOnlyEntity: this.readOnlyEntity - } - }, - /** ui selector cache */ - ui: { - addItem: "[data-id='addItem']", - addBusinessMetadata: "[data-id='addBusinessMetadata']", - saveBusinessMetadata: "[data-id='saveBusinessMetadata']", - businessMetadataTree: "[data-id='businessMetadataTree']", - cancel: "[data-id='cancel']", - businessMetadataHeader: ".businessMetaDataPanel .panel-heading.main-parent" - }, - events: function() { - var events = {}; - events["click " + this.ui.addItem] = 'createNameElement'; - events["click " + this.ui.addBusinessMetadata] = "onAddBusinessMetadata"; - events["click " + this.ui.saveBusinessMetadata] = "onSaveBusinessMetadata"; - events["click " + this.ui.cancel] = "onCancel"; - events["click " + this.ui.businessMetadataHeader] = "onHeaderClick"; - return events; - }, - initialize: function(options) { - var that = this; - _.extend(this, _.pick(options, "entity", "businessMetadataCollection", "enumDefCollection", "guid", "fetchCollection")); - this.editMode = false; - this.readOnlyEntity = Enums.entityStateReadOnly[this.entity.status]; - this.$("editBox").hide(); - this.actualCollection = new Backbone.Collection( - _.map(this.entity.businessAttributes, function(val, key) { - var foundBusinessMetadata = that.businessMetadataCollection[key]; - if (foundBusinessMetadata) { - _.each(val, function(aVal, aKey) { - var foundAttr = _.find(foundBusinessMetadata, function(o) { - return o.name === aKey - }); - if (foundAttr) { - val[aKey] = { value: aVal, typeName: foundAttr.typeName }; - } - }) - } - return _.extend({}, val, { __internal_UI_businessMetadataName: key }); - })); - this.collection = new Backbone.Collection(); - this.entityModel = new VEntity(); - }, - onHeaderClick: function() { - var that = this; - $('.businessMetaDataPanel').on("hidden.bs.collapse", function(e) { - that.ui.cancel.hide(); - that.ui.saveBusinessMetadata.hide(); - that.ui.addBusinessMetadata.show(); - that.editMode = false; - that.ui.businessMetadataTree.show(); - that.$(".editBox").hide(); - that.updateToActualData(); - if (that.collection && that.collection.length === 0) { - that.ui.addBusinessMetadata.text("Add"); - } else { - that.ui.addBusinessMetadata.text("Edit"); - } - }); - }, - updateToActualData: function(options) { - var silent = options && options.silent || false; - this.collection.reset($.extend(true, [], this.actualCollection.toJSON()), { silent: silent }); - }, - onAddBusinessMetadata: function() { - this.ui.addBusinessMetadata.hide(); - this.ui.saveBusinessMetadata.show(); - this.ui.cancel.show(); - this.editMode = true; - this.ui.businessMetadataTree.hide(); - this.$(".editBox").show(); - this.updateToActualData({ silent: true }); - if (this.collection.length === 0) { - this.createNameElement(); - } else { - this.collection.trigger("reset"); - } - this.panelOpenClose(); - }, - onCancel: function() { - this.ui.cancel.hide(); - this.ui.saveBusinessMetadata.hide(); - this.ui.addBusinessMetadata.show(); - this.editMode = false; - this.ui.businessMetadataTree.show(); - this.$(".editBox").hide(); - this.updateToActualData(); - this.panelOpenClose(); - }, - panelOpenClose: function() { - var collection = this.editMode ? this.collection : this.actualCollection, - headingEl = this.$el.find(".panel-heading.main-parent"); - if (collection && collection.length === 0) { - this.ui.addBusinessMetadata.text("Add"); - } else { - this.ui.addBusinessMetadata.text("Edit"); - if (headingEl.hasClass("collapsed")) { - headingEl.click(); - } - } - }, - validate: function() { - var validation = true; - this.$el.find('.custom-col-1[data-id="value"] [data-key]').each(function(el) { - var val = $(this).val(), - elIsSelect2 = $(this).hasClass("select2-hidden-accessible"); - if (_.isString(val)) { - val = val.trim(); - } - if (_.isEmpty(val)) { - if (validation) { - validation = false; - } - if (elIsSelect2) { - $(this).siblings(".select2").find(".select2-selection").attr("style", "border-color : red !important"); - } else { - $(this).css("borderColor", "red"); - } - } else { - if (elIsSelect2) { - $(this).siblings(".select2").find(".select2-selection").attr("style", ""); - } else { - $(this).css("borderColor", ""); - } - } - }); - return validation; - }, - onSaveBusinessMetadata: function() { - var that = this; - if (!this.validate()) { - return; - } - var nData = this.generateData(); - if (this.actualCollection.length === 0 && _.isEmpty(nData)) { - this.onCancel(); - return; - } - this.entityModel.saveBusinessMetadataEntity(this.guid, { - data: JSON.stringify(nData), - type: "POST", - success: function(data) { - Utils.notifySuccess({ - content: "One or more Business Metadata attribute" + Messages.getAbbreviationMsg(true, 'editSuccessMessage') - }); - that.entity.businessAttributes = data; - that.ui.businessMetadataTree.html(""); - that.editMode = false; - that.fetchCollection(); - that.onCancel(); - - }, - complete: function(model, response) { - //that.hideLoader(); - } - }); - }, - generateData: function() { - var finalObj = {}; - this.collection.forEach(function(model) { - if (!model.has("addAttrButton")) { - var businessMetadataName = model.get("__internal_UI_businessMetadataName"), - modelObj = model.toJSON(); - _.each(modelObj, function(o, k) { - if (k === "isNew" || k === "__internal_UI_businessMetadataName") { - delete modelObj[k]; - return; - } - if (_.isObject(o) && o.value !== undefined) { - modelObj[k] = o.value; - } - }) - if (businessMetadataName !== undefined) { - if (finalObj[businessMetadataName]) { - finalObj[businessMetadataName] = _.extend(finalObj[businessMetadataName], modelObj); - } else { - finalObj[businessMetadataName] = modelObj; - } - } - } - }); - if (_.isEmpty(finalObj)) { - this.actualCollection.forEach(function(model) { - var businessMetadataName = model.get("__internal_UI_businessMetadataName"); - if (businessMetadataName) { - finalObj[businessMetadataName] = {}; - } - }) - } - return finalObj; - }, - createNameElement: function(options) { - var modelObj = { isNew: true }; - this.collection.unshift(modelObj); - }, - renderBusinessMetadata: function() { - var that = this, - li = "" - this.actualCollection.forEach(function(obj) { - var attrLi = ""; - _.each(obj.attributes, function(val, key) { - if (key !== "__internal_UI_businessMetadataName") { - var newVal = val; - if (_.isObject(val) && !_.isUndefinedNull(val.value)) { - newVal = val.value; - if (newVal.length > 0 && val.typeName.indexOf("date") > -1) { - newVal = _.map(newVal, function(dates) { - return Utils.formatDate({ date: dates, zone: false, dateFormat: Globals.dateFormat }); - }); - } - if (val.typeName === "date") { - newVal = Utils.formatDate({ date: newVal, zone: false, dateFormat: Globals.dateFormat }); - } - } - attrLi += "" + _.escape(key) + " (" + _.escape(val.typeName) + ")" + _.escape(newVal) + ""; - } - }); - li += that.associateAttributePanel(obj, attrLi); - }); - var html = li; - if (html === "" && this.readOnlyEntity === false) { - html = '
        No business metadata have been created yet. To add a business metadata, click here
        '; - } - this.ui.businessMetadataTree.html(html); - }, - associateAttributePanel: function(obj, tableBody) { - return ''; - }, - onRender: function() { - if (this.actualCollection && this.actualCollection.length) { - this.$el.find(".panel-heading.main-parent").removeClass("collapsed").attr("aria-expanded", "true"); - this.$el.find("#businessMetadataCollapse").addClass("in").removeAttr("style"); - this.ui.addBusinessMetadata.text("Edit"); - } - this.renderBusinessMetadata(); - } - }); -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/entity/EntityDetailTableLayoutView.js b/dashboardv2/public/js/views/entity/EntityDetailTableLayoutView.js deleted file mode 100644 index 5eee4d71114..00000000000 --- a/dashboardv2/public/js/views/entity/EntityDetailTableLayoutView.js +++ /dev/null @@ -1,115 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/entity/EntityDetailTableLayoutView_tmpl', - 'utils/CommonViewFunction', - 'models/VEntity', - 'utils/Utils' -], function(require, Backbone, EntityDetailTableLayoutView_tmpl, CommonViewFunction, VEntity, Utils) { - 'use strict'; - - var EntityDetailTableLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends EntityDetailTableLayoutView */ - { - _viewName: 'EntityDetailTableLayoutView', - - template: EntityDetailTableLayoutView_tmpl, - - templateHelpers: function() { - return { - editEntity: this.editEntity - }; - }, - - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - detailValue: "[data-id='detailValue']", - noValueToggle: "[data-id='noValueToggle']", - editButton: '[data-id="editButton"]', - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.noValueToggle] = function() { - this.showAllProperties = !this.showAllProperties; - this.ui.noValueToggle.attr("data-original-title", (this.showAllProperties ? "Hide" : "Show") + " empty values"); - Utils.togglePropertyRelationshipTableEmptyValues({ - "inputType": this.ui.noValueToggle, - "tableEl": this.ui.detailValue - }); - }; - events["click " + this.ui.editButton] = 'onClickEditEntity'; - return events; - }, - /** - * intialize a new EntityDetailTableLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'entity', 'typeHeaders', 'attributeDefs', 'attributes', 'editEntity', 'guid', 'entityDefCollection', 'searchVent', 'fetchCollection')); - this.entityModel = new VEntity({}); - this.showAllProperties = false; - }, - bindEvents: function() {}, - onRender: function() { - this.entityTableGenerate(); - }, - entityTableGenerate: function() { - var that = this, - highlightString = $(".atlas-header .global-search-container input.global-search").val(), - table = CommonViewFunction.propertyTable({ - scope: this, - valueObject: _.extend({ "isIncomplete": this.entity.isIncomplete || false }, this.entity.attributes), - attributeDefs: this.attributeDefs, - highlightString: highlightString - }); - this.ui.detailValue.append(table); - Utils.togglePropertyRelationshipTableEmptyValues({ - "inputType": this.ui.noValueToggle, - "tableEl": this.ui.detailValue - }); - setTimeout(function() { - that.$el.find(".searched-term-highlight").addClass("bold"); - }, 5000) - }, - onClickEditEntity: function(e) { - var that = this; - $(e.currentTarget).blur(); - require([ - 'views/entity/CreateEntityLayoutView' - ], function(CreateEntityLayoutView) { - var view = new CreateEntityLayoutView({ - guid: that.guid, - searchVent: that.searchVent, - entityDefCollection: that.entityDefCollection, - typeHeaders: that.typeHeaders, - callback: function() { - that.fetchCollection(); - } - }); - - }); - } - }); - return EntityDetailTableLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/entity/EntityLabelDefineView.js b/dashboardv2/public/js/views/entity/EntityLabelDefineView.js deleted file mode 100644 index 4cb48910089..00000000000 --- a/dashboardv2/public/js/views/entity/EntityLabelDefineView.js +++ /dev/null @@ -1,208 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/entity/EntityLabelDefineView_tmpl', - 'models/VEntity', - 'utils/Utils', - 'utils/Messages', - 'utils/Enums', - 'utils/UrlLinks', - 'utils/CommonViewFunction', -], function(require, Backbone, EntityLabelDefineView_tmpl, VEntity, Utils, Messages, Enums, UrlLinks, CommonViewFunction) { - 'use strict'; - - return Backbone.Marionette.LayoutView.extend({ - _viewName: 'REntityLabelDefineView', - template: EntityLabelDefineView_tmpl, - templateHelpers: function() { - return { - swapItem: this.swapItem, - labels: this.labels, - saveLabels: this.saveLabels, - readOnlyEntity: this.readOnlyEntity, - div_1: this.dynamicId_1, - div_2: this.dynamicId_2 - }; - }, - ui: { - addLabelOptions: "[data-id='addLabelOptions']", - addLabels: "[data-id='addLabels']", - saveLabels: "[data-id='saveLabels']", - cancel: "[data-id='cancel']", - labelsHeader: ".labelsPanel .panel-heading" - }, - events: function() { - var events = {}; - events["change " + this.ui.addLabelOptions] = 'onChangeLabelChange'; - events["click " + this.ui.addLabels] = 'handleBtnClick'; - events["click " + this.ui.saveLabels] = 'saveUserDefinedLabels'; - events["click " + this.ui.cancel] = 'onCancelClick'; - events["click " + this.ui.labelsHeader] = 'onHeaderClick'; - return events; - }, - initialize: function(options) { - var self = this; - _.extend(this, _.pick(options, 'entity', 'customFilter', 'renderAuditTableLayoutView')); - this.swapItem = false, this.saveLabels = false; - this.readOnlyEntity = this.customFilter === undefined ? Enums.entityStateReadOnly[this.entity.status] : this.customFilter; - this.entityModel = new VEntity(this.entity); - this.labels = this.entity.labels || []; - this.dynamicId_1 = CommonViewFunction.getRandomIdAndAnchor(); - this.dynamicId_2 = CommonViewFunction.getRandomIdAndAnchor(); - }, - onRender: function() { - this.populateLabelOptions(); - }, - bindEvents: function() {}, - onHeaderClick: function() { - var that = this; - $(".labelsPanel").on("hidden.bs.collapse", function() { - that.labels = that.entityModel.get("labels") || []; - that.swapItem = false; - that.saveLabels = false; - that.render(); - if (that.labels.length > 0) { - $('.labelsPanel').find(that.ui.labelsHeader.attr('href')).removeClass('in'); - that.ui.labelsHeader.addClass('collapsed').attr('aria-expanded', false); - } - }); - }, - populateLabelOptions: function() { - var that = this, - str = this.labels.map(function(label) { - return ""; - }); - this.ui.addLabelOptions.html(str); - var getLabelData = function(data, selectedData) { - if (data.suggestions.length) { - return _.map(data.suggestions, function(name, index) { - var findValue = _.find(selectedData, { id: name }) - if (findValue) { - return findValue; - } else { - return { - id: name, - text: name - } - } - }); - } else { - var findValue = _.find(selectedData, { id: data.prefixString }) - return findValue ? [findValue] : []; - } - }; - this.ui.addLabelOptions.select2({ - placeholder: "Select Label", - allowClear: false, - tags: true, - multiple: true, - ajax: { - url: UrlLinks.searchApiUrl('suggestions'), - dataType: 'json', - delay: 250, - data: function(params) { - return { - prefixString: params.term, // search term - fieldName: '__labels' - }; - }, - processResults: function(data, params) { - return { results: getLabelData(data, this.$element.select2("data")) }; - }, - cache: true - }, - createTag: function(data) { - var found = _.find(this.$element.select2("data"), { id: data.term }); - if (!found) { - return { id: data.term, text: data.term }; - } - }, - templateResult: this.formatResultSearch - }); - }, - formatResultSearch: function(state) { - if (!state.id) { - return state.text; - } - if (!state.element && state.text.trim() !== "") { - return $("Add '" + _.escape(state.text) + "'"); - } - }, - onChangeLabelChange: function() { - this.labels = this.ui.addLabelOptions.val(); - }, - handleBtnClick: function() { - this.swapItem = !this.swapItem; - if (this.customFilter === undefined) { - this.saveLabels = this.swapItem === true ? true : false; - } else { - this.saveLabels = false; - } - this.render(); - }, - onCancelClick: function() { - this.labels = this.entityModel.get("labels") || []; - this.swapItem = false; - this.saveLabels = false; - this.render(); - }, - saveUserDefinedLabels: function() { - var that = this; - var entityJson = that.entityModel.toJSON(); - if ((entityJson.labels && entityJson.labels.length !== 0) || this.labels.length !== 0) { - var payload = this.labels; - that.entityModel.saveEntityLabels(entityJson.guid, { - data: JSON.stringify(payload), - type: 'POST', - success: function() { - var msg = entityJson.labels === undefined ? 'addSuccessMessage' : 'editSuccessMessage', - caption = "One or more label"; - if (payload.length === 0) { - msg = 'removeSuccessMessage'; - caption = "One or more existing label"; - that.entityModel.unset('labels'); - } else { - that.entityModel.set('labels', payload); - } - Utils.notifySuccess({ - content: caption + Messages.getAbbreviationMsg(true, msg) - }); - that.swapItem = false; - that.saveLabels = false; - that.render(); - if (that.renderAuditTableLayoutView) { - that.renderAuditTableLayoutView(); - } - }, - error: function(e) { - that.ui.saveLabels && that.ui.saveLabels.length > 0 && that.ui.saveLabels[0].setAttribute("disabled", false); - Utils.notifySuccess({ - content: e.message - }); - }, - complete: function() { - that.ui.saveLabels && that.ui.saveLabels.length > 0 && that.ui.saveLabels[0].setAttribute("disabled", false); - that.render(); - } - }); - } - } - }); -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/entity/EntityUserDefineItemView.js b/dashboardv2/public/js/views/entity/EntityUserDefineItemView.js deleted file mode 100644 index 3a6bd633231..00000000000 --- a/dashboardv2/public/js/views/entity/EntityUserDefineItemView.js +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -define(['require', - 'backbone', - 'hbs!tmpl/entity/EntityUserDefineItemView_tmpl' - -], function(require, Backbone, EntityUserDefineItemView_tmpl) { - 'use strict'; - - return Backbone.Marionette.ItemView.extend({ - _viewName: 'EntityUserDefineItemView', - - template: EntityUserDefineItemView_tmpl, - - templateHelpers: function() { - return { - items: this.items, - allValueRemovedUpdate: this.allValueRemovedUpdate - }; - }, - - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - itemKey: "[data-type='key']", - itemValue: "[data-type='value']", - addItem: "[data-id='addItem']", - deleteItem: "[data-id='deleteItem']", - charSupportMsg: "[data-id='charSupportMsg']" - }, - /** ui events hash */ - events: function() { - var events = {}; - events['input ' + this.ui.itemKey] = 'onItemKeyChange'; - events['input ' + this.ui.itemValue] = 'onItemValueChange'; - events['click ' + this.ui.addItem] = 'onAddItemClick'; - events['click ' + this.ui.deleteItem] = 'onDeleteItemClick'; - return events; - }, - - /** - * intialize a new GlobalExclusionComponentView Layout - * @constructs - */ - initialize: function(options) { - if (options.items.length === 0) { - this.items = [{ key: "", value: "" }]; - } else { - this.items = $.extend(true, [], options.items); - } - this.updateParentButtonState = options.updateButtonState; - }, - onRender: function() {}, - onAddItemClick: function(e) { - this.allValueRemovedUpdate = false; - var el = e.currentTarget; - this.items.splice(parseInt(el.dataset.index) + 1, 0, { key: "", value: "" }); - this.render(); - }, - onDeleteItemClick: function(e) { - var el = e.currentTarget; - this.items.splice(el.dataset.index, 1); - this.allValueRemovedUpdate = false; - if (this.items.length === 0) { - var updated = this.updateParentButtonState(); - if (updated === false) { - this.allValueRemovedUpdate = true; - this.render(); - } - } else { - this.render(); - } - }, - onItemKeyChange: function(e) { - var el = e.currentTarget; - this.handleCharSupport(el); - if (!el.value.trim().includes(':')) { - this.items[el.dataset.index].key = _.escape(el.value.trim()); - } - }, - onItemValueChange: function(e) { - var el = e.currentTarget; - this.handleCharSupport(el); - if (!el.value.trim().includes(':')) { - this.items[el.dataset.index].value = el.value.trim(); - } - }, - handleCharSupport: function(el) { - if (el.value.trim().includes(':')) { - el.setAttribute('class', 'form-control errorClass'); - this.ui.charSupportMsg.html("These special character '(:)' are not supported."); - } else { - el.setAttribute('class', 'form-control'); - this.ui.charSupportMsg.html(""); - } - } - }); - -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/entity/EntityUserDefineView.js b/dashboardv2/public/js/views/entity/EntityUserDefineView.js deleted file mode 100644 index 311fbe50511..00000000000 --- a/dashboardv2/public/js/views/entity/EntityUserDefineView.js +++ /dev/null @@ -1,201 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/entity/EntityUserDefineView_tmpl', - 'models/VEntity', - 'utils/Utils', - 'utils/Enums', - 'utils/Messages', - 'utils/CommonViewFunction', -], function(require, Backbone, EntityUserDefineView_tmpl, VEntity, Utils, Enums, Messages, CommonViewFunction) { - 'use strict'; - - return Backbone.Marionette.LayoutView.extend({ - _viewName: 'EntityUserDefineView', - template: EntityUserDefineView_tmpl, - templateHelpers: function() { - return { - customAttibutes: this.customAttibutes, - readOnlyEntity: this.readOnlyEntity, - swapItem: this.swapItem, - saveAttrItems: this.saveAttrItems, - divId_1: this.dynamicId_1, - divId_2: this.dynamicId_2 - }; - }, - ui: { - addAttr: "[data-id='addAttr']", - saveAttrItems: "[data-id='saveAttrItems']", - cancel: "[data-id='cancel']", - addItem: "[data-id='addItem']", - userDefineHeader: ".userDefinePanel .panel-heading" - }, - events: function() { - var events = {}; - events["click " + this.ui.addAttr] = 'onAddAttrClick'; - events["click " + this.ui.addItem] = 'onAddAttrClick'; - events["click " + this.ui.saveAttrItems] = 'onEditAttrClick'; - events["click " + this.ui.cancel] = 'onCancelClick'; - events["click " + this.ui.userDefineHeader] = 'onHeaderClick'; - return events; - }, - initialize: function(options) { - _.extend(this, _.pick(options, 'entity', 'customFilter', 'renderAuditTableLayoutView')); - this.userDefineAttr = this.entity && this.entity.customAttributes || []; - this.initialCall = false; - this.swapItem = false, this.saveAttrItems = false; - this.readOnlyEntity = this.customFilter === undefined ? Enums.entityStateReadOnly[this.entity.status] : this.customFilter; - this.entityModel = new VEntity(this.entity); - this.dynamicId_1 = CommonViewFunction.getRandomIdAndAnchor(); - this.dynamicId_2 = CommonViewFunction.getRandomIdAndAnchor(); - this.generateTableFields(); - }, - onRender: function() {}, - renderEntityUserDefinedItems: function() { - var that = this; - require(['views/entity/EntityUserDefineItemView'], function(EntityUserDefineItemView) { - that.itemView = new EntityUserDefineItemView({ items: that.customAttibutes, updateButtonState: that.updateButtonState.bind(that) }); - that.REntityUserDefinedItemView.show(that.itemView); - }); - }, - bindEvents: {}, - addChildRegion: function() { - this.addRegions({ - REntityUserDefinedItemView: "#r_entityUserDefinedItemView" - }); - this.renderEntityUserDefinedItems(); - }, - onHeaderClick: function() { - var that = this; - $(".userDefinePanel").on("hidden.bs.collapse", function() { - that.swapItem = false; - that.saveAttrItems = false; - that.initialCall = false; - that.render(); - if (that.customAttibutes.length > 0) { - $('.userDefinePanel').find(that.ui.userDefineHeader.attr('href')).removeClass('in'); - that.ui.userDefineHeader.addClass('collapsed').attr('aria-expanded', false); - } - }); - }, - onAddAttrClick: function() { - this.swapItem = !this.swapItem; - if (this.customFilter === undefined) { - this.saveAttrItems = this.swapItem === true ? true : false; - } else { - this.saveAttrItems = false; - } - this.initialCall = true; - this.render(); - if (this.swapItem === true) { - this.addChildRegion(); - } - }, - generateTableFields: function() { - var that = this; - this.customAttibutes = []; - _.each(Object.keys(that.userDefineAttr), function(key, i) { - that.customAttibutes.push({ - key: key, - value: that.userDefineAttr[key] - }); - }); - }, - onEditAttrClick: function() { - this.initialCall = this.customAttibutes.length > 0 ? false : true; - this.setAttributeModal(this.itemView); - }, - updateButtonState: function() { - if (this.customAttibutes.length === 0) { - this.swapItem = false; - this.saveAttrItems = false; - this.render(); - } else { - return false; - } - }, - onCancelClick: function() { - this.initialCall = false; - this.swapItem = false; - this.saveAttrItems = false; - this.render(); - }, - structureAttributes: function(list) { - var obj = {} - list.map(function(o) { - obj[o.key] = o.value; - }); - return obj; - }, - saveAttributes: function(list) { - var that = this; - var entityJson = that.entityModel.toJSON(); - var properties = that.structureAttributes(list); - entityJson.customAttributes = properties; - var payload = { entity: entityJson }; - that.entityModel.createOreditEntity({ - data: JSON.stringify(payload), - type: 'POST', - success: function() { - var msg = that.initialCall ? 'addSuccessMessage' : 'editSuccessMessage', - caption = "One or more user-defined propertie"; // 's' will be added in abbreviation function - that.customAttibutes = list; - if (list.length === 0) { - msg = 'removeSuccessMessage'; - caption = "One or more existing user-defined propertie"; - } - Utils.notifySuccess({ - content: caption + Messages.getAbbreviationMsg(true, msg) - }); - that.swapItem = false; - that.saveAttrItems = false; - that.render(); - if (that.renderAuditTableLayoutView) { - that.renderAuditTableLayoutView(); - } - }, - error: function(e) { - that.initialCall = false; - Utils.notifySuccess({ - content: e.message - }); - that.ui.saveAttrItems.attr("disabled", false); - }, - complete: function() { - that.ui.saveAttrItems.attr("disabled", false); - that.initialCall = false; - } - }); - }, - setAttributeModal: function(itemView) { - var self = this; - this.ui.saveAttrItems.attr("disabled", true); - var list = itemView.$el.find("[data-type]"), - dataList = []; - Array.prototype.push.apply(dataList, itemView.items); - var field = CommonViewFunction.CheckDuplicateAndEmptyInput(list, dataList); - if (field.validation && !field.hasDuplicate) { - self.saveAttributes(itemView.items); - } else { - this.ui.saveAttrItems.attr("disabled", false); - } - } - }); -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/glossary/AssignTermLayoutView.js b/dashboardv2/public/js/views/glossary/AssignTermLayoutView.js deleted file mode 100644 index b4e6a480de2..00000000000 --- a/dashboardv2/public/js/views/glossary/AssignTermLayoutView.js +++ /dev/null @@ -1,293 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/glossary/AssignTermLayoutView_tmpl', - 'utils/Utils', - 'utils/Enums', - 'utils/Messages', - 'utils/UrlLinks', - 'modules/Modal', - 'jquery-steps' -], function(require, Backbone, AssignTermLayoutViewTmpl, Utils, Enums, Messages, UrlLinks, Modal) { - - var AssignTermLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends AssignTermLayoutView */ - { - _viewName: 'AssignTermLayoutView', - - template: AssignTermLayoutViewTmpl, - - templateHelpers: function() { - return { - isAttributeRelationView: this.isAttributeRelationView, - selectedTermAttributeList: Enums.termRelationAttributeList[this.selectedTermAttribute] - }; - }, - - /** Layout sub regions */ - regions: { - RGlossaryTree: "#r_glossaryTree" - }, - - /** ui selector cache */ - ui: { - wizard: '[data-id="wizard"]' - }, - /** ui events hash */ - events: function() { - var events = {}; - return events; - }, - /** - * intialize a new AssignTermLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'glossaryCollection', 'guid', 'callback', 'hideLoader', 'isCategoryView', 'categoryData', 'isTermView', 'termData', 'isAttributeRelationView', 'selectedTermAttribute', 'associatedTerms', 'multiple')); - var that = this; - this.options = options; - if (!this.isCategoryView && !this.isTermView && !this.isAttributeRelationView) { - this.isEntityView = true; - } - this.glossary = { - selectedItem: {} - } - var title = ""; - if (this.isCategoryView || this.isEntityView) { - title = ("Assign term to " + (this.isCategoryView ? "Category" : "entity")) - } else if (this.isAttributeRelationView) { - title = "Assign term to " + this.selectedTermAttribute; - } else { - title = "Assign Category to term"; - } - this.modal = new Modal({ - "title": title, - "content": this, - "cancelText": "Cancel", - "okText": "Assign", - "allowCancel": true, - "showFooter": this.isAttributeRelationView ? false : true, - "mainClass": "wizard-modal", - "okCloses": false - }); - this.modal.open(); - this.modal.$el.find('button.ok').attr("disabled", true); - this.modal.on('closeModal', function() { - that.modal.trigger('cancel'); - if (that.assignTermError && that.hideLoader) { - that.hideLoader(); - } - if (options.onModalClose) { - options.onModalClose() - } - }); - this.modal.on('ok', function() { - that.assignTerm(); - }); - this.bindEvents(); - }, - bindEvents: function() { - this.listenTo(this.glossaryCollection, "node_selected", function(skip) { - this.modal.$el.find('button.ok').attr("disabled", false); - }, this); - }, - onRender: function() { - this.renderGlossaryTree(); - var that = this; - if (this.isAttributeRelationView) { - this.ui.wizard.steps({ - headerTag: "h3", - bodyTag: "section", - transitionEffect: "slideLeft", - autoFocus: true, - enableCancelButton: true, - transitionEffect: $.fn.steps.transitionEffect.none, - transitionEffectSpeed: 200, - labels: { - cancel: "Cancel", - finish: "Assign", - next: "Next", - previous: "Previous", - loading: "Loading ..." - }, - onStepChanging: function(event, currentIndex, newIndex) { - var isMatch = that.glossary.selectedItem.type == "GlossaryTerm"; - if (!isMatch) { - Utils.notifyWarn({ - content: "Please select Term for association" - }); - } - return isMatch - }, - onFinished: function(event, currentIndex) { - var $assignBtn = $(this).find('a[href="#finish"]'); - if (!$assignBtn.attr('disabled')) { - $assignBtn.attr('disabled', true).showButtonLoader(); - $assignBtn.parent().attr('aria-disabled', 'true').addClass('disabled'); - that.assignTerm(); - } - }, - onCanceled: function(event) { - that.modal.trigger('cancel'); - }, - }); - } - }, - assignTerm: function() { - this.assignTermError = false; - var that = this, - data = [], - termAttributeFormData = [], - selectedItem = this.glossary.selectedItem, - selectedGuid = selectedItem.guid, - termName = selectedItem.text, - ajaxOptions = { - success: function(rModel, response) { - Utils.notifySuccess({ - content: (that.isCategoryView || that.isEntityView || that.isAttributeRelationView ? "Term" : "Category") + " is associated successfully " - }); - that.modal.trigger('closeModal'); - if (that.callback) { - that.callback(); - } - }, - cust_error: function() { - var $assignBtn = that.$el.find('a[href="#finish"]'); - $assignBtn.removeAttr('disabled').hideButtonLoader(); - $assignBtn.parent().attr('aria-disabled', 'false').removeClass('disabled'); - that.assignTermError = true; - }, - complete: function() { - that.modal.trigger('closeModal'); - } - }, - model = new this.glossaryCollection.model(); - if (this.isCategoryView) { - data = $.extend(true, {}, this.categoryData); - if (data.terms) { - data.terms.push({ "termGuid": selectedGuid }); - } else { - data.terms = [{ "termGuid": selectedGuid }]; - } - model.assignTermToCategory(_.extend(ajaxOptions, { data: JSON.stringify(data), guid: data.guid })); - } else if (this.isTermView) { - data = $.extend(true, {}, this.termData); - if (data.categories) { - data.categories.push({ "categoryGuid": selectedGuid }); - } else { - data.categories = [{ "categoryGuid": selectedGuid }]; - } - model.assignCategoryToTerm(_.extend(ajaxOptions, { data: JSON.stringify(data), guid: data.guid })); - } else if (this.isAttributeRelationView) { - termAttributeFormData = this.$('[data-id="termAttributeForm"]').serializeArray().reduce(function(obj, item) { - obj[item.name] = item.value; - return obj; - }, {}), - data = $.extend(true, {}, this.termData); - if (data[this.selectedTermAttribute]) { - data[this.selectedTermAttribute].push(_.extend({ "termGuid": selectedGuid }, termAttributeFormData)); - } else { - data[this.selectedTermAttribute] = [_.extend({ "termGuid": selectedGuid }, termAttributeFormData)]; - } - model.assignTermToAttributes(_.extend(ajaxOptions, { data: JSON.stringify(data), guid: data.guid })); - } else { - var deletedEntity = [], - skipEntity = []; - - if (this.multiple) { - _.each(that.multiple, function(entity, i) { - var name = Utils.getName(entity.model); - if (Enums.entityStateReadOnly[entity.model.status]) { - deletedEntity.push(name); - } else { - if (_.indexOf((entity.model.meaningNames || _.pluck(entity.model.meanings, 'displayText')), termName) === -1) { - data.push({ guid: entity.model.guid }) - } else { - skipEntity.push(name); - } - } - }); - if (deletedEntity.length) { - Utils.notifyError({ - html: true, - content: "" + deletedEntity.join(', ') + - " " + (deletedEntity.length === 1 ? "entity " : "entities ") + - Messages.assignTermDeletedEntity - }); - that.modal.close(); - } - } else { - data.push({ "guid": that.guid }); - } - if (skipEntity.length) { - var text = "" + skipEntity.length + " of " + that.multiple.length + - " entities selected have already been associated with " + termName + - " term, Do you want to associate the term with other entities ?", - removeCancelButton = false; - if ((skipEntity.length + deletedEntity.length) === that.multiple.length) { - text = (skipEntity.length > 1 ? "All selected" : "Selected") + " entities have already been associated with " + termName + " term"; - removeCancelButton = true; - } - var notifyObj = { - text: text, - modal: true, - ok: function(argument) { - if (data.length) { - model.assignTermToEntity(selectedGuid, _.extend(ajaxOptions, { data: JSON.stringify(data) })); - } - }, - cancel: function(argument) {} - } - if (removeCancelButton) { - notifyObj['confirm'] = { - confirm: true, - buttons: [{ - text: 'Ok', - addClass: 'btn-atlas btn-md', - click: function(notice) { - notice.remove(); - } - }, - null - ] - } - } - Utils.notifyConfirm(notifyObj); - } else if (data.length) { - model.assignTermToEntity(selectedGuid, _.extend(ajaxOptions, { data: JSON.stringify(data) })); - } - } - }, - renderGlossaryTree: function() { - var that = this; - require(['views/glossary/GlossaryLayoutView'], function(GlossaryLayoutView) { - that.RGlossaryTree.show(new GlossaryLayoutView(_.extend({ - "isAssignTermView": that.isCategoryView, - "isAssignCategoryView": that.isTermView, - "isAssignEntityView": that.isEntityView, - "isAssignAttributeRelationView": that.isAttributeRelationView, - "glossary": that.glossary, - "associatedTerms": that.associatedTerms - }, that.options))); - }); - }, - }); - return AssignTermLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/glossary/CreateEditCategoryTermLayoutView.js b/dashboardv2/public/js/views/glossary/CreateEditCategoryTermLayoutView.js deleted file mode 100644 index 41e8f5c128d..00000000000 --- a/dashboardv2/public/js/views/glossary/CreateEditCategoryTermLayoutView.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/glossary/CreateEditCategoryTermLayoutView_tmpl', - 'utils/Utils', - 'utils/UrlLinks' -], function(require, Backbone, CreateEditCategoryTermLayoutViewTmpl, Utils, UrlLinks) { - - var CreateEditCategoryTermLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends CreateEditCategoryTermLayoutView */ - { - _viewName: 'CreateEditCategoryTermLayoutView', - - template: CreateEditCategoryTermLayoutViewTmpl, - - templateHelpers: function() { - return { - create: this.create, - modelJSON: this.modelJSON - }; - }, - - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - "qualifiedName": "[data-id='qualifiedName']", - "name": "[data-id='name']", - "shortDescription": "[data-id='shortDescription']", - "longDescription": "[data-id='longDescription']", - "categoryTermForm": "[data-id='categoryTermForm']" - }, - /** ui events hash */ - events: function() { - var events = {}; - return events; - }, - /** - * intialize a new CreateEditCategoryTermLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'glossaryCollection', 'modelJSON')); - if (!this.modelJSON) { - this.create = true; - } - }, - bindEvents: function() {}, - onRender: function() {} - }); - return CreateEditCategoryTermLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/glossary/CreateEditGlossaryLayoutView.js b/dashboardv2/public/js/views/glossary/CreateEditGlossaryLayoutView.js deleted file mode 100644 index d43eb8396be..00000000000 --- a/dashboardv2/public/js/views/glossary/CreateEditGlossaryLayoutView.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/glossary/CreateEditGlossaryLayoutView_tmpl', - 'utils/Utils', - 'utils/UrlLinks' -], function(require, Backbone, CreateEditGlossaryLayoutViewTmpl, Utils, UrlLinks) { - - var CreateEditGlossaryLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends CreateEditGlossaryLayoutView */ - { - _viewName: 'CreateEditGlossaryLayoutView', - - template: CreateEditGlossaryLayoutViewTmpl, - - templateHelpers: function() { - return { - create: this.create - }; - }, - - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - "name": "[data-id='name']", - "shortDescription": "[data-id='shortDescription']", - "longDescription": "[data-id='longDescription']", - "glossaryForm": "[data-id='glossaryForm']" - }, - /** ui events hash */ - events: function() { - var events = {}; - return events; - }, - /** - * intialize a new CreateEditGlossaryLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'glossaryCollection', 'model')); - if (!this.model) { - this.create = true; - } - }, - bindEvents: function() {}, - onRender: function() {} - }); - return CreateEditGlossaryLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js b/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js deleted file mode 100644 index e30034cc6b7..00000000000 --- a/dashboardv2/public/js/views/glossary/GlossaryDetailLayoutView.js +++ /dev/null @@ -1,508 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/glossary/GlossaryDetailLayoutView_tmpl', - 'utils/Utils', - 'utils/Messages', - 'utils/Globals', - 'utils/CommonViewFunction', - 'collection/VGlossaryList' -], function(require, Backbone, GlossaryDetailLayoutViewTmpl, Utils, Messages, Globals, CommonViewFunction, VGlossaryList) { - 'use strict'; - - var GlossaryDetailLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends GlossaryDetailLayoutView */ - { - _viewName: 'GlossaryDetailLayoutView', - - template: GlossaryDetailLayoutViewTmpl, - - /** Layout sub regions */ - regions: { - RSearchResultLayoutView: "#r_searchResultLayoutView", - RTagTableLayoutView: "#r_tagTableLayoutView", - RRelationLayoutView: "#r_relationLayoutView" - }, - templateHelpers: function() { - return { - isTermView: this.isTermView, - isCategoryView: this.isCategoryView - }; - }, - - /** ui selector cache */ - ui: { - details: "[data-id='details']", - editButton: "[data-id='editButton']", - title: "[data-id='title']", - shortDescription: "[data-id='shortDescription']", - longDescription: "[data-id='longDescription']", - - categoryList: "[data-id='categoryList']", - removeCategory: "[data-id='removeCategory']", - categoryClick: "[data-id='categoryClick']", - addCategory: "[data-id='addCategory']", - - termList: "[data-id='termList']", - removeTerm: "[data-id='removeTerm']", - termClick: "[data-id='termClick']", - addTerm: "[data-id='addTerm']", - - tagList: "[data-id='tagListTerm']", - removeTag: '[data-id="removeTagTerm"]', - tagClick: '[data-id="tagClickTerm"]', - addTag: '[data-id="addTagTerm"]', - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.categoryClick] = function(e) { - if (e.target.nodeName.toLocaleLowerCase() == "i") { - this.onClickRemoveAssociationBtn(e); - } else { - var guid = $(e.currentTarget).data('guid'), - gId = this.data.anchor && this.data.anchor.glossaryGuid, - categoryObj = _.find(this.data.categories, { "categoryGuid": guid }); - this.glossary.selectedItem = { "type": "GlossaryCategory", "guid": guid, "model": categoryObj }; - Utils.setUrl({ - url: '#!/glossary/' + guid, - mergeBrowserUrl: false, - urlParams: { gType: "category", viewType: "category", fromView: "glossary", gId: gId }, - trigger: true, - updateTabState: true - }); - } - }; - events["click " + this.ui.termClick] = function(e) { - if (e.target.nodeName.toLocaleLowerCase() == "i") { - this.onClickRemoveAssociationBtn(e); - } else { - var guid = $(e.currentTarget).data('guid'), - gId = this.data.anchor && this.data.anchor.glossaryGuid, - termObj = _.find(this.data.terms, { "termGuid": guid }); - this.glossary.selectedItem = { "type": "GlossaryTerm", "guid": guid, "model": termObj }; - Utils.setUrl({ - url: '#!/glossary/' + guid, - mergeBrowserUrl: false, - urlParams: { gType: "term", viewType: "term", fromView: "glossary", gId: gId }, - trigger: true, - updateTabState: true - }); - } - }; - events["click " + this.ui.tagClick] = function(e) { - if (e.target.nodeName.toLocaleLowerCase() == "i") { - this.onClickTagCross(e); - } else { - Utils.setUrl({ - url: '#!/tag/tagAttribute/' + e.currentTarget.textContent, - mergeBrowserUrl: false, - trigger: true - }); - } - }; - events["click " + this.ui.editButton] = function(e) { - var that = this, - model = this.glossaryCollection.fullCollection.get(this.guid); - if (this.isGlossaryView) { - CommonViewFunction.createEditGlossaryCategoryTerm({ - "model": model, - "isGlossaryView": this.isGlossaryView, - "collection": this.glossaryCollection, - "callback": function(sModel) { - var data = sModel.toJSON(); - model.set(data, { silent: true }); // update glossaryCollection - that.data = data; - that.renderDetails(that.data); - that.glossaryCollection.trigger("update:details", { isGlossaryUpdate: true }); - } - }); - } else { - CommonViewFunction.createEditGlossaryCategoryTerm({ - "isTermView": this.isTermView, - "isCategoryView": this.isCategoryView, - "model": this.data, - "collection": this.glossaryCollection, - "callback": function(data) { - if (data.name != that.data.name) { - var glossary = that.glossaryCollection.fullCollection.get(data.anchor.glossaryGuid); - if (that.isTermView) { - _.find(glossary.get('terms'), function(obj) { - if (obj.termGuid == data.guid) { - obj.displayText = data.name - } - }); - } else if (!data.parentCategory) { - _.find(glossary.get('categories'), function(obj) { - if (obj.categoryGuid == data.guid) { - obj.displayText = data.name - } - }); - } - that.glossaryCollection.trigger("update:details", { data: that.data }); - } - that.data = data; - that.renderDetails(that.data); - } - }); - } - }; - events["click " + this.ui.addTerm] = 'onClickAddTermBtn'; - events["click " + this.ui.addCategory] = 'onClickAddTermBtn'; - events["click " + this.ui.addTag] = 'onClickAddTagBtn'; - return events; - }, - /** - * intialize a new GlossaryDetailLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'guid', 'glossaryCollection', 'glossary', 'collection', 'typeHeaders', 'value', 'entityDefCollection', 'enumDefCollection', 'classificationDefCollection', 'searchVent')); - if (this.value && this.value.gType) { - if (this.value.gType == "category") { - this.isCategoryView = true; - } else if (this.value.gType == "term") { - this.isTermView = true; - } else { - this.isGlossaryView = true; - } - } - this.selectedTermAttribute = null; - }, - onRender: function() { - this.$('.fontLoader-relative').show(); - this.getData(); - this.bindEvents(); - }, - bindEvents: function() { - var that = this; - }, - getData: function() { - if (this.isGlossaryView) { - if (this.glossaryCollection.fullCollection.length) { - this.data = this.glossaryCollection.fullCollection.get(this.guid).toJSON(); - this.glossaryCollection.trigger("data:updated", $.extend(true, {}, this.data)); - this.renderDetails(this.data); - } else { - this.listenTo(this.glossaryCollection.fullCollection, "reset ", function(skip) { - var foundGlossary = this.glossaryCollection.fullCollection.get(this.guid); - this.data = foundGlossary ? foundGlossary.toJSON() : null; - this.glossaryCollection.trigger("data:updated", $.extend(true, {}, this.data)); - if (this.data == null) { - this.glossary.selectedItem = {}; - Utils.setUrl({ - url: '#!/glossary', - mergeBrowserUrl: false, - urlParams: null, - trigger: true, - updateTabState: true - }); - } - this.renderDetails(this.data); - }, this); - } - } else {; - Utils.showTitleLoader(this.$('.page-title .fontLoader'), this.ui.details); - var getApiFunctionKey = "getCategory", - that = this; - if (this.isTermView) { - getApiFunctionKey = "getTerm"; - } - this.glossaryCollection[getApiFunctionKey]({ - "guid": this.guid, - "ajaxOptions": { - success: function(data) { - if (that.isDestroyed) { - return; - } - that.data = data; - if (that.isTermView) { - var tags = { - 'self': [], - 'propagated': [], - 'propagatedMap': {}, - 'combineMap': {} - }; - if (that.data) { - var tagObject = that.data.classifications; - _.each(tagObject, function(val) { - var typeName = val.typeName; - if (val.entityGuid === that.guid) { - tags['self'].push(val) - } else { - tags['propagated'].push(val); - if (tags.propagatedMap[typeName]) { - tags.propagatedMap[typeName]["count"] += tags.propagatedMap[typeName]["count"]; - } else { - tags.propagatedMap[typeName] = val; - tags.propagatedMap[typeName]["count"] = 1; - } - } - if (tags.combineMap[typeName] === undefined) { - tags.combineMap[typeName] = val; - } - }); - tags.self = _.sortBy(tags.self, "typeName"); - tags.propagated = _.sortBy(tags.propagated, "typeName"); - } - var obj = { - "guid": that.guid, - "entityDefCollection": that.entityDefCollection, - "typeHeaders": that.typeHeaders, - "tagCollection": that.collection, - "enumDefCollection": that.enumDefCollection, - "classificationDefCollection": that.classificationDefCollection, - "glossaryCollection": that.glossaryCollection, - "searchVent": that.searchVent, - "tags": tags, - "getSelectedTermAttribute": function() { - return that.selectedTermAttribute; - }, - "setSelectedTermAttribute": function(val) { - that.selectedTermAttribute = val; - } - } - that.renderSearchResultLayoutView(obj); - that.renderTagTableLayoutView(obj); - that.renderRelationLayoutView(obj); - } - that.glossaryCollection.trigger("data:updated", $.extend(true, {}, data)); - that.glossary.selectedItem.model = data; - that.glossary.selectedItem.guid = data.guid; - that.renderDetails(data) - }, - cust_error: function() {} - } - }); - } - }, - renderDetails: function(data) { - Utils.hideTitleLoader(this.$('.fontLoader'), this.ui.details); - if (data) { - this.ui.title.text(data.name || data.displayText || data.qualifiedName); - this.ui.shortDescription.text(data.shortDescription ? data.shortDescription : ""); - this.ui.longDescription.text(data.longDescription ? data.longDescription : ""); - this.generateCategories(data.categories); - this.generateTerm(data.terms); - this.generateTag(data.classifications); - } else { - this.ui.title.text("No Data found"); - } - }, - generateCategories: function(data) { - var that = this, - categories = ""; - _.each(data, function(val) { - var name = _.escape(val.displayText); - categories += '' + name + ''; - }); - this.ui.categoryList.find("span.btn").remove(); - this.ui.categoryList.prepend(categories); - }, - generateTerm: function(data) { - var that = this, - terms = ""; - _.each(data, function(val) { - var name = _.escape(val.displayText); - terms += '' + name + ''; - }); - this.ui.termList.find("span.btn").remove(); - this.ui.termList.prepend(terms); - - }, - generateTag: function(tagObject) { - var that = this, - tagData = ""; - _.each(tagObject, function(val) { - tagData += '' + val.typeName + ''; - }); - this.ui.tagList.find("span.btn").remove(); - this.ui.tagList.prepend(tagData); - }, - getCategoryTermCount: function(collection, matchString) { - var terms = 0; - _.each(collection, function(model) { - if (model.get(matchString)) { - terms += model.get(matchString).length; - } - }); - return terms; - }, - onClickAddTermBtn: function(e) { - var that = this, - glossary = this.glossaryCollection; - if (this.value && this.value.gId) { - var foundModel = this.glossaryCollection.find({ guid: this.value.gId }); - if (foundModel) { - glossary = new VGlossaryList([foundModel.toJSON()], { - comparator: function(item) { - return item.get("name"); - } - }); - } - } - var obj = { - callback: function() { - that.getData(); - }, - glossaryCollection: glossary, - }, - emptyListMessage = this.isCategoryView ? "There are no available terms that can be associated with this category" : "There are no available categories that can be associated with this term"; - - if (this.isCategoryView) { - obj = _.extend(obj, { - categoryData: this.data, - associatedTerms: (this.data && this.data.terms && this.data.terms.length > 0) ? this.data.terms : [], - isCategoryView: this.isCategoryView, - }); - } else { - obj = _.extend(obj, { - termData: this.data, - isTermView: this.isTermView, - }); - } - if (this.getCategoryTermCount(glossary.fullCollection.models, this.isCategoryView ? "terms" : "categories")) { - this.AssignTermLayoutViewModal(obj); - } else { - Utils.notifyInfo({ - content: emptyListMessage - }); - } - }, - AssignTermLayoutViewModal: function(termCategoryObj) { - var that = this; - require(['views/glossary/AssignTermLayoutView'], function(AssignTermLayoutView) { - var view = new AssignTermLayoutView(termCategoryObj); - view.modal.on('ok', function() { - that.hideLoader(); - }); - - }); - }, - onClickAddTagBtn: function(e) { - var that = this; - require(['views/tag/AddTagModalView'], function(AddTagModalView) { - var tagList = []; - _.map(that.data.classifications, function(obj) { - if (obj.entityGuid === that.guid) { - tagList.push(obj.typeName); - } - }); - var view = new AddTagModalView({ - guid: that.guid, - tagList: tagList, - callback: function() { - that.getData(); - if (that.searchVent) { - that.searchVent.trigger('entityList:refresh'); - } - }, - showLoader: that.showLoader.bind(that), - hideLoader: that.hideLoader.bind(that), - collection: that.classificationDefCollection, - enumDefCollection: that.enumDefCollection - }); - }); - }, - onClickTagCross: function(e) { - var that = this, - tagName = $(e.currentTarget).text(), - termName = this.data.name; - CommonViewFunction.deleteTag(_.extend({}, { - msg: "
        Remove: " + "" + _.escape(tagName) + " assignment from " + _.escape(termName) + "?
        ", - titleMessage: Messages.removeTag, - okText: "Remove", - showLoader: that.showLoader.bind(that), - hideLoader: that.hideLoader.bind(that), - tagName: tagName, - guid: that.guid, - callback: function() { - that.getData(); - if (that.searchVent) { - that.searchVent.trigger('entityList:refresh'); - } - } - })); - }, - onClickRemoveAssociationBtn: function(e) { - var $el = $(e.currentTarget), - guid = $el.data('guid'), - name = $el.text(), - that = this; - CommonViewFunction.removeCategoryTermAssociation({ - selectedGuid: guid, - model: that.data, - collection: that.glossaryCollection, - msg: "
        Remove: " + "" + _.escape(name) + " assignment from " + _.escape(that.data.name) + "?
        ", - titleMessage: Messages.glossary[that.isTermView ? "removeCategoryfromTerm" : "removeTermfromCategory"], - isCategoryView: that.isCategoryView, - isTermView: that.isTermView, - buttonText: "Remove", - showLoader: that.hideLoader.bind(that), - hideLoader: that.hideLoader.bind(that), - callback: function() { - that.getData(); - } - }); - }, - showLoader: function() { - Utils.showTitleLoader(this.$('.page-title .fontLoader'), this.ui.details); - }, - hideLoader: function() { - Utils.hideTitleLoader(this.$('.page-title .fontLoader'), this.ui.details); - }, - renderTagTableLayoutView: function(options) { - var that = this; - require(['views/tag/TagDetailTableLayoutView'], function(TagDetailTableLayoutView) { - if (that.RTagTableLayoutView) { - that.RTagTableLayoutView.show(new TagDetailTableLayoutView(_.extend({}, options, { - "entityName": _.escape(that.ui.title.text()), - "fetchCollection": that.getData.bind(that), - "entity": that.data - }))); - } - }); - }, - renderSearchResultLayoutView: function(options) { - var that = this; - require(['views/search/SearchResultLayoutView'], function(SearchResultLayoutView) { - if (that.RSearchResultLayoutView) { - that.RSearchResultLayoutView.show(new SearchResultLayoutView(_.extend({}, options, { - "value": { "searchType": "basic", "term": that.data.qualifiedName }, - "fromView": "glossary" - }))); - } - }); - }, - renderRelationLayoutView: function(options) { - var that = this; - require(['views/glossary/TermRelationAttributeLayoutView'], function(TermRelationAttributeLayoutView) { - if (that.RRelationLayoutView) { - that.RRelationLayoutView.show(new TermRelationAttributeLayoutView(_.extend({}, options, { - "entityName": that.ui.title.text(), - "fetchCollection": that.getData.bind(that), - "data": that.data - }))); - } - }); - }, - }); - return GlossaryDetailLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/glossary/GlossaryLayoutView.js b/dashboardv2/public/js/views/glossary/GlossaryLayoutView.js deleted file mode 100644 index a13ad4a806b..00000000000 --- a/dashboardv2/public/js/views/glossary/GlossaryLayoutView.js +++ /dev/null @@ -1,860 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/glossary/GlossaryLayoutView_tmpl', - 'utils/Utils', - 'utils/Messages', - 'utils/Globals', - 'utils/UrlLinks', - 'utils/CommonViewFunction', - 'jstree' -], function(require, Backbone, GlossaryLayoutViewTmpl, Utils, Messages, Globals, UrlLinks, CommonViewFunction) { - 'use strict'; - - var GlossaryLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends GlossaryLayoutView */ - { - _viewName: 'GlossaryLayoutView', - - template: GlossaryLayoutViewTmpl, - - /** Layout sub regions */ - regions: {}, - templateHelpers: function() { - return { - isAssignView: this.isAssignView, - importTmplUrl: UrlLinks.glossaryImportTempUrl(), - isAssignAttributeRelationView: this.isAssignAttributeRelationView - }; - }, - - /** ui selector cache */ - ui: { - createGlossary: "[data-id='createGlossary']", - refreshGlossary: "[data-id='refreshGlossary']", - searchTerm: "[data-id='searchTerm']", - searchCategory: "[data-id='searchCategory']", - glossaryView: 'input[name="glossaryView"]', - termTree: "[data-id='termTree']", - categoryTree: "[data-id='categoryTree']", - importGlossary: "[data-id='importGlossary']", - glossaryTreeLoader: "[data-id='glossaryTreeLoader']", - glossaryTreeView: "[data-id='glossaryTreeView']" - }, - /** ui events hash */ - events: function() { - var events = {}; - events["change " + this.ui.glossaryView] = 'glossaryViewToggle'; - events["click " + this.ui.createGlossary] = function(e) { - var that = this; - if (e) { - $(e.currentTarget).attr("disabled", "true"); - } - CommonViewFunction.createEditGlossaryCategoryTerm({ - isGlossaryView: true, - collection: this.glossaryCollection, - callback: function() { - that.ui.createGlossary.removeAttr("disabled"); - that.getGlossary(); - }, - onModalClose: function() { - that.ui.createGlossary.removeAttr("disabled"); - } - }) - }; - events["click " + this.ui.refreshGlossary] = function() { - this.ui.refreshGlossary.attr("disabled", true); - this.getGlossary(); - }; - events["click " + this.ui.importGlossary] = 'onClickImportGlossary'; - events["keyup " + this.ui.searchTerm] = function() { - this.ui.termTree.jstree("search", _.escape(this.ui.searchTerm.val())); - }; - events["keyup " + this.ui.searchCategory] = function() { - this.ui.categoryTree.jstree("search", this.ui.searchCategory.val()); - }; - return events; - }, - /** - * intialize a new GlossaryLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'associatedTerms', 'guid', 'value', 'glossaryCollection', 'glossary', 'isAssignTermView', 'isAssignCategoryView', 'isAssignEntityView', 'isAssignAttributeRelationView', 'importVent')); - this.viewType = "term"; - this.isAssignView = this.isAssignTermView || this.isAssignCategoryView || this.isAssignEntityView || this.isAssignAttributeRelationView; - this.bindEvents(); - this.query = { - term: {}, - category: {} - }; - if (Utils.getUrlState.isGlossaryTab() && this.value && this.value.viewType) { - this.viewType = this.value.viewType; - this.query[this.viewType] = _.extend({}, this.value, { "guid": this.guid }); - } - }, - bindEvents: function() { - var that = this; - this.listenTo(this.glossaryCollection.fullCollection, "reset add change", function(skip) { - this.generateTree(); - this.setValues(); - this.changeLoaderState(false); - this.ui.refreshGlossary.attr("disabled", false); - }, this); - this.listenTo(this.glossaryCollection, "update:details", function(options) { - var isGlossaryUpdate = options.isGlossaryUpdate; - if (isGlossaryUpdate) { - if (this.ui.termTree.jstree(true).refresh) { - this.ui.termTree.jstree(true).refresh(); - } - if (this.ui.categoryTree.jstree(true).refresh) { - this.ui.categoryTree.jstree(true).refresh(); - } - } else { - var $tree = this.ui[this.viewType == "term" ? "termTree" : "categoryTree"]; - if ($tree.jstree(true).refresh) { - $tree.jstree(true).refresh(); - this.setValues({ trigger: false }); - } - } - this.changeLoaderState(false); - }, this); - if (!this.isAssignView) { - $('body').on('click', '.termPopoverOptions li, .categoryPopoverOptions li', function(e) { - that.$('.termPopover,.categoryPopover').popover('hide'); - that[$(this).find('a').data('fn')](e) - }); - } - if (this.importVent) { - this.importVent.on("Import:Glossary:Update", function(options) { - that.getGlossary(); - }); - } - }, - onRender: function() { - this.changeLoaderState(true); - if (this.isAssignCategoryView) { - this.$('.category-view').show(); - this.$('.term-view').hide(); - } - if (this.isAssignView && this.glossaryCollection.fullCollection.length) { - this.generateTree(); - this.disableNodesList = this.getDisableNodes(); - } else { - this.getGlossary(); - } - }, - changeLoaderState: function(showLoader) { - if (showLoader) { - this.ui.glossaryTreeLoader.show(); - this.ui.glossaryTreeView.hide(); - } else { - this.ui.glossaryTreeLoader.hide(); - this.ui.glossaryTreeView.show(); - } - }, - setValues: function(options) { - if (this.viewType == "category") { - if (!this.ui.glossaryView.prop("checked")) { - this.ui.glossaryView.prop("checked", true).trigger("change", options); - } - } else { - if (this.ui.glossaryView.prop("checked")) { - this.ui.glossaryView.prop("checked", false).trigger("change", options); - } - } - }, - glossaryViewToggle: function(e, options) { - var that = this; - if (e.currentTarget.checked) { - this.$('.category-view').show(); - this.$('.term-view').hide(); - this.viewType = "category"; - this.$('.dropdown-toggle').attr('disabled', 'disabled'); - } else { - this.$('.term-view').show(); - this.$('.category-view').hide(); - this.viewType = "term"; - this.$('.dropdown-toggle').removeAttr('disabled'); - } - var setDefaultSelector = function() { - if (!that.value) { - return; - } - var model = null; - if (that.value.gId) { - model = that.glossaryCollection.fullCollection.get(that.value.gId); - } else { - model = that.glossaryCollection.fullCollection.first(); - } - model = model.toJSON ? model.toJSON() : model; - that.glossary.selectedItem = { - type: "Glossary", - guid: model.guid, - id: model.guid, - model: model, - text: model.name, - gType: "glossary" - } - } - if (Utils.getUrlState.isGlossaryTab()) { - var obj = this.query[this.viewType], - $tree = this.ui[(this.viewType == "term" ? "termTree" : "categoryTree")]; - obj["gId"] = that.value.gId; //this Property added, Because when we toggle the GlossaryViewButton it does not adds the gId which is required for selection. - if (obj.guid) { - var node = $tree.jstree(true).get_node(obj.guid); - if (node) { - this.glossary.selectedItem = node.original; - $tree.jstree('activate_node', obj.guid); - } - } else { - if (that.glossaryCollection.fullCollection.length) { - setDefaultSelector(); - $tree.jstree('activate_node', that.glossary.selectedItem.guid); - } - } - this.query[this.viewType] = _.extend(obj, _.pick(this.glossary.selectedItem, 'model', 'guid', 'gType', 'type'), { "viewType": this.viewType, "isNodeNotFoundAtLoad": this.query[this.viewType].isNodeNotFoundAtLoad }); - var url = _.isEmpty(this.glossary.selectedItem) ? '#!/glossary' : '#!/glossary/' + this.glossary.selectedItem.guid; - Utils.setUrl({ - "url": url, - "urlParams": _.extend({}, _.omit(obj, 'guid', 'model', 'type', 'isNodeNotFoundAtLoad')), - "mergeBrowserUrl": false, - "trigger": (options && !_.isUndefined(options.trigger) ? options.trigger : true), - "updateTabState": true - }); - } - }, - getGlossary: function() { - this.changeLoaderState(true); - this.glossaryCollection.fetch({ reset: true }); - }, - generateCategoryData: function(options) { - return _.map(options.data, function(obj) { - return { - "text": _.escape(obj.displayText), - "icon": "fa fa-files-o", - "guid": obj.categoryGuid, - "id": obj.categoryGuid, - "glossaryId": options.node.glossaryId, - "glossaryName": options.node.glossaryName, - "model": obj, - "type": "GlossaryCategory", - "gType": "category", - "children": true - } - }); - }, - getCategory: function(options) { - var that = this; - this.glossaryCollection.getCategory({ - "guid": options.node.guid, - "related": true, - "ajaxOptions": { - success: function(data) { - if (data && data.children) { - options.callback(that.generateCategoryData(_.extend({}, { "data": data.children }, options))); - } else { - options.callback([]); - } - }, - cust_error: function() { - options.callback([]); - } - } - }); - }, - generateData: function(opt) { - var that = this, - selectedGuid = that.guid, - associatedTerms = that.associatedTerms, - type = opt.type; - - if (opt.type == this.viewType) { - this.query[opt.type].isNodeNotFoundAtLoad = true; - } - var getSelectedState = function(options) { - var objGuid = options.objGuid, - node = options.node, - index = options.index; - if (that.isAssignView) { - return { - 'opened': true - } - } else if (!that.guid) { - that.query[that.viewType].isNodeNotFoundAtLoad = false; - var selectedItem = { - "type": "Glossary", - "gType": "glossary", - "model": that.glossaryCollection.fullCollection.first().toJSON() - }; - selectedItem.text = selectedItem.model.name; - selectedItem.guid = selectedItem.model.guid; - if (index == 0 && selectedItem.guid == objGuid) { - that.glossary.selectedItem = selectedItem; - that.query[that.viewType].model = selectedItem.model; - that.query[that.viewType].type = selectedItem.type; - return { - 'opened': true, - 'selected': true - } - } - } else { - if (that.guid == objGuid) { - that.query[that.viewType].isNodeNotFoundAtLoad = false; - that.glossary.selectedItem = node - that.query[that.viewType].model = node.model; - that.query[that.viewType].type = node.type; - return { - 'opened': true, - 'selected': true - } - } - } - } - return this.glossaryCollection.fullCollection.map(function(model, i) { - var obj = model.toJSON(), - parent = { - "text": _.escape(obj.name), - "icon": "fa fa-folder-o", - "guid": obj.guid, - "id": obj.guid, - "model": obj, - "type": obj.typeName ? obj.typeName : "Glossary", - "gType": "glossary", - "children": [] - } - parent.state = getSelectedState({ - index: i, - node: parent, - objGuid: obj.guid - }); - if (type == "category" && obj.categories) { - var isSelected = false, - parentGuid = obj.guid, - parentCategoryGuid = null, - categoryList = [], - catrgoryRelation = []; - _.each(obj.categories, function(category) { - if (that.options.value) { - isSelected = that.options.value.guid ? that.options.value.guid == category.categoryGuid : false; - } - - var typeName = category.typeName || "GlossaryCategory", - guid = category.categoryGuid, - categoryObj = { - id: guid, - guid: guid, - text: _.escape(category.displayText), - type: typeName, - gType: "category", - glossaryId: obj.guid, - glossaryName: obj.name, - children: [], - model: category, - icon: "fa fa-files-o" - }; - categoryObj.state = getSelectedState({ - index: i, - node: categoryObj, - objGuid: guid - }) - if (category.parentCategoryGuid) { - catrgoryRelation.push({ parent: category.parentCategoryGuid, child: guid }) - } - categoryList.push(categoryObj); - }); - _.each(categoryList, function(category) { - var getRelation = _.find(catrgoryRelation, function(catrgoryObj) { - if (catrgoryObj.child == category.guid) return catrgoryObj; - }) - if (getRelation) { - _.map(categoryList, function(catrgoryObj) { - if (catrgoryObj.guid == getRelation.parent) { - catrgoryObj["children"].push(category); - }; - }) - } else { - parent.children.push(category) - } - }) - - } - if (type == "term" && obj.terms) { - _.each(obj.terms, function(term) { - if (associatedTerms) { - var associatedTermFound = _.find(associatedTerms, function(obj, index) { - if ((obj.termGuid ? obj.termGuid : obj.guid) == term.termGuid) { - return obj; - } - }); - if (associatedTermFound) { - return; - } - } - - var typeName = term.typeName || "GlossaryTerm", - guid = term.termGuid, - termObj = { - "text": _.escape(term.displayText), - "type": typeName, - "gType": "term", - "guid": guid, - "id": guid, - "parent": obj, - "glossaryName": obj.name, - "glossaryId": obj.guid, - "model": term, - "icon": "fa fa-file-o" - } - termObj.state = getSelectedState({ - index: i, - node: termObj, - objGuid: guid - }) - parent.children.push(termObj); - - }); - } - return parent; - }); - }, - manualRender: function(options) { - _.extend(this, _.omit(options, 'isTrigger')); - if (this.value && this.value.viewType) { - this.viewType = this.value.viewType; - } - if (this.guid && this.value && ((this.value.fromView && this.value.fromView) || (this.value.updateView))) { - var $tree = this.ui[this.viewType == "term" ? "termTree" : "categoryTree"], - node = $tree.jstree(true).get_node(this.guid); - if (node) { - $tree.jstree('activate_node', this.guid, { skipTrigger: true }); - delete this.value.fromView; - delete this.value.updateView; - this.glossary.selectedItem = node.original; - this.query[this.viewType] = _.extend({}, _.pick(this.glossary.selectedItem, 'model', 'guid', 'gType', 'type'), { "viewType": this.viewType }); - Utils.setUrl({ - url: '#!/glossary/' + this.guid, - urlParams: this.value, - mergeBrowserUrl: false, - trigger: false, - updateTabState: true - }); - this.glossaryCollection.trigger("update:details", { isGlossaryUpdate: this.value.gType == "glossary" }); - } - } else { - this.setValues(); - } - if (options.isTrigger) { - this.triggerUrl(); - } - }, - getDisableNodes: function() { - var disableNodesSelection = []; - if (this.options && this.options.isAssignAttributeRelationView) { - var disableTerms = (this.options.termData && this.options.selectedTermAttribute) ? this.options.termData[this.options.selectedTermAttribute] : null; - disableNodesSelection = _.map(disableTerms, function(obj) { - return obj.termGuid; - }); - disableNodesSelection.push(this.options.termData.guid); - } - return disableNodesSelection; - }, - generateTree: function() { - var $termTree = this.ui.termTree, - $categoryTree = this.ui.categoryTree, - that = this, - this_guid = that.guid, - getTreeConfig = function(options) { - return { - "plugins": ["search", "themes", "core", "wholerow", "sort", "conditionalselect"], - "conditionalselect": function(node) { - var obj = node && node.original && node.original.type; - if (!obj) { - return; - } - if (that.isAssignView) { - var isDisableNode = false; - if (that.disableNodesList) { - isDisableNode = (that.disableNodesList.indexOf(node.original.guid) > -1) ? true : false; - } - return (obj != "Glossary" && !isDisableNode) ? true : false; - } else { - return obj != "NoAction" ? true : false; - } - }, - "search": { - "show_only_matches": true - }, - "core": { - "data": function(node, cb) { - if (node.id === "#") { - cb(that.generateData(options)); - } else { - that.getCategory({ "node": node.original, "callback": cb }); - } - }, - "themes": { - "name": that.isAssignView ? "default" : "default-dark", - "dots": true - }, - } - } - }, - treeLoaded = function(options) { - if (that.query[options.type].isNodeNotFoundAtLoad == true) { - var id = that.glossary.selectedItem.guid; - if (id) { - options.$el.jstree('activate_node', id); - } - } - that.changeLoaderState(false); - }, - createAction = function(options) { - var $el = options.el, - type = options.type, - popoverClassName = type == "term" ? "termPopover" : "categoryPopover"; - if (!that.isAssignView) { - var wholerowEl = $el.find("li[role='treeitem'] > .jstree-wholerow:not(:has(>div.tools))") - wholerowEl.append('
        '); - - if (type == "term") { - that.createTermAction(); - } else if (type == "category") { - that.createCategoryAction(); - } - } - }, - initializeTree = function(options) { - var $el = options.el, - type = options.type; - - $el.jstree(getTreeConfig({ - type: type - })).on("load_node.jstree", function(e, data) { - createAction(_.extend({}, options, data)); - }).on("open_node.jstree", function(e, data) { - createAction(_.extend({}, options, data)); - }) - .on("select_node.jstree", function(e, data) { - if (that.isAssignView) { - that.glossary.selectedItem = data.node.original; - that.glossaryCollection.trigger("node_selected"); - } else { - var popoverClassName = (type == "term" ? '.termPopover' : '.categoryPopover'), - currentClickedPopoverEl = ""; - if (data.event) { - if ($(data.event.currentTarget).parent().hasClass('jstree-leaf')) { - currentClickedPopoverEl = $(data.event.currentTarget).parent().find(popoverClassName); - } else { - currentClickedPopoverEl = $(data.event.currentTarget).parent().find(">div " + popoverClassName); - } - $(popoverClassName).not(currentClickedPopoverEl).popover('hide'); - } - if (that.query[type].isNodeNotFoundAtLoad == true) { - that.query[type].isNodeNotFoundAtLoad = false; - } else if (type == that.viewType) { - if (data && data.event && data.event.skipTrigger) { - return; - } else if (that.glossary.selectedItem.guid !== data.node.original.guid) { - that.glossary.selectedItem = data.node.original; - that.triggerUrl(); - } - } - } - }).on("search.jstree", function(e, data) { - createAction(_.extend({}, options, data)); - }).on("clear_search.jstree", function(e, data) { - createAction(_.extend({}, options, data)); - }).bind('loaded.jstree', function(e, data) { - treeLoaded({ "$el": $el, "type": type }); - }); - }, - - initializeTermTree = function() { - if ($termTree.data('jstree')) { - $('.termPopover').popover('destroy'); - $termTree.jstree(true).refresh(); - } else { - initializeTree({ - el: $termTree, - type: "term" - }); - } - }, - initializeCategoryTree = function() { - if ($categoryTree.data('jstree')) { - $('.categoryPopover').popover('destroy'); - $categoryTree.jstree(true).refresh(); - } else { - initializeTree({ - el: $categoryTree, - type: "category" - }) - } - } - if (this.isAssignView) { - if (this.isAssignTermView || this.isAssignEntityView || this.isAssignAttributeRelationView) { - initializeTermTree(); - } else if (this.isAssignCategoryView) { - initializeCategoryTree(); - } - } else { - initializeTermTree(); - initializeCategoryTree(); - } - - - if (Utils.getUrlState.isGlossaryTab()) { - this.triggerUrl(); - } - this.glossaryCollection.trigger("render:done"); - }, - createTermAction: function() { - var that = this; - Utils.generatePopover({ - el: this.$('.termPopover'), - contentClass: 'termPopoverOptions', - popoverOptions: { - content: function() { - var node = that.query[that.viewType], - liString = ""; - if (node.type == "Glossary") { - liString = "
      • Create Term
      • " + - "
      • Delete Glossary
      • " - } else { - liString = "
      • Delete Term
      • " - } - return "
          " + liString + "
        "; - } - } - }); - }, - createCategoryAction: function() { - var that = this; - Utils.generatePopover({ - el: this.$('.categoryPopover'), - contentClass: 'categoryPopoverOptions', - popoverOptions: { - content: function() { - var node = that.query[that.viewType], - liString = ""; - if (node.type == "Glossary") { - liString = "
      • Create Category
      • " + - "
      • Delete Glossary
      • " - } else { - liString = "
      • Create Sub-Category
      • " + - "
      • Delete Category
      • " - } - return "
          " + liString + "
        "; - } - } - }); - }, - createSubNode: function(opt) { - var that = this, - type = this.glossary.selectedItem.type; - if ((type == "Glossary" || type == "GlossaryCategory") && this.viewType == "category") { - CommonViewFunction.createEditGlossaryCategoryTerm({ - "isCategoryView": true, - "collection": that.glossaryCollection, - "callback": function(updateCollection) { - var updatedObj = { - categoryGuid: updateCollection.guid, - displayText: updateCollection.name, - relationGuid: updateCollection.anchor ? updateCollection.anchor.relationGuid : null - }, - glossary = that.glossaryCollection.fullCollection.findWhere({ guid: updateCollection.anchor.glossaryGuid }); - if (updateCollection.parentCategory) { - updatedObj["parentCategoryGuid"] = updateCollection.parentCategory.categoryGuid; - } - if (glossary) { - var glossaryAttributes = glossary.attributes || null; - if (glossaryAttributes) { - if (glossaryAttributes.categories) { - glossaryAttributes['categories'].push(updatedObj); - } else { - glossaryAttributes['categories'] = [updatedObj]; - } - } - } - that.ui.categoryTree.jstree(true).refresh(); - }, - "node": this.glossary.selectedItem - }) - } else { - CommonViewFunction.createEditGlossaryCategoryTerm({ - "isTermView": true, - "callback": function() { - that.getGlossary(); - }, - "collection": that.glossaryCollection, - "node": this.glossary.selectedItem - }) - } - }, - deleteNode: function(opt) { - var that = this, - messageType = "", - type = this.glossary.selectedItem.type, - guid = this.glossary.selectedItem.guid, - gId = this.glossary.selectedItem.glossaryId, - options = { - success: function(rModel, response) { - if (!gId) { - gId = guid; - } - var glossary = that.glossaryCollection.fullCollection.get(gId); - if (that.value) { - if (that.value.gType == "term") { - glossary.set('terms', _.reject(glossary.get('terms'), function(obj) { - return obj.termGuid == guid; - }), { silent: true }); - } else if (that.value.gType == "category") { - glossary.set('categories', _.reject(glossary.get('categories'), function(obj) { - return obj.categoryGuid == guid || obj.parentCategoryGuid == guid; - }), { silent: true }); - } else { - glossary = that.glossaryCollection.fullCollection.first(); - if (glossary) { - gId = glossary.get('guid'); - } else { - gId = null - } - } - } - Utils.notifySuccess({ - content: messageType + Messages.getAbbreviationMsg(false, 'deleteSuccessMessage') - }); - var url = gId ? '#!/glossary/' + gId : '#!/glossary'; - if (gId == null) { - that.glossary.selectedItem = {}; - that.value = null; - that.query = { - term: {}, - category: {} - }; - that.ui.categoryTree.jstree(true).refresh(); - that.ui.termTree.jstree(true).refresh(); - } - Utils.setUrl({ - url: url, - mergeBrowserUrl: false, - trigger: true, - urlParams: gId ? _.extend({}, that.value, { - gType: 'glossary', - updateView: true, - gId: null - }) : null, - updateTabState: true - }); - }, - complete: function() { - that.notificationModal.hideButtonLoader(); - that.notificationModal.remove(); - } - }, - notifyObj = { - modal: true, - ok: function(obj) { - that.notificationModal = obj; - obj.showButtonLoader(); - if (type == "Glossary") { - that.glossaryCollection.fullCollection.get(guid).destroy(options, { silent: true, reset: false }); - } else if (type == "GlossaryCategory") { - new that.glossaryCollection.model().deleteCategory(guid, options); - } else if (type == "GlossaryTerm") { - new that.glossaryCollection.model().deleteTerm(guid, options); - } - }, - okCloses: false, - cancel: function(argument) {} - }; - if (type == "Glossary") { - messageType = "Glossary"; - } else if (type == "GlossaryCategory") { - messageType = "Category" - } else if (type == "GlossaryTerm") { - messageType = "Term"; - } - notifyObj['text'] = "Are you sure you want to delete the " + messageType;; - Utils.notifyConfirm(notifyObj); - }, - triggerUrl: function(options) { - if (this.isAssignView) { - return; - } - var selectedItem = this.glossary.selectedItem; - if (this.glossaryCollection.length && (_.isEmpty(selectedItem) || this.query[this.viewType].isNodeNotFoundAtLoad)) { - var model = selectedItem.model - if (model && !_.isUndefined(model.parentCategory || model.parentCategoryGuid)) { - selectedItem = { "model": this.glossaryCollection.first().toJSON() }; - selectedItem.guid = selectedItem.model.guid; - selectedItem.type = "Glossary"; - selectedItem.gType = "glossary"; - selectedItem.text = model.name; - this.glossary.selectedItem = selectedItem; - this.query[this.viewType].model = selectedItem.model; - this.query[this.viewType].gType = "glossary"; - this.query[this.viewType].type = "Glossary"; - delete this.query[this.viewType].gId; - } - } - if (_.isEmpty(selectedItem)) { - return; - } - if (Utils.getUrlState.isGlossaryTab() || Utils.getUrlState.isDetailPage()) { - var obj = {}; - if (selectedItem.glossaryId) { - obj["gId"] = selectedItem.glossaryId; - } else if (selectedItem.type == "Glossary") { - obj["gId"] = selectedItem.guid; - } - this.query[this.viewType] = _.extend(obj, _.omit(this.value, 'gId'), _.pick(this.glossary.selectedItem, 'model', 'type', 'gType', 'guid'), { "viewType": this.viewType, "isNodeNotFoundAtLoad": this.query[this.viewType].isNodeNotFoundAtLoad }); - //Below condition if for adding term Param to the URL for selection Purpose while switching from Old UI to New UI on term selection. - if (selectedItem.type === "GlossaryTerm") { - obj['term'] = selectedItem.text + '@' + selectedItem.glossaryName; - } else { - delete obj.term; - } - Utils.setUrl({ - url: '#!/glossary/' + obj.guid, - mergeBrowserUrl: false, - trigger: true, - urlParams: _.omit(obj, 'model', 'type', 'isNodeNotFoundAtLoad'), //Guid has been removed from here because we need in the URL for Highlighting issue. - updateTabState: true - }); - } - }, - onClickImportGlossary: function() { - var that = this; - require([ - 'views/import/ImportLayoutView' - ], function(ImportLayoutView) { - var view = new ImportLayoutView({ - callback: function() { - that.getGlossary(); - }, - isGlossary: true - }); - }); - } - }); - return GlossaryLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/glossary/TermRelationAttributeLayoutView.js b/dashboardv2/public/js/views/glossary/TermRelationAttributeLayoutView.js deleted file mode 100644 index ded1ab9434e..00000000000 --- a/dashboardv2/public/js/views/glossary/TermRelationAttributeLayoutView.js +++ /dev/null @@ -1,249 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/glossary/TermRelationAttributeLayoutView_tmpl', - 'hbs!tmpl/glossary/TermRelationAttributeTable_tmpl', - 'utils/Enums', - 'utils/Utils', - 'utils/UrlLinks', - 'modules/Modal' -], function(require, Backbone, TermRelationAttributeLayoutViewTmpl, TermRelationAttributeTableTmpl, Enums, Utils, UrlLinks, Modal) { - - var TermRelationAttributeTable = Backbone.Marionette.LayoutView.extend({ - _viewName: 'TermRelationAttributeTable', - - template: TermRelationAttributeTableTmpl, - - templateHelpers: function() { - return { - attributeValue: this.data[this.selectedTermAttribute], - selectedTermAttribute: this.selectedTermAttribute, - editMode: this.editMode, - attributes: Enums.termRelationAttributeList[this.selectedTermAttribute] - } - }, - /** ui selector cache */ - ui: { - "deleteAttribute": '[data-id="deleteAttribute"]', - "attributeUpdate": '[data-id="attributeUpdate"]' - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.deleteAttribute] = 'onModalDeleteAttribute'; - events["change " + this.ui.attributeUpdate] = 'onAttributeUpdate'; - return events; - }, - /** - * intialize a new TermRelationAttributeLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'glossaryCollection', 'data', 'callback', 'selectedTermAttribute', 'onDeleteAttribute', 'editMode')); - var that = this; - this.updateObj = $.extend(true, {}, this.data); - this.modal = new Modal({ - "title": ((this.editMode ? "Edit attributes" : "Attributes") + " of " + this.selectedTermAttribute), - "content": this, - "okText": (this.editMode ? "Update" : "ok"), - "allowCancel": (this.editMode ? true : false), - "okCloses": true, - "width": "80%", - }); - this.modal.open(); - this.modal.on('closeModal', function() { - that.modal.trigger('cancel'); - }); - this.modal.on('ok', function() { - if (that.editMode) { - that.updateAttributes(); - } - }); - this.bindEvents(); - }, - bindEvents: function() { - this.listenTo(this.glossaryCollection, "data:updated", function(data) { - this.data = data; - this.render() - }, this); - }, - onRender: function() {}, - onModalDeleteAttribute: function(e) { - var that = this; - this.onDeleteAttribute(e); - }, - onAttributeUpdate: function(e) { - var $el = $(e.currentTarget), - termGuid = $el.data('termguid'), - name = $el.data('name'); - _.find(this.updateObj[this.selectedTermAttribute], function(obj) { - if (obj.termGuid == termGuid) { - obj[name] = $el.val(); - } - }); - }, - updateAttributes: function() { - var that = this, - model = new this.glossaryCollection.model(), - ajaxOptions = { - success: function(rModel, response) { - Utils.notifySuccess({ - content: "Attributes updated successfully" - }); - if (that.callback) { - that.callback(); - } - } - }; - model.createEditTerm(_.extend(ajaxOptions, { data: JSON.stringify(this.updateObj) }, { guid: this.updateObj.guid })); - } - }); - - var TermRelationAttributeLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends TermRelationAttributeLayoutView */ - { - _viewName: 'TermRelationAttributeLayoutView', - - template: TermRelationAttributeLayoutViewTmpl, - - templateHelpers: function() { - return { - attributeList: Enums.termRelationAttributeList - }; - }, - - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - "showAttribute": '[data-id="showAttribute"]', - "addTermRelation": '[data-id="addTermRelation"]', - "termAttributeTable": '[data-id="termAttributeTable"]', - "deleteAttribute": '[data-id="deleteAttribute"]', - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.addTermRelation] = 'onAddTermRelation'; - events["click " + this.ui.deleteAttribute] = 'onDeleteAttribute'; - events["click " + this.ui.showAttribute] = 'onShowAttribute'; - return events; - }, - /** - * intialize a new TermRelationAttributeLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'glossaryCollection', 'data', 'fetchCollection')); - }, - bindEvents: function() {}, - onRender: function() { - this.renderTermAttributeTable(); - }, - onShowAttribute: function(e) { - var that = this, - attributename = $(e.currentTarget).data('attributename'), - view = new TermRelationAttributeTable({ - "data": that.data, - "editMode": ($(e.currentTarget).data('mode') == "edit"), - "selectedTermAttribute": attributename, - "callback": function() { - if (that.fetchCollection) { - that.fetchCollection(); - } - }, - "onDeleteAttribute": that.onDeleteAttribute.bind(that), - "glossaryCollection": that.glossaryCollection - }); - }, - onAddTermRelation: function(e) { - var that = this, - attributename = $(e.currentTarget).data('attributename'); - require(['views/glossary/AssignTermLayoutView'], function(AssignTermLayoutView) { - var view = new AssignTermLayoutView({ - "isAttributeRelationView": true, - "termData": that.data, - "selectedTermAttribute": attributename, - "callback": function() { - if (that.fetchCollection) { - that.fetchCollection(); - } - }, - "glossaryCollection": that.glossaryCollection - }); - }); - }, - onDeleteAttribute: function(e) { - e.stopPropagation(); - var that = this, - notifyObj = { - modal: true, - text: "Are you sure you want to remove term association", - ok: function(argument) { - var model = new that.glossaryCollection.model(), - selectedGuid = $(e.currentTarget).data('termguid'), - attributename = $(e.currentTarget).data('attributename'), - ajaxOptions = { - success: function(rModel, response) { - Utils.notifySuccess({ - content: "Association removed successfully " - }); - if (that.fetchCollection) { - that.fetchCollection(); - } - } - }, - data = _.clone(that.data); - data[attributename] = _.reject(data[attributename], function(obj) { - return obj.termGuid == selectedGuid; - }); - model.removeTermFromAttributes(_.extend(ajaxOptions, { data: JSON.stringify(data) }, { guid: that.data.guid })); - - }, - cancel: function(argument) {} - }; - Utils.notifyConfirm(notifyObj); - }, - renderTermAttributeTable: function(e, options) { - var that = this; - this.ui.termAttributeTable.html(TermRelationAttributeTableTmpl({ - data: this.data, - attributes: Enums.termRelationAttributeList, - relationTypeTable: true, - getTerms: function(key) { - var terms = _.map(that.data[key], function(obj) { - var name = _.escape(obj.displayText); - return '' + name + ''; - }).join(""), - attributeButtons = ""; - if (terms.length) { - attributeButtons = '
        ' + - '' + - '' + - '
        ' - } - return '' + terms + '' + attributeButtons + ''; - } - })); - } - }); - return TermRelationAttributeLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/graph/LineageLayoutView.js b/dashboardv2/public/js/views/graph/LineageLayoutView.js deleted file mode 100644 index e989c4719bd..00000000000 --- a/dashboardv2/public/js/views/graph/LineageLayoutView.js +++ /dev/null @@ -1,487 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/graph/LineageLayoutView_tmpl', - 'collection/VLineageList', - 'models/VEntity', - 'utils/Utils', - 'LineageHelper', - 'd3', - 'dagreD3', - 'd3-tip', - 'utils/Enums', - 'utils/UrlLinks', - 'utils/Globals', - 'utils/CommonViewFunction', - 'platform', - 'jquery-ui' -], function(require, Backbone, LineageLayoutViewtmpl, VLineageList, VEntity, Utils, LineageHelper, d3, dagreD3, d3Tip, Enums, UrlLinks, Globals, CommonViewFunction, platform) { - 'use strict'; - - var LineageLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends LineageLayoutView */ - { - _viewName: 'LineageLayoutView', - - template: LineageLayoutViewtmpl, - className: "resizeGraph", - - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - graph: ".graph", - checkHideProcess: "[data-id='checkHideProcess']", - checkDeletedEntity: "[data-id='checkDeletedEntity']", - selectDepth: 'select[data-id="selectDepth"]', - filterToggler: '[data-id="filter-toggler"]', - settingToggler: '[data-id="setting-toggler"]', - searchToggler: '[data-id="search-toggler"]', - boxClose: '[data-id="box-close"]', - lineageFullscreenToggler: '[data-id="fullScreen-toggler"]', - filterBox: '.filter-box', - searchBox: '.search-box', - settingBox: '.setting-box', - lineageTypeSearch: '[data-id="typeSearch"]', - searchNode: '[data-id="searchNode"]', - nodeDetailTable: '[data-id="nodeDetailTable"]', - showOnlyHoverPath: '[data-id="showOnlyHoverPath"]', - showTooltip: '[data-id="showTooltip"]', - saveSvg: '[data-id="saveSvg"]', - resetLineage: '[data-id="resetLineage"]', - onZoomIn: '[data-id="zoom-in"]', - labelFullName: '[data-id="labelFullName"]', - onZoomOut: '[data-id="zoom-out"]' - }, - templateHelpers: function() { - return { - width: "100%", - height: "100%" - }; - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.checkHideProcess] = 'onCheckUnwantedEntity'; - events["click " + this.ui.checkDeletedEntity] = 'onCheckUnwantedEntity'; - events['change ' + this.ui.selectDepth] = 'onSelectDepthChange'; - events["click " + this.ui.filterToggler] = 'onClickFilterToggler'; - events["click " + this.ui.boxClose] = 'toggleBoxPanel'; - events["click " + this.ui.settingToggler] = 'onClickSettingToggler'; - events["click " + this.ui.lineageFullscreenToggler] = 'onClickLineageFullscreenToggler'; - events["click " + this.ui.searchToggler] = 'onClickSearchToggler'; - events["click " + this.ui.saveSvg] = 'onClickSaveSvg'; - events["click " + this.ui.resetLineage] = 'onClickResetLineage'; - events["click " + this.ui.onZoomIn] = 'onClickZoomIn'; - events["click " + this.ui.onZoomOut] = 'onClickZoomOut'; - events["change " + this.ui.labelFullName] = "onClickLabelFullName"; - return events; - }, - - /** - * intialize a new LineageLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'processCheck', 'guid', 'entity', 'entityName', 'entityDefCollection', 'actionCallBack', 'fetchCollection', 'attributeDefs')); - this.collection = new VLineageList(); - this.typeMap = {}; - this.apiGuid = {}; - this.edgeCall; - this.filterObj = { - isProcessHideCheck: false, - isDeletedEntityHideCheck: false, - depthCount: '' - }; - this.searchNodeObj = { - selectedNode: '' - } - this.labelFullText = false; - }, - onRender: function() { - var that = this; - this.ui.searchToggler.prop("disabled", true); - this.$graphButtonsEl = this.$(".graph-button-group button, select[data-id='selectDepth']") - this.fetchGraphData(); - if (this.layoutRendered) { - this.layoutRendered(); - } - if (this.processCheck) { - this.hideCheckForProcess(); - } - //this.initializeGraph(); - this.ui.selectDepth.select2({ - data: _.sortBy([3, 6, 9, 12, 15, 18, 21]), - tags: true, - dropdownCssClass: "number-input", - multiple: false - }); - }, - onShow: function() { - this.$('.fontLoader').show(); - // this.$el.resizable({ - // handles: ' s', - // minHeight: 375, - // stop: function(event, ui) { - // ui.element.height(($(this).height())); - // }, - // }); - }, - onClickLineageFullscreenToggler: function(e) { - var icon = $(e.currentTarget).find('i'), - panel = $(e.target).parents('.tab-pane').first(); - icon.toggleClass('fa-expand fa-compress'); - if (icon.hasClass('fa-expand')) { - icon.parent('button').attr("data-original-title", "Full Screen"); - } else { - icon.parent('button').attr("data-original-title", "Default View"); - } - panel.toggleClass('fullscreen-mode'); - var node = this.$("svg").parent()[0].getBoundingClientRect(); - this.LineageHelperRef.updateOptions({ - width: node.width, - height: node.height - }); - this.calculateLineageDetailPanelHeight(); - }, - onCheckUnwantedEntity: function(e) { - var that = this; - //this.initializeGraph(); - if ($(e.target).data("id") === "checkHideProcess") { - this.filterObj.isProcessHideCheck = e.target.checked; - } else { - this.filterObj.isDeletedEntityHideCheck = e.target.checked; - } - this.LineageHelperRef.refresh(); - }, - toggleBoxPanel: function(options) { - var el = options && options.el, - nodeDetailToggler = options && options.nodeDetailToggler, - currentTarget = options.currentTarget; - this.$el.find('.show-box-panel').removeClass('show-box-panel'); - if (el && el.addClass) { - el.addClass('show-box-panel'); - } - this.$('circle.node-detail-highlight').removeClass("node-detail-highlight"); - }, - toggleLoader: function(element) { - if ((element).hasClass('fa-camera')) { - (element).removeClass('fa-camera').addClass("fa-spin-custom fa-refresh"); - } else { - (element).removeClass("fa-spin-custom fa-refresh").addClass('fa-camera'); - } - }, - toggleDisableState: function(options) { - var el = options.el, - disabled = options.disabled; - if (el && el.prop) { - if (disabled) { - el.prop("disabled", disabled); - } else { - el.prop("disabled", !el.prop("disabled")); - } - } - }, - onClickNodeToggler: function(options) { - this.toggleBoxPanel({ el: this.$('.lineage-node-detail'), nodeDetailToggler: true }); - }, - onClickFilterToggler: function() { - this.toggleBoxPanel({ el: this.ui.filterBox }); - }, - onClickSettingToggler: function() { - this.toggleBoxPanel({ el: this.ui.settingBox }); - }, - onClickSearchToggler: function() { - this.toggleBoxPanel({ el: this.ui.searchBox }); - }, - onSelectDepthChange: function(e, options) { - //this.initializeGraph(); - this.filterObj.depthCount = e.currentTarget.value; - //legends property is added in queryParam to stop the legend getting added in lineage graph whenever dept is changed. - this.fetchGraphData({ queryParam: { 'depth': this.filterObj.depthCount }, 'legends': false }); - }, - onClickResetLineage: function() { - this.LineageHelperRef.refresh(); - this.searchNodeObj.selectedNode = ""; - this.ui.lineageTypeSearch.data({ refresh: true }).val("").trigger("change"); - this.ui.labelFullName.prop("checked", false); - this.labelFullText = false; - }, - onClickSaveSvg: function(e, a) { - var that = this; - if (that.lineageRelationshipLength >= 1000) { - Utils.notifyInfo({ - content: "There was an error in downloading lineage: Lineage exceeds display parameters!" - }); - return; - } - this.LineageHelperRef.exportLineage(); - }, - onClickZoomIn: function() { - this.LineageHelperRef.zoomIn(); - }, - onClickZoomOut: function() { - this.LineageHelperRef.zoomOut(); - }, - onClickLabelFullName: function() { - this.labelFullText = !this.labelFullText; - this.LineageHelperRef.displayFullName({ bLabelFullText: this.labelFullText }); - }, - fetchGraphData: function(options) { - var that = this, - queryParam = options && options.queryParam || {}; - this.$('.fontLoader').show(); - this.$('svg>g').hide(); - this.toggleDisableState({ - "el": that.$graphButtonsEl, - disabled: true - }); - //Create data for displaying just entityNode when no relationships are present. - var classificationNamesArray = []; - if (this.entity.classifications) { - this.entity.classifications.forEach(function(item) { - classificationNamesArray.push(item.typeName); - }); - } - this.currentEntityData = { - classificationNames: classificationNamesArray, - displayText: that.entity.attributes.name, - labels: [], - meaningNames: [], - meanings: [] - } - _.extend(this.currentEntityData, _.pick(this.entity, 'attributes', 'guid', 'isIncomplete', 'status', 'typeName')); - //End - this.collection.getLineage(this.guid, { - queryParam: queryParam, - success: function(data) { - if (that.isDestroyed) { - return; - } - data["legends"] = options ? options.legends : true; - // show only main part of lineage current entity is at bottom, so reverse is done - var relationsReverse = data.relations ? data.relations.reverse() : null, - lineageMaxRelationCount = 9000; - if (relationsReverse.length > lineageMaxRelationCount) { - data.relations = relationsReverse.splice(relationsReverse.length - lineageMaxRelationCount, relationsReverse.length - 1); - Utils.notifyInfo({ - content: "Lineage exceeds display parameters and hence only upto 9000 relationships from this lineage can be displayed" - }); - } - that.lineageRelationshipLength = data.relations.length; - if (_.isEmpty(data.relations)) { - if (_.isEmpty(data.guidEntityMap) || !data.guidEntityMap[data.baseEntityGuid]) { - data.guidEntityMap[data.baseEntityGuid] = that.currentEntityData; - } - } - that.createGraph(data); - that.renderLineageTypeSearch(data); - }, - cust_error: function(model, response) { - that.noLineage(); - }, - complete: function() { - that.$('.fontLoader').hide(); - that.$('svg>g').show(); - } - }) - }, - createGraph: function(data) { - var that = this; - $('.resizeGraph').css("height", this.$('.svg').height() + "px"); - - this.LineageHelperRef = new LineageHelper.default({ - entityDefCollection: this.entityDefCollection.fullCollection.toJSON(), - data: data, - el: this.$('.svg')[0], - legendsEl: this.$('.legends')[0], - legends: data.legends, - getFilterObj: function() { - return { - isProcessHideCheck: that.filterObj.isProcessHideCheck, - isDeletedEntityHideCheck: that.filterObj.isDeletedEntityHideCheck - } - }, - isShowHoverPath: function() { return that.ui.showOnlyHoverPath.prop('checked') }, - isShowTooltip: function() { return that.ui.showTooltip.prop('checked') }, - onPathClick: function(d) { - console.log("Path Clicked"); - if (d.pathRelationObj) { - var relationshipId = d.pathRelationObj.relationshipId; - require(['views/graph/PropagationPropertyModal'], function(PropagationPropertyModal) { - var view = new PropagationPropertyModal({ - edgeInfo: d.pathRelationObj, - relationshipId: relationshipId, - lineageData: data, - apiGuid: that.apiGuid, - detailPageFetchCollection: that.fetchCollection - }); - }); - } - }, - onNodeClick: function(d) { - that.onClickNodeToggler(); - that.updateRelationshipDetails({ guid: d.clickedData }); - that.calculateLineageDetailPanelHeight(); - }, - onLabelClick: function(d) { - var guid = d.clickedData; - if (that.guid == guid) { - Utils.notifyInfo({ - html: true, - content: "You are already on " + "" + that.entityName + " detail page." - }); - } else { - Utils.setUrl({ - url: '#!/detailPage/' + guid + '?tabActive=lineage', - mergeBrowserUrl: false, - trigger: true - }); - } - }, - beforeRender: function() { - that.$('.fontLoader').show(); - that.toggleDisableState({ - "el": that.$graphButtonsEl, - disabled: true - }); - }, - afterRender: function() { - // Remove Loader - that.$('.fontLoader').hide(); - if (data.relations.length) { - that.toggleDisableState({ - "el": that.$graphButtonsEl, - disabled: false - }); - } - } - }); - }, - noLineage: function() { - this.$('.fontLoader').hide(); - this.$('.depth-container').hide(); - this.$('svg').html('No lineage data found'); - if (this.actionCallBack) { - this.actionCallBack(); - } - }, - hideCheckForProcess: function() { - this.$('.hideProcessContainer').hide(); - }, - renderLineageTypeSearch: function(data) { - var that = this; - return new Promise(function(resolve, reject) { - try { - var typeStr = ''; - if (!_.isEmpty(data)) { - _.each(data.guidEntityMap, function(obj, index) { - var nodeData = that.LineageHelperRef.getNode(obj.guid); - if ((that.filterObj.isProcessHideCheck || that.filterObj.isDeletedEntityHideCheck) && nodeData && (nodeData.isProcess || nodeData.isDeleted)) { - return; - } - typeStr += ''; - }); - } - that.ui.lineageTypeSearch.html(typeStr); - that.initilizelineageTypeSearch(); - resolve(); - } catch (e) { - console.log(e); - reject(e); - } - }) - }, - initilizelineageTypeSearch: function() { - var that = this; - this.ui.lineageTypeSearch.select2({ - closeOnSelect: true, - placeholder: 'Select Node' - }).on('change.select2', function(e) { - e.stopPropagation(); - e.stopImmediatePropagation(); - if (!that.ui.lineageTypeSearch.data("refresh")) { - var selectedNode = $('[data-id="typeSearch"]').val(); - that.searchNodeObj.selectedNode = selectedNode; - that.LineageHelperRef.searchNode({ guid: selectedNode }); - } else { - that.ui.lineageTypeSearch.data("refresh", false); - } - }); - if (this.searchNodeObj.selectedNode) { - this.ui.lineageTypeSearch.val(this.searchNodeObj.selectedNode); - this.ui.lineageTypeSearch.trigger("change.select2"); - } - }, - updateRelationshipDetails: function(options) { - var that = this, - guid = options.guid, - initialData = that.LineageHelperRef.getNode(guid); - if (initialData === undefined) { - return; - } - var typeName = initialData.typeName || guid, - attributeDefs = initialData && initialData.entityDef ? initialData.entityDef.attributeDefs : null; - this.$("[data-id='typeName']").text(typeName); - this.entityModel = new VEntity({}); - var config = { - guid: 'guid', - typeName: 'typeName', - name: 'name', - qualifiedName: 'qualifiedName', - owner: 'owner', - createTime: 'createTime', - status: 'status', - classificationNames: 'classifications', - meanings: 'term' - }; - var data = {}; - _.each(config, function(valKey, key) { - var val = initialData[key]; - if (_.isUndefined(val) && initialData.attributes && initialData.attributes[key]) { - val = initialData.attributes[key]; - } - if (val) { - data[valKey] = val; - } - }); - this.ui.nodeDetailTable.html(CommonViewFunction.propertyTable({ - "scope": this, - "valueObject": data, - "attributeDefs": attributeDefs, - "sortBy": false - })); - }, - calculateLineageDetailPanelHeight: function() { - var $parentContainer = $('#tab-lineage .resizeGraph'), - $panel = $parentContainer.find('.fix-box'); - var $parentHeight = $parentContainer.find('.fix-box, tbody').removeAttr('style').height() - 48, // 48px is the Panels top from the parent container - $tBody = $panel.find('tbody'), - panelHeight = $tBody.height() + 100; - if ($parentHeight < panelHeight) { - panelHeight = $parentHeight; - } - $panel.css('height', panelHeight + 'px'); - $tBody.css('height', '100%'); - } - }); - return LineageLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/graph/ProfileBarChart.js b/dashboardv2/public/js/views/graph/ProfileBarChart.js deleted file mode 100644 index d6ab7a8bee3..00000000000 --- a/dashboardv2/public/js/views/graph/ProfileBarChart.js +++ /dev/null @@ -1,151 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(["require", "d3", "d3-tip"], function(require, d3, d3Tip) { - "use strict"; - var ProfileBarChart = { - render: function(options) { - var el = options.el, - type = options.data.key, - data = options.data.values, - formatValue = options.formatValue, - xAxisLabel = options.xAxisLabel, - yAxisLabel = options.yAxisLabel, - rotateXticks = options.rotateXticks, - onBarClick = options.onBarClick, - size = el.getBoundingClientRect(), - svg = d3.select(el), - margin = { top: 20, right: 30, bottom: 100, left: 80 }, - width = size.width - margin.left - margin.right, - height = size.height - margin.top - margin.bottom; - - // set the ranges - var x = d3.scaleBand().range([0, width]).padding(0.5); - - var y = d3.scaleLinear().range([height, 0]); - - var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); - - x.domain( - data.map(function(d) { - return d.value; - }) - ); - y.domain([ - 0, - d3.max(data, function(d) { - return d.count; - }) - ]); - - // gridlines in x axis function - function make_x_gridlines() { - return d3.axisBottom(x).ticks(5); - } - - // gridlines in y axis function - function make_y_gridlines() { - return d3.axisLeft(y).ticks(5); - } - - // add the X gridlines - g.append("g") - .attr("class", "grid") - .attr("transform", "translate(0," + height + ")") - .call(make_x_gridlines().tickSize(-height).tickFormat("")); - - // add the Y gridlines - g.append("g").attr("class", "grid").call(make_y_gridlines().tickSize(-width).tickFormat("")); - - // add the x Axis - var xAxis = g - .append("g") - .attr("transform", "translate(0," + height + ")") - .call(d3.axisBottom(x)); - - if (rotateXticks) { - xAxis.selectAll("text").style("text-anchor", "end").attr("dx", "-.8em").attr("dy", ".15em").attr("transform", "rotate(-45)"); - } - - // add the y Axis - g.append("g").call(d3.axisLeft(y).ticks(3, "s")); - - g.append("text") - .attr("transform", "translate(" + width / 2 + " ," + (margin.top - 25) + ")") - .attr("class", "axislabel") - .text(xAxisLabel); - - // text label for the y axis - g.append("text") - .attr("transform", "rotate(-90)") - .attr("y", 0 - margin.left) - .attr("x", 0 - height / 2) - .attr("dy", "1em") - .attr("class", "axislabel") - .text(yAxisLabel); - - var tooltip = d3Tip() - .attr("class", "d3-tip") - .offset([10, 0]) - .html(function(d) { - console.log(d) - return '
        ' + d.value + '
        ' + type + '' + d.count + '
        '; - }); - - // append the rectangles for the bar chart - g.selectAll(".bar") - .data(data) - .enter() - .append("rect") - .attr("class", "profile-bar") - .attr("x", function(d) { - return x(d.value); - }) - .attr("width", x.bandwidth()) - .attr("y", function(d) { return height; }) - .attr("height", 0) - .on("click", function(e) { - tooltip.hide(); - if (onBarClick) { - onBarClick(e); - } - }) - .on("mouseover", function(d) { - tooltip.show(d, this); - }) - .on("mouseout", function(d) { - tooltip.hide(); - }) - .transition() - .duration(450) - .delay(function(d, i) { - return i * 50; - }) - .attr("y", function(d) { - return y(d.count); - }) - .attr("height", function(d) { - return height - y(d.count); - }); - - g.call(tooltip); - - } - }; - return ProfileBarChart; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/graph/PropagationPropertyModal.js b/dashboardv2/public/js/views/graph/PropagationPropertyModal.js deleted file mode 100644 index d9ef604b61d..00000000000 --- a/dashboardv2/public/js/views/graph/PropagationPropertyModal.js +++ /dev/null @@ -1,344 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'hbs!tmpl/graph/PropagationPropertyModalView_tmpl', - 'models/VRelationship', - 'models/VEntity', - 'modules/Modal', - 'utils/Utils', - 'utils/UrlLinks', - 'utils/Messages' -], function(require, PropagationPropertyModalViewTmpl, VRelationship, VEntity, Modal, Utils, UrlLinks, Messages) { - 'use strict'; - - var PropogationPropertyModal = Backbone.Marionette.CompositeView.extend({ - template: PropagationPropertyModalViewTmpl, - templateHelpers: function() {}, - regions: {}, - ui: { - propagationOptions: '[data-id="propagationOptions"]', - edgeDetailName: '[data-id="edgeDetailName"]', - propagationState: "[data-id='propagationState']", - entityClick: "[data-id='entityClick']", - editPropagationType: 'input[name="editPropagationType"]', - PropagatedClassificationTable: "[data-id='PropagatedClassificationTable']" - - }, - events: function() { - var events = {}, - that = this; - events["change " + this.ui.propagationOptions] = function() { - this.modalEdited = true; - this.modal.$el.find('button.ok').attr("disabled", false); - }; - events["click " + this.ui.editPropagationType] = function(e) { - if (this.modalEdited === true) { - e.preventDefault(); - that.notifyModal(); - } - }; - events["change " + this.ui.editPropagationType] = function(e) { - if (e.target.checked) { - this.showPropagatedClassificationTable(); - this.viewType = "table"; - } else { - this.showEditPropagation(); - this.viewType = "flow"; - } - }; - events["click " + this.ui.entityClick] = function(e) { - var that = this, - url = "", - notifyObj = { - modal: true, - text: "Are you sure you want to navigate away from this page ?", - ok: function(argument) { - that.modal.trigger('cancel'); - Utils.setUrl({ - url: url, - mergeBrowserUrl: false, - trigger: true - }); - - }, - cancel: function(argument) {} - }, - $el = $(e.currentTarget), - guid = $el.parents('tr').data('entityguid'); - if ($el.hasClass('entityName')) { - url = '#!/detailPage/' + guid + '?tabActive=lineage'; - } else { - url = '#!/tag/tagAttribute/' + $el.data('name'); - } - Utils.notifyConfirm(notifyObj); - }; - events["change " + this.ui.propagationState] = function(e) { - this.modalEdited = true; - this.modal.$el.find('button.ok').attr("disabled", false); - var $el = $(e.currentTarget).parents('tr'), - entityguid = $el.data("entityguid"), - classificationName = $el.find('[data-name]').data('name'); - if (e.target.checked) { - this.propagatedClassifications = _.reject(this.propagatedClassifications, function(val, key) { - if (val.entityGuid == entityguid && classificationName == val.typeName) { - that.blockedPropagatedClassifications.push(val); - return true; - } - }); - } else { - this.blockedPropagatedClassifications = _.reject(this.blockedPropagatedClassifications, function(val, key) { - if (val.entityGuid == entityguid && classificationName == val.typeName) { - that.propagatedClassifications.push(val); - return true; - } - }); - } - }; - return events; - }, - /** - * intialize a new PropogationPropertyModal Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'edgeInfo', 'relationshipId', 'lineageData', 'apiGuid', 'detailPageFetchCollection')); - this.entityModel = new VRelationship(); - this.VEntityModel = new VEntity(); - this.modalEdited = false; - this.viewType = 'flow'; - var that = this, - modalObj = { - title: 'Enable/Disable Propagation', - content: this, - okText: 'Update', - okCloses: false, - cancelText: "Cancel", - mainClass: 'modal-lg', - allowCancel: true, - }; - - this.modal = new Modal(modalObj) - this.modal.open(); - this.modal.$el.find('button.ok').attr("disabled", true); - this.on('ok', function() { - that.updateRelation(); - }); - this.on('closeModal', function() { - this.modal.trigger('cancel'); - }); - this.updateEdgeView(this.edgeInfo); - }, - - onRender: function() {}, - updateEdgeView: function(options) { - var obj = options, - fromEntity = this.lineageData.guidEntityMap[obj.fromEntityId], - toEntity = this.lineageData.guidEntityMap[obj.toEntityId]; - if (fromEntity && toEntity) { - this.ui.edgeDetailName.html(_.escape(fromEntity.displayText) + " " + _.escape(toEntity.displayText)); - } - if (obj && obj.relationshipId) { - this.showLoader(); - this.getEdgeEntity({ id: obj.relationshipId, from: fromEntity, to: toEntity }); - } - }, - getPropagationFlow: function(options) { - var relationshipData = options.relationshipData, - graphData = options.graphData, - propagateTags = relationshipData.propagateTags; - if (relationshipData.end1) { - if (relationshipData.end1.guid == graphData.from.guid || propagateTags == "BOTH" || propagateTags == "NONE") { - return propagateTags; - } else { - return propagateTags == "ONE_TO_TWO" ? "TWO_TO_ONE" : "ONE_TO_TWO"; - } - } else { - return propagateTags; - } - }, - getEdgeEntity: function(options) { - var that = this, - id = options.id, - from = options.from, - to = options.to, - enableOtherFlow = function(relationshipObj) { - var isTwoToOne = false; - if (relationshipObj.propagateTags == "BOTH") { - that.ui.propagationOptions.find('.both').show(); - } else { - that.ui.propagationOptions.find('.both').hide(); - if (that.edgeInfo.fromEntityId != relationshipObj.end1.guid && relationshipObj.propagateTags == "ONE_TO_TWO") { - isTwoToOne = true; - } else if (that.edgeInfo.fromEntityId == relationshipObj.end1.guid && relationshipObj.propagateTags == "TWO_TO_ONE") { - isTwoToOne = true; - } - if (isTwoToOne) { - that.ui.propagationOptions.find('.TWO_TO_ONE').show(); - } else { - that.ui.propagationOptions.find('.TWO_TO_ONE').hide(); - } - } - }, - updateValue = function(relationshipData) { - var relationshipObj = relationshipData.relationship; - if (relationshipObj) { - that.$("input[name='propagateRelation'][value=" + that.getPropagationFlow({ - "relationshipData": relationshipObj, - "graphData": options - }) + "]").prop('checked', true); - enableOtherFlow(relationshipObj); - that.showBlockedClassificationTable(relationshipData); - that.hideLoader({ buttonDisabled: true }); - } - } - this.ui.propagationOptions.find('li label>span.fromName').text(from.typeName); - this.ui.propagationOptions.find('li label>span.toName').text(to.typeName); - - if (id === this.ui.propagationOptions.attr("entity-id")) { - return; - } - this.ui.propagationOptions.attr("entity-id", id); - if (this.apiGuid[id]) { - updateValue(this.apiGuid[id]); - } else { - if (this.edgeCall && this.edgeCall.readyState != 4) { - this.edgeCall.abort(); - } - this.edgeCall = this.entityModel.getRelationship(id, { - success: function(relationshipData) { - that.apiGuid[relationshipData.relationship.guid] = relationshipData; - updateValue(relationshipData); - }, - cust_error: function() { - that.hideLoader(); - } - }); - } - }, - updateRelation: function() { - var that = this, - entityId = that.ui.propagationOptions.attr('entity-id'), - PropagationValue = this.$("input[name='propagateRelation']:checked").val(), - relationshipProp = {}; - this.ui.propagationOptions.attr("propagation", PropagationValue); - if (this.viewType == "flow") { - relationshipProp = { - "propagateTags": that.getPropagationFlow({ - "relationshipData": _.extend({}, this.apiGuid[entityId].relationship, { 'propagateTags': PropagationValue }), - "graphData": { from: { guid: this.edgeInfo.fromEntityId } } - }) - } - } else { - relationshipProp = { - "blockedPropagatedClassifications": this.blockedPropagatedClassifications, - "propagatedClassifications": this.propagatedClassifications - }; - } - this.showLoader(); - this.entityModel.saveRelationship({ - data: JSON.stringify(_.extend({}, that.apiGuid[entityId].relationship, relationshipProp)), - success: function(relationshipData) { - if (relationshipData) { - that.hideLoader({ buttonDisabled: true }); - that.modal.trigger('cancel'); - that.apiGuid[relationshipData.guid] = relationshipData; - that.detailPageFetchCollection(); - Utils.notifySuccess({ - content: "Propagation flow updated succesfully." - }); - } - }, - cust_error: function() { - that.hideLoader(); - } - }); - }, - showBlockedClassificationTable: function(options) { - var that = this, - propagationStringValue = "", - classificationTableValue = "", - relationship = options.relationship, - referredEntities = options.referredEntities, - getEntityName = function(guid) { - var entityObj = referredEntities[guid], - name = guid; - if (entityObj) { - name = Utils.getName(entityObj) + " (" + entityObj.typeName + ")"; - } - return "" + name + ""; - }, - getTableRow = function(options) { - var val = options.val, - fromBlockClassification = options.fromBlockClassification; - return "" + val.typeName + "" + getEntityName(val.entityGuid) + ""; - }; - - this.blockedPropagatedClassifications = _.isUndefined(relationship.blockedPropagatedClassifications) ? [] : _.clone(relationship.blockedPropagatedClassifications); - this.propagatedClassifications = _.isUndefined(relationship.propagatedClassifications) ? [] : _.clone(relationship.propagatedClassifications); - _.each(this.blockedPropagatedClassifications, function(val, key) { - propagationStringValue += getTableRow({ "val": val, fromBlockClassification: true }); - }); - _.each(this.propagatedClassifications, function(val, key) { - propagationStringValue += getTableRow({ "val": val, fromBlockClassification: false }); - }); - - classificationTableValue = "" + propagationStringValue + "
        ClassificationEntity NameBlock Propagatation
        "; - - this.ui.PropagatedClassificationTable.append(_.isEmpty(propagationStringValue) ? "No Records Found." : classificationTableValue); - }, - showLoader: function() { - this.modal.$el.find('button.ok').showButtonLoader(); - this.$('.overlay').removeClass('hide').addClass('show'); - }, - hideLoader: function(options) { - var buttonDisabled = options && options.buttonDisabled; - this.modal.$el.find('button.ok').hideButtonLoader(); - this.modal.$el.find('button.ok').attr("disabled", buttonDisabled ? buttonDisabled : false); - this.$('.overlay').removeClass('show').addClass('hide'); - }, - notifyModal: function(options) { - var that = this, - notifyObj = { - modal: true, - text: "It looks like you have edited something. If you leave before saving, your changes will be lost.", - ok: function(argument) { - that.viewType = that.ui.editPropagationType.is(":checked") ? "flow" : "table"; - that.ui.editPropagationType.prop("checked", that.viewType === "flow" ? false : true).trigger("change"); - that.modal.$el.find('button.ok').attr("disabled", true); - }, - cancel: function(argument) { - that.viewType = that.ui.editPropagationType.is(":checked") ? "table" : "flow"; - } - }; - Utils.notifyConfirm(notifyObj); - }, - showEditPropagation: function() { - this.$('.editPropagation').show(); - this.$('.propagatedClassificationTable').hide(); - this.modal.$el.find('.modal-title').text("Enable/Disable Propagation"); - }, - showPropagatedClassificationTable: function() { - this.$('.editPropagation').hide(); - this.$('.propagatedClassificationTable').show(); - this.modal.$el.find('.modal-title').text("Select Classifications to Block Propagation"); - } - - }); - return PropogationPropertyModal; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/graph/RelationshipLayoutView.js b/dashboardv2/public/js/views/graph/RelationshipLayoutView.js deleted file mode 100644 index 96585848361..00000000000 --- a/dashboardv2/public/js/views/graph/RelationshipLayoutView.js +++ /dev/null @@ -1,554 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define([ - "require", - "backbone", - "hbs!tmpl/graph/RelationshipLayoutView_tmpl", - "collection/VLineageList", - "models/VEntity", - "utils/Utils", - "utils/CommonViewFunction", - "d3", - "d3-tip", - "utils/Enums", - "utils/UrlLinks", - "platform" -], function(require, Backbone, RelationshipLayoutViewtmpl, VLineageList, VEntity, Utils, CommonViewFunction, d3, d3Tip, Enums, UrlLinks, platform) { - "use strict"; - - var RelationshipLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends RelationshipLayoutView */ - { - _viewName: "RelationshipLayoutView", - - template: RelationshipLayoutViewtmpl, - className: "resizeGraph", - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - relationshipDetailClose: '[data-id="close"]', - searchNode: '[data-id="searchNode"]', - relationshipViewToggle: 'input[name="relationshipViewToggle"]', - relationshipDetailTable: "[data-id='relationshipDetailTable']", - relationshipSVG: "[data-id='relationshipSVG']", - relationshipDetailValue: "[data-id='relationshipDetailValue']", - zoomControl: "[data-id='zoomControl']", - boxClose: '[data-id="box-close"]', - noValueToggle: "[data-id='noValueToggle']" - }, - - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.relationshipDetailClose] = function() { - this.toggleInformationSlider({ close: true }); - }; - events["keyup " + this.ui.searchNode] = "searchNode"; - events["click " + this.ui.boxClose] = "toggleBoxPanel"; - events["change " + this.ui.relationshipViewToggle] = function(e) { - this.relationshipViewToggle(e.currentTarget.checked); - }; - events["click " + this.ui.noValueToggle] = function(e) { - Utils.togglePropertyRelationshipTableEmptyValues({ - inputType: this.ui.noValueToggle, - tableEl: this.ui.relationshipDetailValue - }); - }; - return events; - }, - - /** - * intialize a new RelationshipLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, "entity", "entityName", "guid", "actionCallBack", "attributeDefs")); - this.graphData = this.createData(this.entity); - }, - createData: function(entity) { - var that = this, - links = [], - nodes = {}; - if (entity && entity.relationshipAttributes) { - _.each(entity.relationshipAttributes, function(obj, key) { - if (!_.isEmpty(obj)) { - links.push({ - source: nodes[that.entity.typeName] || - (nodes[that.entity.typeName] = _.extend({ name: that.entity.typeName }, { value: entity })), - target: nodes[key] || - (nodes[key] = _.extend({ - name: key - }, { value: obj })), - value: obj - }); - } - }); - } - return { nodes: nodes, links: links }; - }, - onRender: function() { - this.ui.zoomControl.hide(); - this.$el.addClass("auto-height"); - }, - onShow: function(argument) { - if (this.graphData && _.isEmpty(this.graphData.links)) { - this.noRelationship(); - } else { - this.createGraph(this.graphData); - } - this.createTable(); - }, - noRelationship: function() { - this.$("svg").html('No relationship data found'); - }, - toggleInformationSlider: function(options) { - if (options.open && !this.$(".relationship-details").hasClass("open")) { - this.$(".relationship-details").addClass("open"); - } else if (options.close && this.$(".relationship-details").hasClass("open")) { - d3.selectAll("circle").attr("stroke", "none"); - this.$(".relationship-details").removeClass("open"); - } - }, - toggleBoxPanel: function(options) { - var el = options && options.el, - nodeDetailToggler = options && options.nodeDetailToggler, - currentTarget = options.currentTarget; - this.$el.find(".show-box-panel").removeClass("show-box-panel"); - if (el && el.addClass) { - el.addClass("show-box-panel"); - } - this.$("circle.node-detail-highlight").removeClass("node-detail-highlight"); - }, - searchNode: function(e) { - var $el = $(e.currentTarget); - this.updateRelationshipDetails(_.extend({}, $el.data(), { searchString: $el.val() })); - }, - updateRelationshipDetails: function(options) { - var data = options.obj.value, - typeName = data.typeName || options.obj.name, - searchString = _.escape(options.searchString), - listString = "", - getEntityTypelist = function(options) { - var activeEntityColor = "#4a90e2", - deletedEntityColor = "#BB5838", - entityTypeHtml = "
        ",
        -                            getdefault = function(obj) {
        -                                var options = obj.options,
        -                                    status = Enums.entityStateReadOnly[options.entityStatus || options.status] ? " deleted-relation" : "",
        -                                    guid = options.guid,
        -                                    entityColor = obj.color,
        -                                    name = obj.name,
        -                                    typeName = options.typeName;
        -                                if (typeName === "AtlasGlossaryTerm") {
        -                                    return '
      • ' + - '' + name + ' (' + typeName + ')' + - '
      • '; - } else { - return "
      • " + - "" + name + " (" + typeName + ")" + - "
      • "; - } - }, - getWithButton = function(obj) { - var options = obj.options, - status = Enums.entityStateReadOnly[options.entityStatus || options.status] ? " deleted-relation" : "", - guid = options.guid, - entityColor = obj.color, - name = obj.name, - typeName = options.typeName, - relationship = obj.relationship || false, - entity = obj.entity || false, - icon = '', - title = "Deleted"; - if (relationship) { - icon = ''; - status = Enums.entityStateReadOnly[options.relationshipStatus || options.status] ? "deleted-relation" : ""; - title = "Relationship Deleted"; - } - return "
      • " + - "" + _.escape(name) + " (" + options.typeName + ")" + - '' + - "
      • "; - }; - - var name = options.entityName ? options.entityName : Utils.getName(options, "displayText"); - if (options.entityStatus == "ACTIVE") { - if (options.relationshipStatus == "ACTIVE") { - entityTypeHtml = getdefault({ - color: activeEntityColor, - options: options, - name: name - }); - } else if (options.relationshipStatus == "DELETED") { - entityTypeHtml = getWithButton({ - color: activeEntityColor, - options: options, - name: name, - relationship: true - }); - } - } else if (options.entityStatus == "DELETED") { - entityTypeHtml = getWithButton({ - color: deletedEntityColor, - options: options, - name: name, - entity: true - }); - } else { - entityTypeHtml = getdefault({ - color: activeEntityColor, - options: options, - name: name - }); - } - return entityTypeHtml + "
        "; - }; - this.ui.searchNode.hide(); - this.$("[data-id='typeName']").text(typeName); - var getElement = function(options) { - var name = options.entityName ? options.entityName : Utils.getName(options, "displayText"); - var entityTypeButton = getEntityTypelist(options); - return entityTypeButton; - }; - if (_.isArray(data)) { - if (data.length > 1) { - this.ui.searchNode.show(); - } - _.each(_.sortBy(data, "displayText"), function(val) { - var name = Utils.getName(val, "displayText"), - valObj = _.extend({}, val, { entityName: name }); - if (searchString) { - if (name.search(new RegExp(searchString, "i")) != -1) { - listString += getElement(valObj); - } else { - return; - } - } else { - listString += getElement(valObj); - } - }); - } else { - listString += getElement(data); - } - this.$("[data-id='entityList']").html(listString); - }, - createGraph: function(data) { - //Ref - http://bl.ocks.org/fancellu/2c782394602a93921faff74e594d1bb1 - - var that = this, - width = this.$("svg").width(), - height = this.$("svg").height(), - nodes = d3.values(data.nodes), - links = data.links; - - var activeEntityColor = "#00b98b", - deletedEntityColor = "#BB5838", - defaultEntityColor = "#e0e0e0", - selectedNodeColor = "#4a90e2"; - - var svg = d3 - .select(this.$("svg")[0]) - .attr("viewBox", "0 0 " + width + " " + height) - .attr("enable-background", "new 0 0 " + width + " " + height), - node, - path; - - var container = svg - .append("g") - .attr("id", "container") - .attr("transform", "translate(0,0)scale(1,1)"); - - var zoom = d3 - .zoom() - .scaleExtent([0.1, 4]) - .on("zoom", function() { - container.attr("transform", d3.event.transform); - }); - - svg.call(zoom).on("dblclick.zoom", null); - - container - .append("svg:defs") - .selectAll("marker") - .data(["deletedLink", "activeLink"]) // Different link/path types can be defined here - .enter() - .append("svg:marker") // This section adds in the arrows - .attr("id", String) - .attr("viewBox", "-0 -5 10 10") - .attr("refX", 10) - .attr("refY", -0.5) - .attr("orient", "auto") - .attr("markerWidth", 6) - .attr("markerHeight", 6) - .append("svg:path") - .attr("d", "M 0,-5 L 10 ,0 L 0,5") - .attr("fill", function(d) { - return d == "deletedLink" ? deletedEntityColor : activeEntityColor; - }) - .style("stroke", "none"); - - var forceLink = d3 - .forceLink() - .id(function(d) { - return d.id; - }) - .distance(function(d) { - return 100; - }) - .strength(1); - - var simulation = d3 - .forceSimulation() - .force("link", forceLink) - .force("charge", d3.forceManyBody()) - .force("center", d3.forceCenter(width / 2, height / 2)); - - update(); - - function update() { - path = container - .append("svg:g") - .selectAll("path") - .data(links) - .enter() - .append("svg:path") - .attr("class", "relatioship-link") - .attr("stroke", function(d) { - return getPathColor({ data: d, type: "path" }); - }) - .attr("marker-end", function(d) { - return "url(#" + (isAllEntityRelationDeleted({ data: d }) ? "deletedLink" : "activeLink") + ")"; - }); - - node = container - .selectAll(".node") - .data(nodes) - .enter() - .append("g") - .attr("class", "node") - .on("mousedown", function() { - console.log(d3.event); - d3.event.preventDefault(); - }) - .on("click", function(d) { - if (d3.event.defaultPrevented) return; // ignore drag - if (d && d.value && d.value.guid == that.guid) { - that.ui.boxClose.trigger("click"); - return; - } - that.toggleBoxPanel({ el: that.$(".relationship-node-details") }); - that.ui.searchNode.data({ obj: d }); - $(this) - .find("circle") - .addClass("node-detail-highlight"); - that.updateRelationshipDetails({ obj: d }); - }) - .call( - d3 - .drag() - .on("start", dragstarted) - .on("drag", dragged) - ); - - var circleContainer = node.append("g"); - - circleContainer - .append("circle") - .attr("cx", 0) - .attr("cy", 0) - .attr("r", function(d) { - d.radius = 25; - return d.radius; - }) - .attr("fill", function(d) { - if (d && d.value && d.value.guid == that.guid) { - if (isAllEntityRelationDeleted({ data: d, type: "node" })) { - return deletedEntityColor; - } else { - return selectedNodeColor; - } - } else if (isAllEntityRelationDeleted({ data: d, type: "node" })) { - return deletedEntityColor; - } else { - return activeEntityColor; - } - }) - .attr("typename", function(d) { - return d.name; - }); - - circleContainer - .append("text") - .attr("x", 0) - .attr("y", 0) - .attr("dy", 25 - 17) - .attr("text-anchor", "middle") - .style("font-family", "FontAwesome") - .style("font-size", function(d) { - return "25px"; - }) - .text(function(d) { - var iconObj = Enums.graphIcon[d.name]; - if (iconObj && iconObj.textContent) { - return iconObj.textContent; - } else { - if (d && _.isArray(d.value) && d.value.length > 1) { - return "\uf0c5"; - } else { - return "\uf016"; - } - } - }) - .attr("fill", function(d) { - return "#fff"; - }); - - var countBox = circleContainer.append("g"); - - countBox - .append("circle") - .attr("cx", 18) - .attr("cy", -20) - .attr("r", function(d) { - if (_.isArray(d.value) && d.value.length > 1) { - return 10; - } - }); - - countBox - .append("text") - .attr("dx", 18) - .attr("dy", -16) - .attr("text-anchor", "middle") - .attr("fill", defaultEntityColor) - .text(function(d) { - if (_.isArray(d.value) && d.value.length > 1) { - return d.value.length; - } - }); - - node.append("text") - .attr("x", -15) - .attr("y", "35") - .text(function(d) { - return d.name; - }); - - simulation.nodes(nodes).on("tick", ticked); - - simulation.force("link").links(links); - } - - function ticked() { - path.attr("d", function(d) { - var diffX = d.target.x - d.source.x, - diffY = d.target.y - d.source.y, - // Length of path from center of source node to center of target node - pathLength = Math.sqrt(diffX * diffX + diffY * diffY), - // x and y distances from center to outside edge of target node - offsetX = (diffX * d.target.radius) / pathLength, - offsetY = (diffY * d.target.radius) / pathLength; - - return "M" + d.source.x + "," + d.source.y + "A" + pathLength + "," + pathLength + " 0 0,1 " + (d.target.x - offsetX) + "," + (d.target.y - offsetY); - }); - - node.attr("transform", function(d) { - return "translate(" + d.x + "," + d.y + ")"; - }); - } - - function dragstarted(d) { - d3.event.sourceEvent.stopPropagation(); - if (d && d.value && d.value.guid != that.guid) { - if (!d3.event.active) simulation.alphaTarget(0.3).restart(); - d.fx = d.x; - d.fy = d.y; - } - } - - function dragged(d) { - if (d && d.value && d.value.guid != that.guid) { - d.fx = d3.event.x; - d.fy = d3.event.y; - } - } - - function getPathColor(options) { - return isAllEntityRelationDeleted(options) ? deletedEntityColor : activeEntityColor; - } - - function isAllEntityRelationDeleted(options) { - var data = options.data, - type = options.type; - var d = $.extend(true, {}, data); - if (d && !_.isArray(d.value)) { - d.value = [d.value]; - } - - return ( - _.findIndex(d.value, function(val) { - if (type == "node") { - return (val.entityStatus || val.status) == "ACTIVE"; - } else { - return val.relationshipStatus == "ACTIVE"; - } - }) == -1 - ); - } - var zoomClick = function() { - var scaleFactor = 0.8; - if (this.id === 'zoom_in') { - scaleFactor = 1.3; - } - zoom.scaleBy(svg.transition().duration(750), scaleFactor); - } - - d3.selectAll(this.$('.lineageZoomButton')).on('click', zoomClick); - }, - createTable: function() { - this.entityModel = new VEntity({}); - var table = CommonViewFunction.propertyTable({ - scope: this, - valueObject: this.entity.relationshipAttributes, - attributeDefs: this.attributeDefs - }); - this.ui.relationshipDetailValue.html(table); - Utils.togglePropertyRelationshipTableEmptyValues({ - inputType: this.ui.noValueToggle, - tableEl: this.ui.relationshipDetailValue - }); - }, - relationshipViewToggle: function(checked) { - this.ui.relationshipDetailTable.toggleClass("visible invisible"); - this.ui.relationshipSVG.toggleClass("visible invisible"); - - if (checked) { - this.ui.zoomControl.hide(); - this.$el.addClass("auto-height"); - } else { - this.ui.zoomControl.show(); - this.$el.removeClass("auto-height"); - } - } - } - ); - return RelationshipLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/graph/TypeSystemTreeView.js b/dashboardv2/public/js/views/graph/TypeSystemTreeView.js deleted file mode 100644 index 935cae0019a..00000000000 --- a/dashboardv2/public/js/views/graph/TypeSystemTreeView.js +++ /dev/null @@ -1,526 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -define([ - "require", - "backbone", - "hbs!tmpl/graph/TypeSystemTreeView_tmpl", - "collection/VLineageList", - "models/VEntity", - "LineageHelper", - "d3", - "dagreD3", - "d3-tip", - "utils/CommonViewFunction", - "utils/Utils", - "platform", - "jquery-ui" -], function(require, Backbone, TypeSystemTreeViewTmpl, VLineageList, VEntity, LineageHelper, d3, dagreD3, d3Tip, CommonViewFunction, Utils, platform) { - "use strict"; - - /** @lends TypeSystemTreeView */ - var TypeSystemTreeView = Backbone.Marionette.LayoutView.extend({ - _viewName: "TypeSystemTreeViewTmpl", - - template: TypeSystemTreeViewTmpl, - templateHelpers: function() { - return { - modalID: this.viewId, - width: "100%", - height: "300px" - }; - }, - - /** Layout sub regions */ - regions: { - RTypeSystemTreeViewPage: "#r_typeSystemTreeViewPage" - }, - - /** ui selector cache */ - ui: { - typeSystemTreeViewPage: "[data-id='typeSystemTreeViewPage']", - boxClose: '[data-id="box-close"]', - nodeDetailTable: '[data-id="nodeDetailTable"]', - attributeTable: '[data-id="attribute-table"]', - typeSearch: '[data-id="typeSearch"]', - filterServiceType: '[data-id="filterServiceType"]', - onZoomIn: '[data-id="zoom-in"]', - onZoomOut: '[data-id="zoom-out"]', - filterBox: ".filter-box", - searchBox: ".search-box", - settingBox: '.setting-box', - filterToggler: '[data-id="filter-toggler"]', - settingToggler: '[data-id="setting-toggler"]', - searchToggler: '[data-id="search-toggler"]', - labelFullName: '[data-id="labelFullName"]', - reset: '[data-id="reset"]', - fullscreenToggler: '[data-id="fullScreen-toggler"]', - noValueToggle: "[data-id='noValueToggle']", - showOnlyHoverPath: '[data-id="showOnlyHoverPath"]', - showTooltip: '[data-id="showTooltip"]', - saveSvg: '[data-id="saveSvg"]', - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.boxClose] = "toggleBoxPanel"; - events["click " + this.ui.onZoomIn] = "onClickZoomIn"; - events["click " + this.ui.onZoomOut] = "onClickZoomOut"; - events["click " + this.ui.filterToggler] = "onClickFilterToggler"; - events["click " + this.ui.settingToggler] = 'onClickSettingToggler'; - events["click " + this.ui.searchToggler] = "onClickSearchToggler"; - events["click " + this.ui.saveSvg] = 'onClickSaveSvg'; - events["click " + this.ui.fullscreenToggler] = "onClickFullscreenToggler"; - events["click " + this.ui.reset] = "onClickReset"; - events["change " + this.ui.labelFullName] = "onClickLabelFullName"; - events["click " + this.ui.noValueToggle] = function() { - this.showAllProperties = !this.showAllProperties; - this.ui.noValueToggle.attr("data-original-title", (this.showAllProperties ? "Hide" : "Show") + " empty values"); - Utils.togglePropertyRelationshipTableEmptyValues({ - "inputType": this.ui.noValueToggle, - "tableEl": this.ui.nodeDetailTable - }); - }; - return events; - }, - - /** - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, "entityDefCollection")); - this.labelFullText = false; - }, - onShow: function() { - this.$(".fontLoader").show(); - this.initializeGraph(); - this.fetchGraphData(); - }, - onRender: function() { - var that = this; - this.$el.on("click", "code li[data-def]", function() { - if (that.selectedDetailNode) { - var dataObj = $(this).data(), - defObj = that.selectedDetailNode[dataObj.def], - newData = null; - if (dataObj.def === "businessAttributes") { - newData = defObj[dataObj.attribute]; - } else { - newData = _.filter(defObj, { name: dataObj.attribute }); - } - that.ui.attributeTable.find("pre").html('' + Utils.JSONPrettyPrint(newData, function(val) { - return val; - }) + ''); - that.$el.find('[data-id="typeAttrDetailHeader"]').text(dataObj.def); - that.ui.nodeDetailTable.hide("slide", { direction: "right" }, 400); - that.ui.attributeTable.show("slide", { direction: "left" }, 400); - that.$el.find(".typeDetailHeader").hide(); - that.$el.find(".typeAttrDetailHeader").show() - } - }); - this.$el.on("click", "span[data-id='box-back']", function() { - that.ui.nodeDetailTable.show("slide", { direction: "right" }, 400); - that.ui.attributeTable.hide("slide", { direction: "left" }, 400); - that.$el.find(".typeDetailHeader").show(); - that.$el.find(".typeAttrDetailHeader").hide() - }) - }, - fetchGraphData: function(options) { - var that = this; - var entityTypeDef = that.entityDefCollection.fullCollection.toJSON(); - this.$(".fontLoader").show(); - this.$("svg").empty(); - if (that.isDestroyed) { - return; - } - if (entityTypeDef.length) { - that.generateData($.extend(true, {}, { data: entityTypeDef }, options)).then(function(graphObj) { - that.createGraph(options); - }); - } - }, - generateData: function(options) { - return new Promise( - function(resolve, reject) { - try { - var that = this, - newHashMap = {}, - styleObj = { - fill: "none", - stroke: "#ffb203", - width: 3 - }, - makeNodeData = function(relationObj) { - if (relationObj) { - if (relationObj.updatedValues) { - return relationObj; - } - var obj = _.extend(relationObj, { - shape: "img", - updatedValues: true, - label: relationObj.name.trunc(18), - toolTipLabel: relationObj.name, - id: relationObj.guid, - isLineage: true, - isIncomplete: false - }); - return obj; - } - }, - getStyleObjStr = function(styleObj) { - return "fill:" + styleObj.fill + ";stroke:" + styleObj.stroke + ";stroke-width:" + styleObj.width; - }, - setNode = function(guid, obj) { - var node = that.LineageHelperRef.getNode(guid); - if (!node) { - var nodeData = makeNodeData(obj); - that.LineageHelperRef.setNode(guid, nodeData); - return nodeData; - } else { - return node; - } - }, - setEdge = function(fromNodeGuid, toNodeGuid) { - that.LineageHelperRef.setEdge(fromNodeGuid, toNodeGuid, { - arrowhead: "arrowPoint", - style: getStyleObjStr(styleObj), - styleObj: styleObj - }); - }, - setGraphData = function(fromEntityId, toEntityId) { - setNode(fromEntityId); - setNode(toEntityId); - setEdge(fromEntityId, toEntityId); - }; - - if (options.data) { - if (options.filter) { - // filter - var pendingSuperList = {}, - outOfFilterData = {}, - doneList = {}; - - var linkParents = function(obj) { - if (obj && obj.superTypes.length) { - _.each(obj.superTypes, function(superType) { - var fromEntityId = obj.guid; - var tempObj = doneList[superType] || outOfFilterData[superType]; - if (tempObj) { - if (!doneList[superType]) { - setNode(tempObj.guid, tempObj); - } - setEdge(tempObj.guid, fromEntityId); - linkParents(tempObj); - } else { - if (pendingSuperList[superType]) { - pendingSuperList[superType].push(fromEntityId); - } else { - pendingSuperList[superType] = [fromEntityId]; - } - } - }); - } - } - _.each(options.data, function(obj) { - var fromEntityId = obj.guid; - if (pendingSuperList[obj.name]) { - doneList[obj.name] = obj; - setNode(fromEntityId, obj); - _.map(pendingSuperList[obj.name], function(guid) { - setEdge(fromEntityId, guid); - }); - delete pendingSuperList[obj.name]; - linkParents(obj); - } - if (obj.serviceType === options.filter) { - doneList[obj.name] = obj; - setNode(fromEntityId, obj); - linkParents(obj); - } else if (!doneList[obj.name] && !outOfFilterData[obj.name]) { - outOfFilterData[obj.name] = obj; - } - }); - pendingSuperList = null; - doneList = null; - outOfFilterData = null; - } else { - // Without filter - var pendingList = {}, - doneList = {}; - - _.each(options.data, function(obj) { - var fromEntityId = obj.guid; - doneList[obj.name] = obj; - setNode(fromEntityId, obj); - if (pendingList[obj.name]) { - _.map(pendingList[obj.name], function(guid) { - setEdge(guid, fromEntityId); - }); - delete pendingList[obj.name]; - } - if (obj.subTypes.length) { - _.each(obj.subTypes, function(subTypes) { - //var subTypesObj = _.find(options.data({ name: superTypes }); - //setNode(superTypeObj.attributes.guid, superTypeObj.attributes); - if (doneList[subTypes]) { - setEdge(fromEntityId, doneList[subTypes].guid); - } else { - if (pendingList[subTypes]) { - pendingList[subTypes].push(fromEntityId); - } else { - pendingList[subTypes] = [fromEntityId]; - } - } - }); - } - }); - pendingList = null; - doneList = null; - } - } - resolve(this.g); - } catch (e) { - reject(e); - } - }.bind(this) - ); - }, - toggleBoxPanel: function(options) { - var el = options && options.el, - nodeDetailToggler = options && options.nodeDetailToggler, - currentTarget = options.currentTarget; - this.$el.find(".show-box-panel").removeClass("show-box-panel"); - if (el && el.addClass) { - el.addClass("show-box-panel"); - } - this.$("circle.node-detail-highlight").removeClass("node-detail-highlight"); - }, - onClickNodeToggler: function(options) { - this.toggleBoxPanel({ el: this.$(".lineage-node-detail"), nodeDetailToggler: true }); - }, - onClickZoomIn: function() { - this.LineageHelperRef.zoomIn(); - }, - onClickZoomOut: function() { - this.LineageHelperRef.zoomOut(); - }, - onClickFilterToggler: function() { - this.toggleBoxPanel({ el: this.ui.filterBox }); - }, - onClickSettingToggler: function() { - this.toggleBoxPanel({ el: this.ui.settingBox }); - }, - onClickSearchToggler: function() { - this.toggleBoxPanel({ el: this.ui.searchBox }); - }, - onClickLabelFullName: function() { - this.labelFullText = !this.labelFullText; - this.LineageHelperRef.displayFullName({ bLabelFullText : this.labelFullText }); - }, - onClickReset: function() { - this.fetchGraphData({ refresh: true }); - this.ui.typeSearch.data({ refresh: true }).val("").trigger("change"); - this.ui.filterServiceType.data({ refresh: true }).val("").trigger("change"); - this.ui.labelFullName.prop("checked", false); - this.labelFullText = false; - }, - onClickSaveSvg: function(e, a) { - this.LineageHelperRef.exportLineage({ downloadFileName: "TypeSystemView" }); - }, - onClickFullscreenToggler: function(e) { - var icon = $(e.currentTarget).find("i"), - panel = $(e.target).parents(".tab-pane").first(); - icon.toggleClass("fa-expand fa-compress"); - if (icon.hasClass("fa-expand")) { - icon.parent("button").attr("data-original-title", "Full Screen"); - } else { - icon.parent("button").attr("data-original-title", "Default View"); - } - panel.toggleClass("fullscreen-mode"); - var node = this.$("svg.main").parent()[0].getBoundingClientRect(); - this.LineageHelperRef.updateOptions({ - width: node.width, - height: node.height - }); - this.calculateLineageDetailPanelHeight(); - }, - updateDetails: function(data) { - this.$("[data-id='typeName']").text(Utils.getName(data)); - - this.selectedDetailNode = {}; - this.selectedDetailNode.atttributes = data.attributeDefs; - this.selectedDetailNode.businessAttributes = data.businessAttributeDefs; - this.selectedDetailNode.relationshipAttributes = data.relationshipAttributeDefs; - //atttributes - data["atttributes"] = (data.attributeDefs || []).map(function(obj) { - return obj.name; - }); - //businessAttributes - data["businessAttributes"] = _.keys(data.businessAttributeDefs); - //relationshipAttributes - data["relationshipAttributes"] = (data.relationshipAttributeDefs || []).map(function(obj) { - return obj.name; - }); - - this.ui.nodeDetailTable.html( - CommonViewFunction.propertyTable({ - scope: this, - guidHyperLink: false, - getValue: function(val, key) { - if (key && key.toLowerCase().indexOf("time") > 0) { - return Utils.formatDate({ date: val }); - } else { - return val; - } - }, - getArrayOfStringElement: function(val, key) { - var def = null, - classname = "json-string"; - if (key === "atttributes" || key === "businessAttributes" || key === "relationshipAttributes") { - def = key; - classname += " cursor"; - } - return "
      • " + val + "
      • " - }, - getArrayOfStringFormat: function(valueArray) { - return valueArray.join(""); - }, - getEmptyString: function(key) { - if (key === "subTypes" || key === "superTypes" || key === "atttributes" || key === "relationshipAttributes") { - return "[]"; - } - return "N/A"; - }, - valueObject: _.omit(data, ["id", "attributeDefs", "relationshipAttributeDefs", "businessAttributeDefs", "isLineage", "isIncomplete", "label", "shape", "toolTipLabel", "updatedValues"]), - sortBy: true - }) - ); - }, - createGraph: function(opt) { - this.LineageHelperRef.createGraph(); - }, - filterData: function(value) { - this.LineageHelperRef.refresh(); - this.fetchGraphData({ filter: value }); - }, - initializeGraph: function() { - //ref - https://bl.ocks.org/seemantk/80613e25e9804934608ac42440562168 - var that = this, - node = this.$("svg.main").parent()[0].getBoundingClientRect(); - this.$("svg").attr("viewBox", "0 0 " + node.width + " " + node.height); - this.LineageHelperRef = new LineageHelper.default({ - el: this.$("svg.main")[0], - legends: false, - setDataManually: true, - width: node.width, - height: node.height, - zoom: true, - fitToScreen: true, - dagreOptions: { - rankdir: "tb" - }, - toolTipTitle: "Type", - isShowHoverPath: function() { return that.ui.showOnlyHoverPath.prop('checked') }, - isShowTooltip: function() { return that.ui.showTooltip.prop('checked') }, - onNodeClick: function(d) { - that.onClickNodeToggler(); - that.updateDetails(that.LineageHelperRef.getNode(d.clickedData, true)); - that.calculateLineageDetailPanelHeight(); - }, - beforeRender: function() { - that.$(".fontLoader").show(); - }, - afterRender: function() { - that.graphOptions = that.LineageHelperRef.getGraphOptions(); - that.renderTypeFilterSearch(); - that.$(".fontLoader").hide(); - return; - } - }); - }, - renderTypeFilterSearch: function(data) { - var that = this; - var searchStr = "", - filterStr = "", - tempFilteMap = {}; - var nodes = that.LineageHelperRef.getNodes(); - if (!_.isEmpty(nodes)) { - _.each(nodes, function(obj) { - searchStr += '"; - if (obj.serviceType && !tempFilteMap[obj.serviceType]) { - tempFilteMap[obj.serviceType] = obj.serviceType; - filterStr += '"; - } - }); - } - this.ui.typeSearch.html(searchStr); - if (!this.ui.filterServiceType.data("select2")) { - this.ui.filterServiceType.html(filterStr); - } - - this.initilizeTypeFilterSearch(); - }, - initilizeTypeFilterSearch: function() { - var that = this; - this.ui.typeSearch - .select2({ - closeOnSelect: true, - placeholder: "Select Type" - }) - .on("change.select2", function(e) { - e.stopPropagation(); - e.stopImmediatePropagation(); - if (!that.ui.typeSearch.data("refresh")) { - var selectedNode = $('[data-id="typeSearch"]').val(); - that.LineageHelperRef.searchNode({ guid: selectedNode }); - } else { - that.ui.typeSearch.data("refresh", false); - } - }); - if (!this.ui.filterServiceType.data("select2")) { - this.ui.filterServiceType - .select2({ - closeOnSelect: true, - placeholder: "Select ServiceType" - }) - .on("change.select2", function(e) { - e.stopPropagation(); - e.stopImmediatePropagation(); - if (!that.ui.filterServiceType.data("refresh")) { - var selectedNode = $('[data-id="filterServiceType"]').val(); - that.filterData(selectedNode); - } else { - that.ui.filterServiceType.data("refresh", false); - } - }); - } - }, - calculateLineageDetailPanelHeight: function(){ - this.ui.typeSystemTreeViewPage.find('tbody').removeAttr('style'); - var $panel = this.ui.typeSystemTreeViewPage.find('.fix-box'), - $parentHeight = this.ui.typeSystemTreeViewPage.height() - 48, // 48px is the Panels top from the parent container - $tBody = $panel.find('tbody'), - panelHeight = $tBody.height() + 37; //37px is height of Panel Header - if($parentHeight < panelHeight){ - panelHeight = $parentHeight; - } - $panel.css('height', panelHeight + 'px'); - $tBody.css('height', '100%'); - } - }); - return TypeSystemTreeView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/import/ImportLayoutView.js b/dashboardv2/public/js/views/import/ImportLayoutView.js deleted file mode 100644 index 27440bb9a4a..00000000000 --- a/dashboardv2/public/js/views/import/ImportLayoutView.js +++ /dev/null @@ -1,170 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define([ - "require", - "backbone", - "hbs!tmpl/import/ImportLayoutView_tmpl", - "modules/Modal", - 'utils/CommonViewFunction', - "utils/Utils", - "utils/UrlLinks", - "dropzone" -], function(require, Backbone, ImportLayoutViewTmpl, Modal, CommonViewFunction, Utils, UrlLinks, dropzone) { - var ImportLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends ImportLayoutView */ - { - _viewName: "ImportLayoutView", - - template: ImportLayoutViewTmpl, - - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - errorContainer: "[data-id='errorContainer']", - importGlossary: "[data-id='importGlossary']", - errorDetails: "[data-id='errorDetails']" - }, - /** ui events hash */ - events: function() { - var events = {}; - return events; - }, - /** - * intialize a new ImportLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, "callback", "isGlossary")); - var that = this; - this.modal = new Modal({ - title: this.isGlossary ? "Import Glossary Term" : "Import Business Metadata", - content: this, - cancelText: "Cancel", - okText: "Upload", - allowCancel: true, - okCloses: false, - mainClass: "dropzone-modal" - }).open(); - this.modal.$el.find("button.ok").attr("disabled", true); - this.modal.on("ok", function(e) { - that.dropzone.processQueue(); - }); - this.modal.on("closeModal", function() { - that.modal.trigger("cancel"); - }); - this.bindEvents(); - }, - bindEvents: function() { - var that = this; - $('body').on('click', '.importBackBtn', function() { - var modalTitle = that.isGlossary ? "Import Glossary Term" : "Import Business Metadata"; - that.toggleErrorAndDropZoneView({ title: modalTitle, isErrorView: false }); - }); - }, - onRender: function() { - var that = this; - this.dropzone = null; - var updateButton = function(files) { - var buttonEl = that.modal.$el.find("button.ok"); - if (files.length === 0) { - buttonEl.attr("disabled", true); - } else { - buttonEl.attr("disabled", false); - } - } - var headers = {}; - headers[CommonViewFunction.restCsrfCustomHeader] = CommonViewFunction.restCsrfValue || '""'; - this.ui.importGlossary.dropzone({ - url: that.isGlossary ? UrlLinks.glossaryImportUrl() : UrlLinks.businessMetadataImportUrl(), - clickable: true, - acceptedFiles: ".csv,.xls,.xlsx", - autoProcessQueue: false, - maxFiles: 1, - addRemoveLinks: true, - timeout: 0, - init: function() { - that.dropzone = this; - this.on('addedfile', function(file) { - updateButton(this.files); - }) - this.on('removedfile', function(file) { - updateButton(this.files); - }) - }, - maxfilesexceeded: function(file) { - this.removeAllFiles(); - this.addFile(file); - }, - success: function(file, response, responseObj) { - var success = true; - if (response.failedImportInfoList && response.failedImportInfoList.length) { - var errorStr = '', - notificationMsg = ''; - success = false; - that.ui.errorDetails.empty(); - Utils.defaultErrorHandler(null, file.xhr, { defaultErrorMessage: response.failedImportInfoList[0].remarks }); - if (response.failedImportInfoList.length > 1) { - var modalTitle = '
        '; - _.each(response.failedImportInfoList, function(err_obj) { - errorStr += '
      • ' + _.escape(err_obj.remarks) + '
      • '; - }); - that.ui.errorDetails.append(errorStr); - that.toggleErrorAndDropZoneView({ title: modalTitle, isErrorView: true }); - } - } - if (success) { - that.modal.trigger("cancel"); - Utils.notifySuccess({ - content: "File: " + file.name + " imported successfully" - }); - } - if (that.callback && ((response.successImportInfoList && response.successImportInfoList.length > 0) || success)) { - that.callback(); - } - }, - error: function(file, response, responseObj) { - Utils.defaultErrorHandler(null, responseObj, { defaultErrorMessage: (response.errorMessage) || response }); - that.modal.$el.find("button.ok").attr("disabled", false); - }, - dictDefaultMessage: "Drop files here or click to upload(.csv, .xls, .xlsx).", - headers: headers - }); - }, - toggleErrorAndDropZoneView: function(options) { - var that = this; - if (options) { - that.modal.$el.find('.modal-title').html(options.title); - if (options.isErrorView) { - that.ui.importGlossary.addClass("hide"); - that.ui.errorContainer.removeClass("hide"); - that.modal.$el.find("button.ok").addClass('hide'); - } else { - that.ui.importGlossary.removeClass("hide"); - that.ui.errorContainer.addClass("hide"); - that.modal.$el.find("button.ok").removeClass('hide'); - that.ui.errorDetails.empty(); - } - } - } - } - ); - return ImportLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/migration/MigrationView.js b/dashboardv2/public/js/views/migration/MigrationView.js deleted file mode 100644 index e7000f32a90..00000000000 --- a/dashboardv2/public/js/views/migration/MigrationView.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/migration/MigrationView_tmpl' -], function(require, Backbone, MigrationViewTmpl) { - 'use strict'; - - var ProfileLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends ProfileLayoutView */ - { - _viewName: 'MigrationView', - - template: MigrationViewTmpl, - - /** Layout sub regions */ - regions: { - RStatisticsView: "#r_statisticsView", - }, - /** ui selector cache */ - ui: {}, - /** ui events hash */ - events: function() {}, - /** - * intialize a new ProfileLayoutView Layout - * @constructs - */ - initialize: function(options) { - this.apiBaseUrl = this.getBaseUrl(window.location.pathname); - }, - bindEvents: function() {}, - getBaseUrl: function(url) { - var path = url.replace(/\/[\w-]+.(jsp|html)|\/+$/ig, ''), - splitPath = path.split("/"); - if (splitPath && splitPath[splitPath.length - 1] === "n") { - splitPath.pop(); - return splitPath.join("/"); - } - return path; - }, - onRender: function() { - var that = this; - require(["views/site/Statistics", "collection/VTagList", "utils/UrlLinks"], function(Statistics, VTagList, UrlLinks) { - that.metricCollection = new VTagList(); - that.metricCollection.url = UrlLinks.metricsApiUrl(); - that.metricCollection.modelAttrName = "data"; - that.RStatisticsView.show(new Statistics({ metricCollection: that.metricCollection, isMigrationView: true })); - }) - } - }); - return ProfileLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/profile/ProfileColumnLayoutView.js b/dashboardv2/public/js/views/profile/ProfileColumnLayoutView.js deleted file mode 100644 index 215391d5d8e..00000000000 --- a/dashboardv2/public/js/views/profile/ProfileColumnLayoutView.js +++ /dev/null @@ -1,175 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define([ - "require", - "backbone", - "hbs!tmpl/profile/ProfileColumnLayoutView_tmpl", - "views/graph/ProfileBarChart", - "collection/VProfileList", - "utils/Utils", - "utils/Messages", - "utils/Globals", - "moment", - "models/VEntity", - "d3" -], function(require, Backbone, ProfileColumnLayoutViewTmpl, ProfileBarChart, VProfileList, Utils, Messages, Globals, moment, VEntity, d3) { - "use strict"; - - var ProfileColumnLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends ProfileColumnLayoutView */ - { - _viewName: "ProfileColumnLayoutView", - - template: ProfileColumnLayoutViewTmpl, - - /** Layout sub regions */ - regions: {}, - templateHelpers: function() { - return { - profileData: this.profileData.attributes ? this.profileData.attributes : this.profileData, - entityDetail: this.entityDetail, - typeObject: this.typeObject - }; - }, - /** ui selector cache */ - ui: { - backToYear: '[data-id="backToYear"]' - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.backToYear] = "backToYear"; - return events; - }, - /** - * intialize a new ProfileColumnLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, "profileData", "guid", "entityDetail")); - this.typeObject = Utils.getProfileTabType(this.profileData.attributes); - this.entityModel = new VEntity(); - this.formatValue = d3.format(".0s"); - }, - fetchEntity: function(argument) { - var that = this; - this.entityModel.getEntity(this.entityDetail.table.guid, { - success: function(data) { - var entity = data.entity, - profileData = - entity && entity.attributes && entity.attributes.profileData ? entity.attributes.profileData.attributes : null; - if (profileData && profileData.rowCount) { - that.$(".rowValue").show(); - that.$(".rowValue .graphval").html("" + that.formatValue(profileData.rowCount).replace("G", "B") + ""); - } - if (entity.attributes) { - if (entity.guid) { - that.$(".table_name .graphval").html( - '' + Utils.getName(entity) + "" - ); - } - that.$(".table_created .graphval").html("" + moment(entity.attributes.createTime).format("LL") + ""); - } - } - }); - }, - bindEvents: function() {}, - onRender: function() { - this.fetchEntity(); - if (this.typeObject && this.typeObject.type === "date") { - this.$("svg").addClass("dateType"); - } - }, - onShow: function() { - this.renderGraph(); - }, - renderGraph: function(argument) { - if (!this.typeObject) { - return; - } - var that = this, - profileData = this.profileData.attributes; - this.data = { - key: this.typeObject.label, - values: this.typeObject.actualObj || [] - }; - this.updateGraph(this.data); - }, - backToYear: function() { - this.ui.backToYear.hide(); - this.$(".profileGraphDetail").show(); - this.monthsData = null; - this.updateGraph(this.data); - }, - createMonthData: function(data) { - var monthsKey = { - 1: "Jan", - 2: "Feb", - 3: "Mar", - 4: "Apr", - 5: "May", - 6: "Jun", - 7: "Jul", - 8: "Aug", - 9: "Sep", - 10: "Oct", - 11: "Nov", - 12: "Dec" - }, - i = 1; - - this.monthsData = { - key: this.typeObject.label, - values: [] - }; - - while (i <= 12) { - this.monthsData.values.push({ - value: monthsKey[i], - count: data[i] || 0 - }); - i++; - } - this.ui.backToYear.show(); - this.$(".profileGraphDetail").hide(); - this.updateGraph(this.monthsData); - }, - updateGraph: function(data) { - var that = this; - this.$("svg").empty(); - ProfileBarChart.render({ - el: this.$("svg")[0], - data: data, - xAxisLabel: this.typeObject.xAxisLabel, - yAxisLabel: this.typeObject.yAxisLabel, - formatValue: this.formatValue, - rotateXticks: this.typeObject.type !== "date", - onBarClick: function(e) { - if (that.typeObject.type === "date") { - if (!that.monthsData) { - that.createMonthData(e.monthlyCounts); - } - } - } - }); - } - } - ); - return ProfileColumnLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/profile/ProfileLayoutView.js b/dashboardv2/public/js/views/profile/ProfileLayoutView.js deleted file mode 100644 index cd4eed0b281..00000000000 --- a/dashboardv2/public/js/views/profile/ProfileLayoutView.js +++ /dev/null @@ -1,111 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/profile/ProfileLayoutView_tmpl', - 'collection/VProfileList', - 'utils/Utils', - 'utils/Messages', - 'utils/Globals' -], function(require, Backbone, ProfileLayoutViewTmpl, VProfileList, Utils, Messages, Globals) { - 'use strict'; - - var ProfileLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends ProfileLayoutView */ - { - _viewName: 'ProfileLayoutView', - - template: ProfileLayoutViewTmpl, - - /** Layout sub regions */ - regions: { - RProfileTableOrColumnLayoutView: "#r_profileTableOrColumnLayoutView" - }, - /** ui selector cache */ - ui: {}, - templateHelpers: function() { - return { - profileData: this.profileData ? this.profileData.attributes : this.profileData, - typeName: this.typeName - }; - }, - - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.addTag] = 'checkedValue'; - return events; - }, - /** - * intialize a new ProfileLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'profileData', 'guid', 'value', 'typeName', 'entityDetail', 'typeHeaders', 'entityDefCollection', 'enumDefCollection', 'classificationDefCollection', 'glossaryCollection')); - if (this.typeName === "hive_db" || this.typeName === "hbase_namespace") { - this.profileData = { attributes: true }; - } - }, - bindEvents: function() {}, - onRender: function() { - if (this.profileData) { - if (this.typeName === "hive_table") { - this.renderProfileTableLayoutView(); - } else if (this.typeName === "hive_db" || this.typeName === "hbase_namespace") { - this.renderSearchResultLayoutView(); - } else { - this.renderProfileColumnLayoutView(); - } - } - }, - renderSearchResultLayoutView: function() { - var that = this; - require(['views/search/SearchResultLayoutView'], function(SearchResultLayoutView) { - var value = _.extend({}, that.value, { - 'guid': that.guid, - 'searchType': 'relationship', - 'typeName': that.typeName - }); - that.RProfileTableOrColumnLayoutView.show(new SearchResultLayoutView({ - 'value': value, - 'profileDBView': true, - 'typeHeaders': that.typeHeaders, - 'entityDefCollection': that.entityDefCollection, - 'enumDefCollection': that.enumDefCollection, - 'isTableDropDisable': true, - 'glossaryCollection': that.glossaryCollection, - 'classificationDefCollection': that.classificationDefCollection - })); - }); - }, - renderProfileTableLayoutView: function(tagGuid) { - var that = this; - require(['views/profile/ProfileTableLayoutView'], function(ProfileTableLayoutView) { - that.RProfileTableOrColumnLayoutView.show(new ProfileTableLayoutView(that.options)); - }); - }, - renderProfileColumnLayoutView: function(tagGuid) { - var that = this; - require(['views/profile/ProfileColumnLayoutView'], function(ProfileColumnLayoutView) { - that.RProfileTableOrColumnLayoutView.show(new ProfileColumnLayoutView(that.options)); - }); - }, - }); - return ProfileLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/profile/ProfileTableLayoutView.js b/dashboardv2/public/js/views/profile/ProfileTableLayoutView.js deleted file mode 100644 index 54dabe24755..00000000000 --- a/dashboardv2/public/js/views/profile/ProfileTableLayoutView.js +++ /dev/null @@ -1,352 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/profile/ProfileTableLayoutView_tmpl', - 'collection/VProfileList', - 'utils/Utils', - 'utils/Messages', - 'utils/Globals', - 'moment', - 'utils/UrlLinks', - 'collection/VCommonList', - 'collection/VEntityList', - 'd3', - 'sparkline' -], function(require, Backbone, ProfileTableLayoutViewTmpl, VProfileList, Utils, Messages, Globals, moment, UrlLinks, VCommonList, VEntityList, d3, sparkline) { - 'use strict'; - - var ProfileTableLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends ProfileTableLayoutView */ - { - _viewName: 'ProfileTableLayoutView', - - template: ProfileTableLayoutViewTmpl, - - /** Layout sub regions */ - regions: { - RProfileTableLayoutView: '#r_profileTableLayoutView' - }, - /** ui selector cache */ - ui: {}, - - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.addTag] = 'checkedValue'; - return events; - }, - /** - * intialize a new ProfileTableLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'profileData', 'guid', 'entityDetail')); - var that = this; - this.profileCollection = new VCommonList([], { - comparator: function(item) { - return item.get('position') || 999; - } - }); - - this.bindEvents(); - }, - onRender: function() { - this.fetchEntity(); - }, - fetchEntity: function(argument) { - var that = this; - this.collection = new VEntityList([], {}); - this.collection.url = UrlLinks.entitiesApiUrl({ guid: this.guid, minExtInfo: false }); - this.collection.fetch({ - success: function(response) { - that.entityObject = that.collection.first().toJSON(); - - var collectionJSON = that.entityObject.entity; - that.entityDetail = collectionJSON.attributes; - - Utils.findAndMergeRefEntity({ - attributeObject: collectionJSON.attributes, - referredEntities: that.entityObject.referredEntities - }); - - Utils.findAndMergeRefEntity({ - attributeObject: collectionJSON.relationshipAttributes, - referredEntities: that.entityObject.referredEntities - }); - - var columns = collectionJSON.relationshipAttributes.columns || collectionJSON.attributes.columns, - db = collectionJSON.relationshipAttributes.db || collectionJSON.attributes.db - - that.renderTableLayoutView(); - if (that.entityDetail) { - if (that.guid && that.entityDetail.name) { - that.$('.table_name .graphval').html('' + that.entityDetail.name + ''); - } - if (db) { - that.$('.db_name .graphval').html('' + Utils.getName(db) + ''); - } - var profileData = that.entityDetail.profileData; - if (profileData && profileData.attributes && profileData.attributes.rowCount) { - that.$('.rowValue .graphval').html('' + d3.format("2s")(profileData.attributes.rowCount).replace('G', 'B') + ''); - } - that.$('.table_created .graphval').html('' + (that.entityDetail.createTime ? moment(that.entityDetail.createTime).format("LL") : "--") + ''); - } - - _.each(columns, function(obj) { - if (obj.attributes && obj.attributes.profileData) { - var profileObj = Utils.getProfileTabType(obj.attributes.profileData.attributes, true); - var changeValueObj = {} - if (profileObj && profileObj.type) { - if (profileObj.type === "numeric") { - changeValueObj['averageLength'] = 0; - changeValueObj['maxLength'] = 0; - } - if (profileObj.type === "string") { - changeValueObj['minValue'] = 0; - changeValueObj['maxValue'] = 0; - changeValueObj['meanValue'] = 0; - changeValueObj['medianValue'] = 0; - } - if (profileObj.type === "date") { - changeValueObj['averageLength'] = 0; - changeValueObj['maxLength'] = 0; - changeValueObj['minValue'] = 0; - changeValueObj['maxValue'] = 0; - changeValueObj['meanValue'] = 0; - changeValueObj['medianValue'] = 0; - } - } - - that.profileCollection.fullCollection.add(_.extend({}, obj.attributes, obj.attributes.profileData.attributes, changeValueObj, { guid: obj.guid, position: obj.attributes ? obj.attributes.position : null })); - } - }); - }, - reset: false - }); - }, - bindEvents: function() { - this.listenTo(this.profileCollection, 'backgrid:refresh', function(model, checked) { - this.renderGraphs(); - }, this); - }, - renderTableLayoutView: function() { - var that = this; - require(['utils/TableLayout'], function(TableLayout) { - var cols = new Backgrid.Columns(that.getAuditTableColumns()); - that.RProfileTableLayoutView.show(new TableLayout(_.extend({}, { - columns: cols, - collection: that.profileCollection, - includeFilter: false, - includePagination: true, - includePageSize: false, - includeFooterRecords: true, - gridOpts: { - className: "table table-hover backgrid table-quickMenu", - emptyText: 'No records found!' - } - }))); - that.renderGraphs(); - }); - }, - renderGraphs: function() { - this.$('.sparklines').sparkline('html', { enableTagOptions: true }); - this.$('.sparklines').bind('sparklineClick', function(ev) { - var id = $(ev.target).data().guid; - Utils.setUrl({ - url: '#!/detailPage/' + id, - mergeBrowserUrl: false, - trigger: true, - urlParams: { - tabActive: 'profile' - } - }); - }); - }, - getAuditTableColumns: function() { - var that = this; - return this.profileCollection.constructor.getTableCols({ - name: { - label: "Name", - cell: "Html", - editable: false, - sortable: true, - sortType: 'toggle', - direction: 'ascending', - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return ''; - } - }) - }, - type: { - label: "Type", - cell: "String", - editable: false, - sortable: true, - sortType: 'toggle', - }, - nonNullData: { - label: "% NonNull", - cell: "Html", - editable: false, - sortable: true, - sortType: 'toggle', - width: "180", - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - if (rawValue < 50) { - var barClass = ((rawValue > 30) && (rawValue <= 50)) ? "progress-bar-warning" : "progress-bar-danger"; - } else { - var barClass = "progress-bar-success"; - } - return '
        ' + rawValue + '%
        ' - } - }) - }, - - distributionDecile: { - label: "Distribution", - cell: "Html", - editable: false, - sortable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var sparkarray = []; - var distibutionObj = Utils.getProfileTabType(model.toJSON()); - if (distibutionObj) { - _.each(distibutionObj.actualObj, function(obj) { - sparkarray.push(obj.count); - }) - } - - return '' - } - }) - }, - cardinality: { - label: "Cardinality", - cell: "Number", - editable: false, - sortable: true, - sortType: 'toggle' - }, - minValue: { - label: "Min", - cell: "Number", - editable: false, - sortable: true, - sortType: 'toggle', - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var profileObj = Utils.getProfileTabType(model.toJSON(), true); - if (profileObj && profileObj.type === "numeric") { - return rawValue; - } - return "-"; - } - }) - }, - maxValue: { - label: "Max", - cell: "Number", - editable: false, - sortable: true, - sortType: 'toggle', - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var profileObj = Utils.getProfileTabType(model.toJSON(), true); - if (profileObj && profileObj.type === "numeric") { - return rawValue; - } - return "-"; - } - }) - }, - averageLength: { - label: "Average Length", - cell: "Number", - editable: false, - sortable: true, - sortType: 'toggle', - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var profileObj = Utils.getProfileTabType(model.toJSON(), true); - if (profileObj && profileObj.type === "string") { - return rawValue; - } - return "-"; - } - }) - }, - maxLength: { - label: "Max Length", - cell: "Number", - editable: false, - sortable: true, - sortType: 'toggle', - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var profileObj = Utils.getProfileTabType(model.toJSON(), true); - if (profileObj && profileObj.type === "string") { - return rawValue; - } - return "-"; - } - }) - }, - meanValue: { - label: "Mean", - cell: "Number", - editable: false, - sortable: true, - sortType: 'toggle', - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var profileObj = Utils.getProfileTabType(model.toJSON(), true); - if (profileObj && profileObj.type === "numeric") { - return rawValue; - } - return "-"; - } - }) - }, - medianValue: { - label: "Median", - cell: "Number", - editable: false, - sortable: true, - sortType: 'toggle', - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var profileObj = Utils.getProfileTabType(model.toJSON(), true); - if (profileObj && profileObj.type === "numeric") { - return rawValue; - } - return "-"; - } - }) - } - }, this.profileCollection); - - } - - }); - return ProfileTableLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/schema/SchemaLayoutView.js b/dashboardv2/public/js/views/schema/SchemaLayoutView.js deleted file mode 100644 index ab776e9cf5e..00000000000 --- a/dashboardv2/public/js/views/schema/SchemaLayoutView.js +++ /dev/null @@ -1,312 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/schema/SchemaTableLayoutView_tmpl', - 'collection/VSchemaList', - 'utils/Utils', - 'utils/CommonViewFunction', - 'utils/Messages', - 'utils/Globals', - 'utils/Enums', - 'utils/UrlLinks' -], function(require, Backbone, SchemaTableLayoutViewTmpl, VSchemaList, Utils, CommonViewFunction, Messages, Globals, Enums, UrlLinks) { - 'use strict'; - - var SchemaTableLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends SchemaTableLayoutView */ - { - _viewName: 'SchemaTableLayoutView', - - template: SchemaTableLayoutViewTmpl, - - /** Layout sub regions */ - regions: { - RSchemaTableLayoutView: "#r_schemaTableLayoutView", - }, - /** ui selector cache */ - ui: { - tagClick: '[data-id="tagClick"]', - addTag: "[data-id='addTag']", - addAssignTag: "[data-id='addAssignTag']", - checkDeletedEntity: "[data-id='checkDeletedEntity']" - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.addTag] = 'checkedValue'; - events["click " + this.ui.addAssignTag] = 'checkedValue'; - events["click " + this.ui.tagClick] = function(e) { - if (e.target.nodeName.toLocaleLowerCase() == "i") { - this.onClickTagCross(e); - } else { - var value = e.currentTarget.text; - Utils.setUrl({ - url: '#!/tag/tagAttribute/' + value, - mergeBrowserUrl: false, - trigger: true - }); - } - }; - events["click " + this.ui.checkDeletedEntity] = 'onCheckDeletedEntity'; - - return events; - }, - /** - * intialize a new SchemaTableLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'guid', 'classificationDefCollection', 'entityDefCollection', 'attribute', 'fetchCollection', 'enumDefCollection')); - this.schemaCollection = new VSchemaList([], {}); - this.commonTableOptions = { - collection: this.schemaCollection, - includeFilter: false, - includePagination: true, - includePageSize: true, - includeGotoPage: true, - includeFooterRecords: true, - includeOrderAbleColumns: false, - includeAtlasTableSorting: true, - gridOpts: { - className: "table table-hover backgrid table-quickMenu", - emptyText: 'No records found!' - }, - filterOpts: {}, - paginatorOpts: {} - }; - this.bindEvents(); - this.bradCrumbList = []; - }, - bindEvents: function() { - var that = this; - this.listenTo(this.schemaCollection, 'backgrid:selected', function(model, checked) { - this.arr = []; - if (checked === true) { - model.set("isEnable", true); - } else { - model.set("isEnable", false); - } - this.schemaCollection.find(function(item) { - var obj = item.toJSON(); - if (item.get('isEnable')) { - that.arr.push({ - id: obj.guid, - model: obj - }); - } - }); - if (this.arr.length > 0) { - this.$('.multiSelectTag').show(); - } else { - this.$('.multiSelectTag').hide(); - } - }); - }, - onRender: function() { - this.generateTableData(); - }, - generateTableData: function(checkedDelete) { - var that = this, - newModel; - this.activeObj = []; - this.deleteObj = []; - this.schemaTableAttribute = null; - if (this.attribute && this.attribute[0]) { - var firstColumn = this.attribute[0], - defObj = that.entityDefCollection.fullCollection.find({ name: firstColumn.typeName }); - if (defObj && defObj.get('options') && defObj.get('options').schemaAttributes) { - if (firstColumn) { - try { - var mapObj = JSON.parse(defObj.get('options').schemaAttributes); - that.schemaTableAttribute = _.pick(firstColumn.attributes, mapObj); - } catch (e) {} - } - } - } - _.each(this.attribute, function(obj) { - if (!Enums.entityStateReadOnly[obj.status]) { - that.activeObj.push(obj); - that.schemaCollection.push(obj); - } else if (Enums.entityStateReadOnly[obj.status]) { - that.deleteObj.push(obj); - } - }); - if (this.schemaCollection.length === 0 && this.deleteObj.length) { - this.ui.checkDeletedEntity.find("input").prop('checked', true); - this.schemaCollection.fullCollection.reset(this.deleteObj); - } - if (this.activeObj.length === 0 && this.deleteObj.length === 0) { - this.ui.checkDeletedEntity.hide(); - } - this.renderTableLayoutView(); - }, - showLoader: function() { - this.$('.fontLoader').show(); - this.$('.tableOverlay').show() - }, - hideLoader: function(argument) { - this.$('.fontLoader').hide(); - this.$('.tableOverlay').hide(); - }, - renderTableLayoutView: function() { - var that = this; - require(['utils/TableLayout'], function(TableLayout) { - var columnCollection = Backgrid.Columns.extend({}), - columns = new columnCollection(that.getSchemaTableColumns()); - that.RSchemaTableLayoutView.show(new TableLayout(_.extend({}, that.commonTableOptions, { - columns: columns - }))); - that.$('.multiSelectTag').hide(); - Utils.generatePopover({ - el: that.$('[data-id="showMoreLess"]'), - contentClass: 'popover-tag-term', - viewFixedPopover: true, - popoverOptions: { - container: null, - content: function() { - return $(this).find('.popup-tag-term').children().clone(); - } - } - }); - }); - }, - getSchemaTableColumns: function() { - var that = this, - col = { - Check: { - name: "selected", - label: "", - cell: "select-row", - headerCell: "select-all" - } - } - if (this.schemaTableAttribute) { - _.each(_.keys(this.schemaTableAttribute), function(key) { - if (key !== "position") { - col[key] = { - label: key.capitalize(), - cell: "html", - editable: false, - className: "searchTableName", - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var value = _.escape(model.get('attributes')[key]); - if (key === "name" && model.get('guid')) { - var nameHtml = '' + value + ''; - if (model.get('status') && Enums.entityStateReadOnly[model.get('status')]) { - nameHtml += ''; - return ''; - } else { - return nameHtml; - } - } else { - return value - } - } - }) - }; - } - }); - col['tag'] = { - label: "Classifications", - cell: "Html", - editable: false, - sortable: false, - className: 'searchTag', - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var obj = model.toJSON(); - if (obj.status && Enums.entityStateReadOnly[obj.status]) { - return '
        ' + CommonViewFunction.tagForTable(obj); + '
        '; - } else { - return CommonViewFunction.tagForTable(obj); - } - } - }) - }; - return this.schemaCollection.constructor.getTableCols(col, this.schemaCollection); - } - - }, - checkedValue: function(e) { - if (e) { - e.stopPropagation(); - } - var guid = "", - that = this, - isTagMultiSelect = $(e.currentTarget).hasClass('multiSelectTag'); - if (isTagMultiSelect && this.arr && this.arr.length) { - that.addTagModalView(guid, this.arr); - } else { - guid = that.$(e.currentTarget).data("guid"); - that.addTagModalView(guid); - } - }, - addTagModalView: function(guid, multiple) { - var that = this; - var tagList = that.schemaCollection.find({ 'guid': guid }); - require(['views/tag/AddTagModalView'], function(AddTagModalView) { - var view = new AddTagModalView({ - guid: guid, - multiple: multiple, - tagList: _.map((tagList ? tagList.get('classifications') : []), function(obj) { - return obj.typeName; - }), - callback: function() { - that.fetchCollection(); - that.arr = []; - }, - hideLoader: that.hideLoader.bind(that), - showLoader: that.showLoader.bind(that), - collection: that.classificationDefCollection, - enumDefCollection: that.enumDefCollection - }); - }); - }, - onClickTagCross: function(e) { - var that = this, - tagName = $(e.target).data("name"), - guid = $(e.target).data("guid"), - assetName = $(e.target).data("assetname"); - CommonViewFunction.deleteTag({ - tagName: tagName, - guid: guid, - msg: "
        Remove: " + "" + _.escape(tagName) + " assignment from " + _.escape(assetName) + " ?
        ", - titleMessage: Messages.removeTag, - okText: "Remove", - showLoader: that.showLoader.bind(that), - hideLoader: that.hideLoader.bind(that), - callback: function() { - that.fetchCollection(); - } - }); - }, - onCheckDeletedEntity: function(e) { - if (e.target.checked) { - if (this.deleteObj.length) { - this.schemaCollection.fullCollection.reset(this.activeObj.concat(this.deleteObj)); - } - } else { - this.schemaCollection.fullCollection.reset(this.activeObj) - } - } - }); - return SchemaTableLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/search/AdvancedSearchInfoView.js b/dashboardv2/public/js/views/search/AdvancedSearchInfoView.js deleted file mode 100644 index 053e2d04189..00000000000 --- a/dashboardv2/public/js/views/search/AdvancedSearchInfoView.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/search/AdvancedSearchInfo_tmpl', -], function(require, Backbone, AdvancedSearchInfoTmpl) { - - var AdvancedSearchInfoView = Backbone.Marionette.LayoutView.extend( - /** @lends AdvancedSearchInfoView */ - { - _viewName: 'AdvancedSearchInfoView', - - template: AdvancedSearchInfoTmpl, - - - - /** Layout sub regions */ - regions: {}, - - - /** ui selector cache */ - ui: { - - }, - /** ui events hash */ - events: function() { - var events = {}; - return events; - }, - /** - * intialize a new AdvancedSearchInfoView Layout - * @constructs - */ - initialize: function(options) { - - }, - bindEvents: function() {}, - onRender: function() { - - }, - - - }); - return AdvancedSearchInfoView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/search/QueryBuilderView.js b/dashboardv2/public/js/views/search/QueryBuilderView.js deleted file mode 100644 index 38a4c34598a..00000000000 --- a/dashboardv2/public/js/views/search/QueryBuilderView.js +++ /dev/null @@ -1,573 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/search/QueryBuilder_tmpl', - 'hbs!tmpl/search/UserDefine_tmpl', - 'utils/Utils', - 'utils/CommonViewFunction', - 'utils/Enums', - 'utils/Globals', - 'moment', - 'query-builder', - 'daterangepicker' -], function(require, Backbone, QueryBuilderTmpl, UserDefineTmpl, Utils, CommonViewFunction, Enums, Globals, moment) { - - var QueryBuilderView = Backbone.Marionette.LayoutView.extend( - /** @lends QueryBuilderView */ - { - _viewName: 'QueryBuilderView', - - template: QueryBuilderTmpl, - - - - /** Layout sub regions */ - regions: {}, - - - /** ui selector cache */ - ui: { - "builder": "#builder" - }, - /** ui events hash */ - events: function() { - var events = {}; - return events; - }, - /** - * intialize a new QueryBuilderView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'attrObj', 'value', 'typeHeaders', 'entityDefCollection', 'enumDefCollection', 'classificationDefCollection', 'businessMetadataDefCollection', 'tag', 'type', 'searchTableFilters', 'systemAttrArr', 'adminAttrFilters')); - this.attrObj = _.sortBy(this.attrObj, 'name'); - this.filterType = this.tag ? 'tagFilters' : 'entityFilters'; - this.defaultRange = "Last 7 Days"; - this.dateRangesMap = { - 'Today': [moment(), moment()], - 'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')], - 'Last 7 Days': [moment().subtract(6, 'days'), moment()], - 'Last 30 Days': [moment().subtract(29, 'days'), moment()], - 'This Month': [moment().startOf('month'), moment().endOf('month')], - 'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')], - 'Last 3 Months': [moment().subtract(3, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')], - 'Last 6 Months': [moment().subtract(6, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')], - 'Last 12 Months': [moment().subtract(12, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')], - 'This Quarter': [moment().startOf('quarter'), moment().endOf('quarter')], - 'Last Quarter': [moment().subtract(1, 'quarter').startOf('quarter'), moment().subtract(1, 'quarter').endOf('quarter')], - 'This Year': [moment().startOf('year'), moment().endOf('year')], - 'Last Year': [moment().subtract(1, 'year').startOf('year'), moment().subtract(1, 'year').endOf('year')] - } - }, - bindEvents: function() {}, - getOperator: function(type, skipDefault) { - var obj = { - operators: null - } - if (type === "string") { - obj.operators = ['=', '!=', 'contains', 'begins_with', 'ends_with']; - if (this.adminAttrFilters) { - obj.operators = obj.operators.concat(['like', 'in']); - } - } - if (type === "date") { - obj.operators = ['=', '!=', '>', '<', '>=', '<=', 'TIME_RANGE']; - } - if (type === "int" || type === "byte" || type === "short" || type === "long" || type === "float" || type === "double") { - obj.operators = ['=', '!=', '>', '<', '>=', '<=']; - } - if (type === "enum" || type === "boolean") { - obj.operators = ['=', '!=']; - } - if (_.isEmpty(skipDefault) && obj.operators) { - obj.operators = obj.operators.concat(['is_null', 'not_null']); - } - return obj; - }, - isPrimitive: function(type) { - if (type === "int" || type === "byte" || type === "short" || type === "long" || type === "float" || type === "double" || type === "string" || type === "boolean" || type === "date") { - return true; - } - return false; - }, - getUserDefineInput: function() { - return UserDefineTmpl(); - }, - getObjDef: function(attrObj, rules, isGroup, groupType, isSystemAttr) { - var that = this; - if (attrObj.name === "__classificationsText" || attrObj.name === "__historicalGuids") { - return; - } - var getLableWithType = function(label, name) { - if (name === "__classificationNames" || name === "__customAttributes" || name === "__labels" || name === "__propagatedClassificationNames") { - return label; - } else { - return label + " (" + attrObj.typeName + ")"; - } - - } - var label = (Enums.systemAttributes[attrObj.name] ? Enums.systemAttributes[attrObj.name] : _.escape(attrObj.name.capitalize())); - var obj = { - id: attrObj.name, - label: getLableWithType(label, attrObj.name), - plainLabel: label, - type: _.escape(attrObj.typeName), - validation: { - callback: function(value, rule) { - if (rule.operator.nb_inputs === false || !_.isEmpty(value) || !value instanceof Error) { - return true; - } else { - if (value instanceof Error) { - return value.message; // with params - } else { - return rule.filter.plainLabel + ' is required'; // with params - } - } - } - } - }; - if (isGroup) { - obj.optgroup = groupType; - } - /* __isIncomplete / IsIncomplete */ - if (isSystemAttr && attrObj.name === "__isIncomplete" || isSystemAttr && attrObj.name === "IsIncomplete") { - obj.type = "boolean"; - obj.label = (Enums.systemAttributes[attrObj.name] ? Enums.systemAttributes[attrObj.name] : _.escape(attrObj.name.capitalize())) + " (boolean)"; - obj['input'] = 'select'; - obj['values'] = [{ 1: 'true' }, { 0: 'false' }]; - _.extend(obj, this.getOperator("boolean")); - return obj; - } - /* Status / __state */ - if (isSystemAttr && attrObj.name === "Status" || isSystemAttr && attrObj.name === "__state" || isSystemAttr && attrObj.name === "__entityStatus") { - obj.label = (Enums.systemAttributes[attrObj.name] ? Enums.systemAttributes[attrObj.name] : _.escape(attrObj.name.capitalize())) + " (enum)"; - obj['input'] = 'select'; - obj['values'] = ['ACTIVE', 'DELETED']; - _.extend(obj, this.getOperator("boolean", true)); - return obj; - } - /* __classificationNames / __propagatedClassificationNames */ - if (isSystemAttr && attrObj.name === "__classificationNames" || attrObj.name === "__propagatedClassificationNames") { - obj["plugin"] = "select2"; - obj["input"] = 'select'; - obj["plugin_config"] = { - placeholder: "Select classfication", - tags: true, - multiple: false, - data: this.classificationDefCollection.fullCollection.models.map(function(o) { return { "id": o.get("name"), "text": o.get("name") } }) - }; - obj["valueSetter"] = function(rule) { - if (rule && !_.isEmpty(rule.value)) { - var selectEl = rule.$el.find('.rule-value-container select') - var valFound = that.classificationDefCollection.fullCollection.find(function(o) { - return o.get("name") === rule.value - }) - if (valFound) { - selectEl.val(rule.value).trigger("change"); - } else { - var newOption = new Option(rule.value, rule.value, false, false); - selectEl.append(newOption).val(rule.value); - } - } - }; - _.extend(obj, this.getOperator("string")); - return obj; - } - /* __customAttributes */ - if (isSystemAttr && attrObj.name === "__customAttributes") { - obj["input"] = function(rule) { - return (rule && rule.operator && rule.operator.nb_inputs) ? that.getUserDefineInput() : null - } - obj["valueGetter"] = function(rule) { - if (rule && rule.operator && rule.operator.type === "contains") { - var $el = rule.$el.find('.rule-value-container'), - key = $el.find("[data-type='key']").val(), - val = $el.find("[data-type='value']").val(); - if (!_.isEmpty(key) && !_.isEmpty(val)) { - return key + "=" + val; - } else { - return new Error("Key & Value is Required"); - } - } else { - return [] // in CommonviewFunction.js value is set to "" for object; - } - } - obj["valueSetter"] = function(rule) { - if (rule && !rule.$el.hasClass("user-define")) { - rule.$el.addClass("user-define"); - } - if (rule && rule.value && rule.value.length && !(rule.value instanceof Error)) { - var $el = rule.$el.find('.rule-value-container'), - value = rule.value.split("="); - if (value) { - $el.find("[data-type='key']").val(value[0]), - $el.find("[data-type='value']").val(value[1]); - } - } - } - obj.operators = ['contains', 'is_null', 'not_null']; - return obj; - } - /* __typeName */ - if (isSystemAttr && attrObj.name === "__typeName") { - var entityType = []; - that.typeHeaders.fullCollection.each(function(model) { - if ((that.type == true && model.get('category') == 'ENTITY') || (that.tag == true && model.get('category') == "CLASSIFICATION")) { - entityType.push({ - "id": model.get("name"), - "text": model.get("name") - }) - } - }); - obj["plugin"] = "select2"; - obj["input"] = 'select'; - obj["plugin_config"] = { - placeholder: "Select type", - tags: true, - multiple: false, - data: entityType - }; - obj["valueSetter"] = function(rule) { - if (rule && !_.isEmpty(rule.value)) { - var selectEl = rule.$el.find('.rule-value-container select') - var valFound = that.typeHeaders.fullCollection.find(function(o) { - return o.get("name") === rule.value - }) - if (valFound) { - selectEl.val(rule.value).trigger("change"); - } else { - var newOption = new Option(rule.value, rule.value, false, false); - selectEl.append(newOption).val(rule.value); - } - } - }; - _.extend(obj, this.getOperator("string")); - return obj; - } - if (obj.type === "date") { - obj['plugin'] = 'daterangepicker'; - obj['plugin_config'] = this.getDateConfig(rules, obj.id); - _.extend(obj, this.getOperator(obj.type)); - return obj; - } - - if (this.isPrimitive(obj.type)) { - if (obj.type === "boolean") { - obj['input'] = 'select'; - obj['values'] = ['true', 'false']; - } - _.extend(obj, this.getOperator(obj.type, false)); - if (_.has(Enums.regex.RANGE_CHECK, obj.type)) { - obj.validation = { - min: Enums.regex.RANGE_CHECK[obj.type].min, - max: Enums.regex.RANGE_CHECK[obj.type].max - }; - if (obj.type === "double" || obj.type === "float") { - obj.type = "double"; - } else if (obj.type === "int" || obj.type === "byte" || obj.type === "short" || obj.type === "long") { - obj.type = "integer" - } - } - return obj; - } - var enumObj = this.enumDefCollection.fullCollection.find({ name: obj.type }); - if (enumObj) { - obj.type = "string"; - obj['input'] = 'select'; - var value = []; - _.each(enumObj.get('elementDefs'), function(o) { - value.push(o.value) - }) - obj['values'] = value; - _.extend(obj, this.getOperator('enum')); - return obj; - } - }, - getDateConfig: function(ruleObj, id, operator) { - var valueObj = ruleObj ? (_.find(ruleObj.rules, { id: id }) || {}) : {}, - isTimeRange = (valueObj.operator && valueObj.operator === "TIME_RANGE" && operator === "TIME_RANGE") || (operator === "TIME_RANGE"), - obj = { - opens: "center", - autoApply: true, - autoUpdateInput: false, - timePickerSeconds: true, - timePicker: true, - locale: { - format: Globals.dateTimeFormat - } - }; - - if (isTimeRange) { - var defaultRangeDate = this.dateRangesMap[this.defaultRange]; - obj.startDate = defaultRangeDate[0]; - obj.endDate = defaultRangeDate[1]; - obj.singleDatePicker = false; - obj.ranges = this.dateRangesMap; - } else { - obj.singleDatePicker = true; - obj.startDate = moment(); - obj.endDate = obj.startDate; - } - - if (!_.isEmpty(valueObj) && operator === valueObj.operator) { - if (isTimeRange) { - if (valueObj.value.indexOf("-") > -1) { - var dates = valueObj.value.split("-"); - obj.startDate = dates[0].trim(); - obj.endDate = dates[1].trim(); - } else { - var dates = this.dateRangesMap[valueObj.value] - obj.startDate = dates[0]; - obj.endDate = dates[1]; - } - obj.singleDatePicker = false; - } else { - obj.startDate = moment(Date.parse(valueObj.value)); - obj.endDate = obj.startDate; - obj.singleDatePicker = true; - } - } - - return obj; - }, - setDateValue: function(rule, rules_widgets) { - if (rule.filter.type === "date" && rule.operator.nb_inputs) { - var inputEl = rule.$el.find(".rule-value-container").find("input"), - datepickerEl = rule.$el.find(".rule-value-container").find("input").data("daterangepicker") - inputEl.attr('readonly', true); - if (datepickerEl) { - datepickerEl.remove(); - var configObj = this.getDateConfig(rules_widgets, rule.filter.id, rule.operator.type) - inputEl.daterangepicker(configObj); - if (rule.operator.type === "TIME_RANGE") { - rule.value = this.defaultRange; - } else { - rule.value = configObj.startDate.format(Globals.dateTimeFormat); - } - inputEl.on('apply.daterangepicker', function(ev, picker) { - picker.setStartDate(picker.startDate); - picker.setEndDate(picker.endDate); - var valueString = ""; - if (picker.chosenLabel) { - if (picker.chosenLabel === "Custom Range") { - valueString = picker.startDate.format(Globals.dateTimeFormat) + " - " + picker.endDate.format(Globals.dateTimeFormat); - } else { - valueString = picker.chosenLabel; - } - } else { - valueString = picker.startDate.format(Globals.dateTimeFormat); - } - picker.element.val(valueString); - rule.value = valueString; - }); - } - } - }, - onRender: function() { - var that = this, - filters = [], - isGroupView = true, - placeHolder = '--Select Attribute--'; - var rules_widgets = null; - if (this.adminAttrFilters) { - var entityDef = this.entityDefCollection.fullCollection.find({ name: "__AtlasAuditEntry" }), - auditEntryAttributeDefs = null; - if (entityDef) { - auditEntryAttributeDefs = $.extend(true, {}, entityDef.get("attributeDefs")) || null; - } - if (auditEntryAttributeDefs) { - _.each(auditEntryAttributeDefs, function(attributes) { - var returnObj = that.getObjDef(attributes, rules_widgets); - if (returnObj) { - filters.push(returnObj); - } - }); - } - rules_widgets = CommonViewFunction.attributeFilter.extractUrl({ "value": this.searchTableFilters ? this.searchTableFilters["adminAttrFilters"] : null, "formatDate": true });; - } else { - if (this.value) { - rules_widgets = CommonViewFunction.attributeFilter.extractUrl({ "value": this.searchTableFilters[this.filterType][(this.tag ? this.value.tag : this.value.type)], "formatDate": true }); - } - _.each(this.attrObj, function(obj) { - var type = that.tag ? that.value.tag : that.value.type; - var returnObj = that.getObjDef(obj, rules_widgets, isGroupView, (type + ' Attribute')); - if (returnObj) { - filters.push(returnObj); - } - }); - var sortMap = { - "__guid": 1, - "__typeName": 2, - "__timestamp": 3, - "__modificationTimestamp": 4, - "__createdBy": 5, - "__modifiedBy": 6, - "__isIncomplete": 7, - "__classificationNames": 9, - "__propagatedClassificationNames": 10, - "__labels": 11, - "__customAttributes": 12, - } - if (that.type) { - sortMap["__state"] = 8; - } else { - sortMap["__entityStatus"] = 8; - } - this.systemAttrArr = _.sortBy(this.systemAttrArr, function(obj) { - return sortMap[obj.name] - }) - _.each(this.systemAttrArr, function(obj) { - var returnObj = that.getObjDef(obj, rules_widgets, isGroupView, 'System Attribute', true); - if (returnObj) { - filters.push(returnObj); - } - }); - if (this.type) { - var pushBusinessMetadataFilter = function(sortedAttributes, businessMetadataKey) { - _.each(sortedAttributes, function(attrDetails) { - var returnObj = that.getObjDef(attrDetails, rules_widgets, isGroupView, "Business Attributes: " + businessMetadataKey); - if (returnObj) { - returnObj.id = businessMetadataKey + "." + returnObj.id; - returnObj.label = returnObj.label; - returnObj.data = { 'entityType': "businessMetadata" }; - filters.push(returnObj); - } - }); - }; - if (this.value.type == "_ALL_ENTITY_TYPES") { - this.businessMetadataDefCollection.each(function(model) { - var sortedAttributes = model.get('attributeDefs'); - sortedAttributes = _.sortBy(sortedAttributes, function(obj) { - return obj.name; - }); - pushBusinessMetadataFilter(sortedAttributes, model.get('name')); - }) - - } else { - var entityDef = this.entityDefCollection.fullCollection.find({ name: this.value.type }), - businessMetadataAttributeDefs = null; - if (entityDef) { - businessMetadataAttributeDefs = entityDef.get("businessAttributeDefs"); - } - if (businessMetadataAttributeDefs) { - _.each(businessMetadataAttributeDefs, function(attributes, key) { - var sortedAttributes = _.sortBy(attributes, function(obj) { - return obj.name; - }); - pushBusinessMetadataFilter(sortedAttributes, key); - }); - } - } - } - } - filters = _.uniq(filters, 'id'); - if (filters && !_.isEmpty(filters)) { - this.ui.builder.off() - .on("afterUpdateRuleOperator.queryBuilder", function(e, rule) { - that.setDateValue(rule, rules_widgets); - }) - .queryBuilder({ - plugins: ['bt-tooltip-errors'], - filters: filters, - select_placeholder: placeHolder, - allow_empty: true, - conditions: ['AND', 'OR'], - allow_groups: true, - allow_empty: true, - templates: { - rule: '
        \ -
        \ -
        \ -
        \ -
        \ -
        \ - \ -
        \ -
        \ - {{? it.settings.display_errors }} \ -
         
        \ - {{?}} \ -
        ' - }, - operators: [ - { type: '=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, - { type: '!=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, - { type: '>', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, - { type: '<', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, - { type: '>=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, - { type: '<=', nb_inputs: 1, multiple: false, apply_to: ['number', 'string', 'boolean'] }, - { type: 'contains', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'like', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'in', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'begins_with', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'ends_with', nb_inputs: 1, multiple: false, apply_to: ['string'] }, - { type: 'is_null', nb_inputs: false, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, - { type: 'not_null', nb_inputs: false, multiple: false, apply_to: ['number', 'string', 'boolean', 'enum'] }, - { type: 'TIME_RANGE', nb_inputs: 1, multiple: false, apply_to: ['date'] } - ], - lang: { - add_rule: 'Add filter', - add_group: 'Add filter group', - operators: { - not_null: 'is not null', - TIME_RANGE: "Time Range" - } - }, - icons: { - add_rule: 'fa fa-plus', - remove_rule: 'fa fa-times', - error: 'fa fa-exclamation-triangle' - }, - rules: rules_widgets - }) - .on("afterCreateRuleInput.queryBuilder", function(e, rule) { - rule.error = null; - if (rule.operator.nb_inputs && rule.filter.id === "__customAttributes") { - rule.$el.addClass("user-define"); - } else if (rule.$el.hasClass("user-define")) { - rule.$el.removeClass("user-define"); - } - if (rule.filter.type === "date") { - rule.$el.find('.rule-value-container >input').attr('readonly', true) - } - that.setDateValue(rule, rules_widgets); - }) - .on('validationError.queryBuilder', function(e, rule, error, value) { - // never display error for my custom filter - var errorMsg = error[0]; - if (that.queryBuilderLang && that.queryBuilderLang.errors && that.queryBuilderLang.errors[errorMsg]) { - errorMsg = that.queryBuilderLang.errors[errorMsg]; - } - rule.$el.find(".error-container span").html(errorMsg); - }); - var queryBuilderEl = that.ui.builder.data("queryBuilder"); - if (queryBuilderEl && queryBuilderEl.lang) { - this.queryBuilderLang = queryBuilderEl.lang; - } - this.$('.rules-group-header .btn-group.pull-right.group-actions').toggleClass('pull-left'); - } else { - this.ui.builder.html('

        No Attributes are available !

        ') - } - } - }); - return QueryBuilderView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/search/SearchDetailLayoutView.js b/dashboardv2/public/js/views/search/SearchDetailLayoutView.js deleted file mode 100644 index 7ab60ecdb13..00000000000 --- a/dashboardv2/public/js/views/search/SearchDetailLayoutView.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/search/SearchDetailLayoutView_tmpl', -], function(require, Backbone, SearchDetailLayoutViewTmpl) { - 'use strict'; - - var SearchDetailLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends SearchDetailLayoutView */ - { - _viewName: 'SearchDetailLayoutView', - - template: SearchDetailLayoutViewTmpl, - - /** Layout sub regions */ - regions: { - RSearchResultLayoutView: "#r_searchResultLayoutView" - }, - - /** ui selector cache */ - ui: {}, - /** ui events hash */ - events: function() {}, - /** - * intialize a new SearchDetailLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'value', 'initialView', 'classificationDefCollection', 'entityDefCollection', 'typeHeaders', 'searchVent', 'enumDefCollection', 'searchTableColumns')); - }, - bindEvents: function() {}, - onRender: function() { - this.renderSearchResultLayoutView(); - }, - renderSearchResultLayoutView: function() { - var that = this; - require(['views/search/SearchResultLayoutView'], function(SearchResultLayoutView) { - if (that.RSearchResultLayoutView) { - that.RSearchResultLayoutView.show(new SearchResultLayoutView(that.options)); - } - }); - } - }); - return SearchDetailLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/search/SearchLayoutView.js b/dashboardv2/public/js/views/search/SearchLayoutView.js deleted file mode 100644 index 714e47bf8f8..00000000000 --- a/dashboardv2/public/js/views/search/SearchLayoutView.js +++ /dev/null @@ -1,887 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -define(['require', - 'backbone', - 'hbs!tmpl/search/SearchLayoutView_tmpl', - 'utils/Utils', - 'utils/UrlLinks', - 'utils/Globals', - 'utils/Enums', - 'collection/VSearchList', - 'utils/CommonViewFunction', - 'modules/Modal' -], function(require, Backbone, SearchLayoutViewTmpl, Utils, UrlLinks, Globals, Enums, VSearchList, CommonViewFunction, Modal) { - 'use strict'; - - var SearchLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends SearchLayoutView */ - { - _viewName: 'SearchLayoutView', - - template: SearchLayoutViewTmpl, - - /** Layout sub regions */ - regions: { - RSaveSearchBasic: "[data-id='r_saveSearchBasic']", - RSaveSearchAdvance: "[data-id='r_saveSearchAdvance']" - }, - - /** ui selector cache */ - ui: { - searchInput: '[data-id="searchInput"]', - searchType: 'input[name="queryType"]', - searchBtn: '[data-id="searchBtn"]', - clearSearch: '[data-id="clearSearch"]', - typeLov: '[data-id="typeLOV"]', - tagLov: '[data-id="tagLOV"]', - termLov: '[data-id="termLOV"]', - refreshBtn: '[data-id="refreshBtn"]', - advancedInfoBtn: '[data-id="advancedInfo"]', - typeAttrFilter: '[data-id="typeAttrFilter"]', - tagAttrFilter: '[data-id="tagAttrFilter"]' - }, - - /** ui events hash */ - events: function() { - var events = {}, - that = this; - events["keyup " + this.ui.searchInput] = function(e) { - var code = e.which; - this.value.query = e.currentTarget.value; - this.query[this.type].query = this.value.query; - if (code == 13) { - that.findSearchResult(); - } - this.checkForButtonVisiblity(); - }; - events["change " + this.ui.searchType] = 'dslFulltextToggle'; - events["click " + this.ui.searchBtn] = 'findSearchResult'; - events["click " + this.ui.clearSearch] = 'clearSearchData'; - events["change " + this.ui.typeLov] = 'checkForButtonVisiblity'; - events["change " + this.ui.tagLov] = 'checkForButtonVisiblity'; - events["change " + this.ui.termLov] = 'checkForButtonVisiblity'; - events["click " + this.ui.refreshBtn] = 'onRefreshButton'; - events["click " + this.ui.advancedInfoBtn] = 'advancedInfo'; - events["click " + this.ui.typeAttrFilter] = function() { - this.openAttrFilter('type'); - }; - events["click " + this.ui.tagAttrFilter] = function() { - this.openAttrFilter('tag'); - }; - return events; - }, - /** - * intialize a new SearchLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'value', 'typeHeaders', 'searchVent', 'entityDefCollection', 'enumDefCollection', 'classificationDefCollection', 'businessMetadataDefCollection', 'searchTableColumns', 'searchTableFilters', 'metricCollection', 'classificationAndMetricEvent')); - this.type = "basic"; - this.entityCountObj = _.first(this.metricCollection.toJSON()) || { entity: { entityActive: {}, entityDeleted: {} }, tag: { tagEntities: {} } }; - this.selectedFilter = { - 'basic': [], - 'dsl': [] - }; - this.filterTypeSelected = null; - var param = Utils.getUrlState.getQueryParams(); - this.query = { - dsl: { - query: this.value ? this.value.query : null, - type: this.value ? this.value.type : null, - pageOffset: this.value ? this.value.pageOffset : null, - pageLimit: this.value ? this.value.pageLimit : null - }, - basic: { - query: this.value ? this.value.query : null, - type: this.value ? this.value.type : null, - tag: this.value ? this.value.tag : null, - term: this.value ? this.value.term : null, - attributes: this.value ? this.value.attributes : null, - tagFilters: this.value ? this.value.tagFilters : null, - pageOffset: this.value ? this.value.pageOffset : null, - pageLimit: this.value ? this.value.pageLimit : null, - entityFilters: this.value ? this.value.entityFilters : null, - includeDE: this.value ? this.value.includeDE : null, - excludeST: this.value ? this.value.excludeST : null, - excludeSC: this.value ? this.value.excludeSC : null - } - }; - if (!this.value) { - this.value = {}; - } - this.dsl = false; - if (param && param.searchType) { - this.type = param.searchType; - this.updateQueryObject(param); - } - if ((this.value && this.value.type) || (this.value && this.value.tag && this.value.searchType === "basic")) { - this.setInitialEntityVal = false; - } else { - this.setInitialEntityVal = true; - } - this.tagEntityCheck = false; - this.typeEntityCheck = false; - this.bindEvents(); - }, - renderSaveSearch: function() { - var that = this; - require(['views/search/save/SaveSearchView'], function(SaveSearchView) { - var saveSearchBaiscCollection = new VSearchList(), - saveSearchAdvanceCollection = new VSearchList(), - saveSearchCollection = new VSearchList(); - saveSearchCollection.url = UrlLinks.saveSearchApiUrl(); - saveSearchBaiscCollection.fullCollection.comparator = function(model) { - return model.get('name').toLowerCase(); - } - saveSearchAdvanceCollection.fullCollection.comparator = function(model) { - return model.get('name').toLowerCase(); - } - var obj = { - value: that.value, - searchVent: that.searchVent, - typeHeaders: that.typeHeaders, - fetchCollection: fetchSaveSearchCollection, - classificationDefCollection: that.classificationDefCollection, - entityDefCollection: that.entityDefCollection, - getValue: function() { - var queryObj = that.query[that.type], - entityObj = that.searchTableFilters['entityFilters'], - tagObj = that.searchTableFilters['tagFilters'], - urlObj = Utils.getUrlState.getQueryParams(); - if (urlObj) { - // includeDE value in because we need to send "true","false" to the server. - urlObj.includeDE = urlObj.includeDE == "true" ? true : false; - urlObj.excludeSC = urlObj.excludeSC == "true" ? true : false; - urlObj.excludeST = urlObj.excludeST == "true" ? true : false; - } - return _.extend({}, queryObj, urlObj, { - 'entityFilters': entityObj ? entityObj[queryObj.type] : null, - 'tagFilters': tagObj ? tagObj[queryObj.tag] : null, - 'type': queryObj.type, - 'query': queryObj.query, - 'term': queryObj.term, - 'tag': queryObj.tag - }) - }, - applyValue: function(model, searchType) { - that.manualRender(_.extend(searchType, CommonViewFunction.generateUrlFromSaveSearchObject({ - value: { "searchParameters": model.get('searchParameters'), 'uiParameters': model.get('uiParameters') }, - classificationDefCollection: that.classificationDefCollection, - entityDefCollection: that.entityDefCollection - }))); - } - } - that.RSaveSearchBasic.show(new SaveSearchView(_.extend(obj, { - isBasic: true, - collection: saveSearchBaiscCollection.fullCollection - }))); - that.RSaveSearchAdvance.show(new SaveSearchView(_.extend(obj, { - isBasic: false, - collection: saveSearchAdvanceCollection.fullCollection - }))); - - function fetchSaveSearchCollection() { - saveSearchCollection.fetch({ - success: function(collection, data) { - saveSearchAdvanceCollection.fullCollection.reset(_.where(data, { "searchType": "ADVANCED" })); - saveSearchBaiscCollection.fullCollection.reset(_.where(data, { "searchType": "BASIC" })); - }, - silent: true - }); - } - fetchSaveSearchCollection(); - }); - }, - bindEvents: function(param) { - var that = this; - this.listenTo(this.typeHeaders, "reset", function(value) { - this.initializeValues(); - }, this); - this.listenTo(this.searchVent, "entityList:refresh", function(model, response) { - this.onRefreshButton(); - }, this); - this.classificationAndMetricEvent.on("classification:Update:Search", function(options) { - that.entityCountObj = _.first(that.metricCollection.toJSON()); - that.value = Utils.getUrlState.getQueryParams() || {}; - if (!that.value.type) that.setInitialEntityVal = true; - that.initializeValues(); - }); - }, - initializeValues: function() { - this.renderTypeTagList(); - this.renderTermList(); - this.setValues(); - this.checkForButtonVisiblity(); - this.renderSaveSearch(); - if (this.setInitialEntityVal) { - this.setInitialEntityVal = false; - } - }, - makeFilterButtonActive: function(filtertypeParam) { - var filtertype = ['entityFilters', 'tagFilters'], - that = this; - if (filtertypeParam) { - if (_.isArray(filtertypeParam)) { - filtertype = filtertypeParam; - } else if (_.isString(filtertypeParam)) { - filtertype = [filtertypeParam]; - } - } - var typeCheck = function(filterObj, type) { - if (that.value.type) { - if (filterObj && filterObj.length) { - that.ui.typeAttrFilter.addClass('active'); - } else { - that.ui.typeAttrFilter.removeClass('active'); - } - that.ui.typeAttrFilter.prop('disabled', false); - } else { - that.ui.typeAttrFilter.removeClass('active'); - that.ui.typeAttrFilter.prop('disabled', true); - } - } - var tagCheck = function(filterObj, type) { - var filterAddOn = Enums.addOnClassification.filter(function(a) { a !== Enums.addOnClassification[0] }); - if (that.value.tag && !_.contains(filterAddOn, that.value.tag)) { - that.ui.tagAttrFilter.prop('disabled', false); - if (filterObj && filterObj.length) { - that.ui.tagAttrFilter.addClass('active'); - } else { - that.ui.tagAttrFilter.removeClass('active'); - } - } else { - that.ui.tagAttrFilter.removeClass('active'); - that.ui.tagAttrFilter.prop('disabled', true); - } - } - _.each(filtertype, function(type) { - var filterObj = that.searchTableFilters[type]; - if (type == "entityFilters") { - typeCheck(filterObj[that.value.type], type); - } - if (type == "tagFilters") { - tagCheck(filterObj[that.value.tag], type); - } - }); - }, - checkForButtonVisiblity: function(e, options) { - var that = this, - isBasicSearch = (this.type == "basic"); - if (e && e.currentTarget) { - var $el = $(e.currentTarget), - isTagEl = $el.data('id') == "tagLOV", - isTermEl = $el.data('id') == "termLOV", - isTypeEl = $el.data('id') == "typeLOV", - select2Data = $el.select2('data'); - if (e.type == "change" && select2Data) { - var value = (_.isEmpty(select2Data) ? select2Data : _.first(select2Data).id), - key = "tag", - filterType = isBasicSearch ? 'tagFilters' : null, - value = value && value.length ? value : null; - if (!isTagEl) { - key = (isTermEl ? "term" : "type"); - if (isBasicSearch) { - filterType = (isTypeEl ? "entityFilters" : null); - } - } - if (this.value) { - //On Change handle - if (this.value[key] !== value || (!value && !this.value[key])) { - var temp = {}; - temp[key] = value; - _.extend(this.value, temp); - // on change of type/tag change the offset. - if (_.isUndefined(options)) { - this.value.pageOffset = 0; - } - _.extend(this.query[this.type], temp); - } else if (isBasicSearch) { - // Initial loading handle. - if (filterType) { - var filterObj = this.searchTableFilters[filterType]; - if (filterObj && this.value[key]) { - this.searchTableFilters[filterType][this.value[key]] = this.value[filterType] ? this.value[filterType] : null; - } - } - - if (this.value.type) { - if (this.value.attributes) { - var attributes = _.sortBy(this.value.attributes.split(',')), - tableColumn = this.searchTableColumns[this.value.type]; - if (_.isEmpty(this.searchTableColumns) || !tableColumn) { - this.searchTableColumns[this.value.type] = attributes - } else if (tableColumn.join(",") !== attributes.join(",")) { - this.searchTableColumns[this.value.type] = attributes; - } - } else if (this.searchTableColumns[this.value.type]) { - this.searchTableColumns[this.value.type] = undefined; - } - } - } - if (isBasicSearch && filterType) { - this.makeFilterButtonActive(filterType); - } - } else if (isBasicSearch) { - this.ui.tagAttrFilter.prop('disabled', true); - this.ui.typeAttrFilter.prop('disabled', true); - } - } - } - - var value = this.ui.searchInput.val() || _.first($(this.ui.typeLov).select2('data')).id; - if (!this.dsl && _.isEmpty(value)) { - var termData = _.first($(this.ui.termLov).select2('data')); - value = _.first($(this.ui.tagLov).select2('data')).id || (termData ? termData.id : ""); - } - if (value && value.length) { - this.ui.searchBtn.removeAttr("disabled"); - setTimeout(function() { - that.ui.searchInput.focus(); - }, 0); - } else { - this.ui.searchBtn.attr("disabled", "true"); - } - }, - onRender: function() { - // array of tags which is coming from url - this.initializeValues(); - }, - updateQueryObject: function(param) { - if (param && param.searchType) { - this.type = param.searchType; - } - _.extend(this.query[this.type], - (this.type == "dsl" ? { - query: null, - type: null, - pageOffset: null, - pageLimit: null - } : { - query: null, - type: null, - tag: null, - term: null, - attributes: null, - tagFilters: null, - pageOffset: null, - pageLimit: null, - entityFilters: null, - includeDE: null - }), param); - }, - onRefreshButton: function() { - var that = this, - apiCount = 2, - updateSearchList = function() { - if (apiCount === 0) { - that.initializeValues(); - var checkURLValue = Utils.getUrlState.getQueryParams(that.url); - if (that.searchVent && (_.has(checkURLValue, "tag") || _.has(checkURLValue, "type") || _.has(checkURLValue, "query"))) { - that.searchVent.trigger('search:refresh'); - } - } - }; - this.metricCollection.fetch({ - complete: function() { - --apiCount; - that.entityCountObj = _.first(that.metricCollection.toJSON()); - updateSearchList(); - } - }); - - this.typeHeaders.fetch({ - silent: true, - complete: function() { - --apiCount; - updateSearchList(); - } - }); - }, - advancedInfo: function(e) { - require([ - 'views/search/AdvancedSearchInfoView', - 'modules/Modal' - ], function(AdvancedSearchInfoView, Modal) { - var view = new AdvancedSearchInfoView(); - var modal = new Modal({ - title: 'Advanced Search Queries', - content: view, - okCloses: true, - showFooter: true, - allowCancel: false - }).open(); - view.on('closeModal', function() { - modal.trigger('cancel'); - }); - }); - }, - openAttrFilter: function(filterType) { - var that = this; - require(['views/search/SearchQueryView'], function(SearchQueryView) { - that.attrModal = new SearchQueryView({ - value: that.value, - tag: (filterType === "tag" ? true : false), - type: (filterType === "type" ? true : false), - searchVent: that.searchVent, - typeHeaders: that.typeHeaders, - entityDefCollection: that.entityDefCollection, - enumDefCollection: that.enumDefCollection, - classificationDefCollection: that.classificationDefCollection, - businessMetadataDefCollection: that.businessMetadataDefCollection, - searchTableFilters: that.searchTableFilters, - - }); - that.attrModal.on('ok', function(scope, e) { - that.okAttrFilterButton(e); - }); - }); - }, - okAttrFilterButton: function(e) { - var that = this, - isTag = this.attrModal.tag ? true : false, - filtertype = isTag ? 'tagFilters' : 'entityFilters', - queryBuilderRef = this.attrModal.RQueryBuilder.currentView.ui.builder, - col = []; - - function getIdFromRuleObject(rule) { - _.map(rule.rules, function(obj, key) { - if (_.has(obj, 'condition')) { - return getIdFromRuleObject(obj); - } else { - return col.push(obj.id) - } - }); - return col; - } - if (queryBuilderRef.data('queryBuilder')) { - var rule = queryBuilderRef.queryBuilder('getRules'); - } - if (rule) { - var ruleUrl = CommonViewFunction.attributeFilter.generateUrl({ "value": rule, "formatedDateToLong": true }); - this.searchTableFilters[filtertype][(isTag ? this.value.tag : this.value.type)] = ruleUrl; - this.makeFilterButtonActive(filtertype); - if (!isTag && this.value && this.value.type && this.searchTableColumns) { - if (!this.searchTableColumns[this.value.type]) { - this.searchTableColumns[this.value.type] = ["selected", "name", "owner", "description", "tag", "typeName"] - } - this.searchTableColumns[this.value.type] = _.sortBy(_.union(this.searchTableColumns[this.value.type], getIdFromRuleObject(rule))); - } - if (rule.rules) { - if (!isTag && !that.tagEntityCheck) { - var state = _.find(rule.rules, { id: "__state" }); - if (state) { - that.typeEntityCheck = (state.value === "ACTIVE" && state.operator === "=") || (state.value === "DELETED" && state.operator === "!=") ? false : true; - that.value.includeDE = that.typeEntityCheck; - } else if (that.typeEntityCheck) { - that.typeEntityCheck = false; - if (!that.tagEntityCheck) { - that.value.includeDE = false; - } - } - } - if (isTag && !that.typeEntityCheck) { - var entityStatus = _.find(rule.rules, { id: "__entityStatus" }); - if (entityStatus) { - that.tagEntityCheck = (entityStatus.value === "ACTIVE" && entityStatus.operator === "=") || (entityStatus.value === "DELETED" && entityStatus.operator === "!=") ? false : true; - that.value.includeDE = that.tagEntityCheck - } else if (that.tagEntityCheck) { - that.tagEntityCheck = false; - if (!that.typeEntityCheck) { - that.value.includeDE = false; - } - } - } - } - this.attrModal.modal.close(); - if ($(e.currentTarget).hasClass('search')) { - this.findSearchResult(); - } - } - }, - manualRender: function(paramObj) { - if (paramObj) { - this.value = paramObj; - } - this.updateQueryObject(paramObj); - this.renderTypeTagList(); - this.setValues(paramObj); - }, - getFilterBox: function() { - var serviceStr = '', - serviceArr = [], - that = this; - this.typeHeaders.fullCollection.each(function(model) { - var serviceType = model.toJSON().serviceType; - if (serviceType) { - serviceArr.push(serviceType); - } - }); - - _.each(_.uniq(serviceArr), function(service) { - serviceStr += '
      • '; - }); - var templt = serviceStr + '
        '; - return templt; - }, - renderTypeTagList: function(options) { - var that = this; - var serviceTypeToBefiltered = (options && options.filterList); - var isTypeOnly = options && options.isTypeOnly; - if (this.selectedFilter[this.type].length) { - serviceTypeToBefiltered = this.selectedFilter[this.type]; - } - this.ui.typeLov.empty(); - var typeStr = '', - tagStr = typeStr, - foundNewClassification = false; - this.typeHeaders.fullCollection.each(function(model) { - var name = Utils.getName(model.toJSON(), 'name'); - if (model.get('category') == 'ENTITY' && (serviceTypeToBefiltered && serviceTypeToBefiltered.length ? _.contains(serviceTypeToBefiltered, model.get('serviceType')) : true)) { - var entityCount = (that.entityCountObj.entity.entityActive[name] || 0) + (that.entityCountObj.entity.entityDeleted[name] || 0); - typeStr += ''; - } - if (isTypeOnly == undefined && model.get('category') == 'CLASSIFICATION') { - var tagEntityCount = that.entityCountObj.tag.tagEntities[name]; - if (that.value && that.value.tag) { // to check if wildcard classification is present in our data - if (name === that.value.tag) { - foundNewClassification = true; - } - } - tagStr += ''; - } - }); - - if (this.type !== "dsl") { - _.each(Enums.addOnEntities, function(entity) { - typeStr += ''; - }); - } - if (!foundNewClassification && that.value) { - if (that.value.tag) { - var classificationValue = decodeURIComponent(that.value.tag); - tagStr += ''; - } - } - if (_.isUndefined(isTypeOnly)) { - //to insert extra classification list - if (that.value) { - _.each(Enums.addOnClassification, function(classificationName) { - if (classificationName !== that.value.tag) { - tagStr += ''; - } - }); - } - that.ui.tagLov.html(tagStr); - this.ui.tagLov.select2({ - placeholder: "Select Classification", - allowClear: true, - tags: true, - createTag: function(tag) { - if (tag.term.indexOf('*') != -1) { - return { - id: tag.term, - text: tag.term, - isNew: true - }; - } - } - }); - } - that.ui.typeLov.html(typeStr); - var typeLovSelect2 = this.ui.typeLov.select2({ - placeholder: "Select Type", - dropdownAdapter: $.fn.select2.amd.require("ServiceTypeFilterDropdownAdapter"), - allowClear: true, - getFilterBox: this.getFilterBox.bind(this), - onFilterSubmit: function(options) { - that.selectedFilter[that.type] = options.filterVal; - that.filterTypeSelected = that.selectedFilter[that.type]; - that.renderTypeTagList({ "filterList": options.filterVal, isTypeOnly: true }); - that.checkForButtonVisiblity(); - } - }); - if (this.value.filterTypeSelected === "undefined") { - typeLovSelect2.on("select2:close", function() { - typeLovSelect2.trigger("hideFilter"); - }); - if (typeLovSelect2 && isTypeOnly) { - typeLovSelect2.select2('open').trigger("change", { 'manual': true }); - } - } - if (that.setInitialEntityVal) { - var defaultEntity = Enums.addOnEntities[0]; - that.value.type = defaultEntity; - that.ui.typeLov.val(defaultEntity, null); - } - }, - renderTermList: function() { - this.glossaryTermArray = null; //This Value is created to store the result of search Term while basic search through term. - var that = this; - var getTypeAheadData = function(data, params) { - var dataList = data.entities, - foundOptions = []; - _.each(dataList, function(obj) { - if (obj) { - if (obj.guid) { - obj['id'] = obj.attributes['qualifiedName']; - } - foundOptions.push(obj); - } - }); - return foundOptions; - }; - this.ui.termLov.select2({ - placeholder: "Search Term", - allowClear: true, - ajax: { - url: UrlLinks.searchApiUrl('attribute'), - dataType: 'json', - delay: 250, - data: function(params) { - return { - attrValuePrefix: params.term, // search term - typeName: "AtlasGlossaryTerm", - limit: 10, - offset: 0 - }; - }, - processResults: function(data, params) { - that.glossaryTermArray = getTypeAheadData(data, params); //storing the search Results obj - return { - results: getTypeAheadData(data, params) - }; - }, - cache: true - }, - templateResult: function(option) { - var name = Utils.getName(option, 'qualifiedName'); - return name === "-" ? option.text : name; - }, - templateSelection: function(option) { - var name = Utils.getName(option, 'qualifiedName'); - return name === "-" ? option.text : name; - }, - escapeMarkup: function(markup) { - return markup; - }, - minimumInputLength: 1 - }); - }, - setValues: function(paramObj) { - var arr = [], - that = this; - if (paramObj) { - this.value = paramObj; - } - if (this.value.filterTypeSelected) { - this.filterTypeSelected = this.value.filterTypeSelected.split(','); - this.renderTypeTagList({ "filterList": this.filterTypeSelected, isTypeOnly: true }); - this.ui.typeLov.val(this.value.type); - } - if (this.value) { - this.ui.searchInput.val(this.value.query || ""); - if (this.value.dslChecked == "true" || this.value.searchType === "dsl") { - if (!this.ui.searchType.prop("checked")) { - this.ui.searchType.prop("checked", true).trigger("change"); - } - } else { - if (this.ui.searchType.prop("checked")) { - this.ui.searchType.prop("checked", false).trigger("change"); - } - } - this.ui.typeLov.val(this.value.type); - if (this.ui.typeLov.data('select2')) { - if (this.ui.typeLov.val() !== this.value.type) { - this.value.type = null; - this.ui.typeLov.val("").trigger("change", { 'manual': true }); - } else { - this.ui.typeLov.trigger("change", { 'manual': true }); - } - } - - - if (!this.dsl) { - this.ui.tagLov.val(this.value.tag); - if (this.ui.tagLov.data('select2')) { - // To handle delete scenario. - if (this.ui.tagLov.val() !== this.value.tag) { - this.value.tag = null; - this.ui.tagLov.val("").trigger("change", { 'manual': true }); - } else { - this.ui.tagLov.trigger("change", { 'manual': true }); - } - } - - if (this.value.term) { - this.ui.termLov.append(''); - } - if (this.ui.termLov.data('select2')) { - if (this.ui.termLov.val() !== this.value.term) { - this.value.term = null; - this.ui.termLov.val("").trigger("change", { 'manual': true }); - } else { - this.ui.termLov.trigger("change", { 'manual': true }); - } - } - } - setTimeout(function() { - that.ui.searchInput.focus(); - }, 0); - } - }, - findSearchResult: function() { - this.triggerSearch(this.ui.searchInput.val()); - }, - //This below function returns the searched Term Guid. - getSearchedTermGuid: function() { - var searchedTerm = this.ui.termLov.select2('val'), - searchedTermGuid = null; - if (searchedTerm) { - this.glossaryTermArray.find(function(obj) { - if (searchedTerm === obj.id) - searchedTermGuid = obj.guid; - }); - } - return searchedTermGuid; - }, - triggerSearch: function(value) { - var params = { - searchType: this.type, - dslChecked: this.ui.searchType.is(':checked'), - tagFilters: null, - entityFilters: null, - filterTypeSelected: this.filterTypeSelected - }, - typeLovValue = this.ui.typeLov.find(':selected').data('name'), // to get count of selected element used data - tagLovValue = this.ui.tagLov.find(':selected').data('name') || this.ui.tagLov.val(), - termLovValue = this.ui.termLov.select2('val'); - params['type'] = typeLovValue || null; - if (!this.dsl) { - params['tag'] = tagLovValue || null; - params['term'] = termLovValue || null; - params['guid'] = this.getSearchedTermGuid(); //Adding Guid in the URL for selection while switching. - var entityFilterObj = this.searchTableFilters['entityFilters'], - tagFilterObj = this.searchTableFilters['tagFilters']; - params['includeDE'] = false; - params['excludeST'] = false; - params['excludeSC'] = false; - if (this.value) { - if (this.value.tag) { - params['tagFilters'] = tagFilterObj[this.value.tag] - } - if (this.value.type) { - params['entityFilters'] = entityFilterObj[this.value.type] - } - var columnList = this.value.type && this.searchTableColumns ? this.searchTableColumns[this.value.type] : null; - if (columnList) { - params['attributes'] = columnList.join(','); - } - params['includeDE'] = _.isUndefinedNull(this.value.includeDE) ? false : this.value.includeDE; - params['excludeST'] = _.isUndefinedNull(this.value.excludeST) ? false : this.value.excludeST; - params['excludeSC'] = _.isUndefinedNull(this.value.excludeSC) ? false : this.value.excludeSC; - } - } - if (this.value && !_.isUndefinedNull(this.value.pageLimit)) { - params['pageLimit'] = this.value.pageLimit; - } - if (this.value && !_.isUndefinedNull(this.value.pageOffset)) { - if (!_.isUndefinedNull(this.query[this.type]) && this.query[this.type].query != value) { - params['pageOffset'] = 0; - } else { - params['pageOffset'] = this.value.pageOffset; - } - } - params['query'] = value || null; - _.extend(this.query[this.type], params); - Utils.setUrl({ - url: '#!/search/searchResult', - urlParams: _.extend({}, this.query[this.type]), - mergeBrowserUrl: false, - trigger: true, - updateTabState: true - }); - }, - dslFulltextToggle: function(e) { - var paramObj = Utils.getUrlState.getQueryParams(); - if (paramObj && this.type == paramObj.searchType) { - this.updateQueryObject(paramObj); - } - if (e.currentTarget.checked) { - this.type = "dsl"; - this.dsl = true; - this.$('.typeFilterBtn,.tagBox,.termBox,.basicSaveSearch').hide(); - this.$('.typeFilter').addClass('col-sm-12'); - this.$('.typeFilter').removeClass('col-sm-10'); - this.$('.advanceSaveSearch').show(); - this.$('.searchText').text('Search By Query'); - this.ui.searchInput.attr("placeholder", 'Search By Query eg. where name="sales_fact"'); - } else { - this.$('.typeFilter').addClass('col-sm-10'); - this.$('.typeFilter').removeClass('col-sm-12'); - this.$('.typeFilterBtn,.tagBox,.termBox,.basicSaveSearch').show(); - this.$('.advanceSaveSearch').hide(); - this.dsl = false; - this.type = "basic"; - this.$('.searchText').text('Search By Text'); - this.ui.searchInput.attr("placeholder", "Search By Text"); - } - if (Utils.getUrlState.isSearchTab()) { - Utils.setUrl({ - url: '#!/search/searchResult', - urlParams: _.extend(this.query[this.type], { - searchType: this.type, - dslChecked: this.ui.searchType.is(':checked') - }), - mergeBrowserUrl: false, - trigger: true, - updateTabState: true - }); - } - }, - clearSearchData: function() { - this.selectedFilter[this.type] = []; - this.filterTypeSelected = []; - this.renderTypeTagList(); - this.updateQueryObject(); - this.ui.typeLov.val("").trigger("change"); - this.ui.tagLov.val("").trigger("change"); - this.ui.searchInput.val(""); - var type = "basicSaveSearch"; - if (this.type == "dsl") { - type = "advanceSaveSearch"; - } - this.$('.' + type + ' .saveSearchList').find('li.active').removeClass('active'); - this.$('.' + type + ' [data-id="saveBtn"]').attr('disabled', true); - if (!this.dsl) { - this.searchTableFilters.tagFilters = {}; - this.searchTableFilters.entityFilters = {}; - } - this.checkForButtonVisiblity(); - Utils.setUrl({ - url: '#!/search/searchResult', - urlParams: { - searchType: this.type, - dslChecked: this.ui.searchType.is(':checked') - }, - mergeBrowserUrl: false, - trigger: true - }); - } - }); - return SearchLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/search/SearchQueryView.js b/dashboardv2/public/js/views/search/SearchQueryView.js deleted file mode 100644 index 69a35a54b6c..00000000000 --- a/dashboardv2/public/js/views/search/SearchQueryView.js +++ /dev/null @@ -1,135 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'modules/Modal', - 'utils/Utils', - 'hbs!tmpl/search/SearchQuery_tmpl', - 'utils/Globals', - 'utils/Enums' -], function(require, Backbone, Modal, Utils, SearchQuery_Tmpl, Globals, Enums) { - - var SearchQueryView = Backbone.Marionette.LayoutView.extend( - /** @lends SearchQueryView */ - { - _viewName: 'SearchQueryView', - - template: SearchQuery_Tmpl, - - - - /** Layout sub regions */ - regions: { - RQueryBuilder: '#r_queryBuilder', - }, - - - /** ui selector cache */ - ui: {}, - /** ui events hash */ - events: function() { - var events = {}; - return events; - }, - /** - * intialize a new SearchQueryView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'value', 'entityDefCollection', 'typeHeaders', 'searchVent', 'enumDefCollection', 'classificationDefCollection', 'businessMetadataDefCollection', 'tag', 'searchTableFilters')); - this.bindEvents(); - var that = this; - this.modal = new Modal({ - title: 'Attribute Filter', - content: this, - allowCancel: true, - mainClass: 'modal-lg', - okCloses: false, - buttons: [{ - text: 'Cancel', - btnClass: "cancel btn-action", - title: 'Cancel' - }, { - text: 'Apply', - btnClass: "ok btn-atlas", - title: "Apply the filters and close popup (won't perform search)" - }, - { - text: 'Search', - btnClass: "ok search btn-atlas", - title: 'Apply the filters and do search' - } - ] - }).open(); - this.modal.on('closeModal', function() { - that.modal.trigger('cancel'); - }); - }, - onRender: function() { - var obj = { - value: this.value, - searchVent: this.searchVent, - entityDefCollection: this.entityDefCollection, - enumDefCollection: this.enumDefCollection, - classificationDefCollection: this.classificationDefCollection, - businessMetadataDefCollection: this.businessMetadataDefCollection, - searchTableFilters: this.searchTableFilters, - typeHeaders: this.typeHeaders - } - - if (this.tag) { - obj['tag'] = true; - obj['attrObj'] = this.classificationDefCollection.fullCollection.find({ name: this.value.tag }); - if (obj.attrObj) { - obj.attrObj = Utils.getNestedSuperTypeObj({ - data: obj.attrObj.toJSON(), - collection: this.classificationDefCollection, - attrMerge: true, - }); - } - if (Globals[this.value.tag] || Globals[Enums.addOnClassification[0]]) { - obj['systemAttrArr'] = (Globals[this.value.tag] || Globals[Enums.addOnClassification[0]]).attributeDefs; - } - } else { - obj['type'] = true; - obj['attrObj'] = this.entityDefCollection.fullCollection.find({ name: this.value.type }); - if (obj.attrObj) { - obj.attrObj = Utils.getNestedSuperTypeObj({ - data: obj.attrObj.toJSON(), - collection: this.entityDefCollection, - attrMerge: true - }); - } - if (Globals[this.value.type] || Globals[Enums.addOnEntities[0]]) { - obj['systemAttrArr'] = (Globals[this.value.type] || Globals[Enums.addOnEntities[0]]).attributeDefs; - } - } - this.renderQueryBuilder(obj); - // this.showHideFilter(this.value); - }, - bindEvents: function() {}, - renderQueryBuilder: function(obj) { - var that = this; - require(['views/search/QueryBuilderView'], function(QueryBuilderView) { - that.RQueryBuilder.show(new QueryBuilderView(obj)); - }); - } - }); - return SearchQueryView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/search/SearchResultLayoutView.js b/dashboardv2/public/js/views/search/SearchResultLayoutView.js deleted file mode 100644 index 04e6856204e..00000000000 --- a/dashboardv2/public/js/views/search/SearchResultLayoutView.js +++ /dev/null @@ -1,1338 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -define(['require', - 'backbone', - 'table-dragger', - 'hbs!tmpl/search/SearchResultLayoutView_tmpl', - 'modules/Modal', - 'models/VEntity', - 'utils/Utils', - 'utils/Globals', - 'collection/VSearchList', - 'models/VCommon', - 'utils/CommonViewFunction', - 'utils/Messages', - 'utils/Enums', - 'utils/UrlLinks', - 'platform' -], function(require, Backbone, tableDragger, SearchResultLayoutViewTmpl, Modal, VEntity, Utils, Globals, VSearchList, VCommon, CommonViewFunction, Messages, Enums, UrlLinks, platform) { - 'use strict'; - - var SearchResultLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends SearchResultLayoutView */ - { - _viewName: 'SearchResultLayoutView', - - template: SearchResultLayoutViewTmpl, - - /** Layout sub regions */ - regions: { - RTagLayoutView: "#r_tagLayoutView", - RSearchLayoutView: "#r_searchLayoutView", - REntityTableLayoutView: "#r_searchResultTableLayoutView", - RSearchQuery: '#r_searchQuery' - }, - - /** ui selector cache */ - ui: { - tagClick: '[data-id="tagClick"]', - termClick: '[data-id="termClick"]', - addTag: '[data-id="addTag"]', - addTerm: '[data-id="addTerm"]', - paginationDiv: '[data-id="paginationDiv"]', - previousData: "[data-id='previousData']", - nextData: "[data-id='nextData']", - pageRecordText: "[data-id='pageRecordText']", - addAssignTag: "[data-id='addAssignTag']", - addAssignTerm: "[data-id='addAssignTerm']", - createEntity: "[data-id='createEntity']", - checkDeletedEntity: "[data-id='checkDeletedEntity']", - checkSubClassification: "[data-id='checkSubClassification']", - checkSubType: "[data-id='checkSubType']", - colManager: "[data-id='colManager']", - containerCheckBox: "[data-id='containerCheckBox']", - columnEmptyInfo: "[data-id='columnEmptyInfo']", - showPage: "[data-id='showPage']", - gotoPage: "[data-id='gotoPage']", - gotoPagebtn: "[data-id='gotoPagebtn']", - activePage: "[data-id='activePage']" - }, - templateHelpers: function() { - return { - entityCreate: Globals.entityCreate, - searchType: this.searchType, - fromView: this.fromView, - isGlossaryView: this.fromView == "glossary", - isSearchTab: Utils.getUrlState.isSearchTab() - }; - }, - /** ui events hash */ - events: function() { - var events = {}, - that = this; - events["click " + this.ui.tagClick] = function(e) { - var scope = $(e.currentTarget); - if (e.target.nodeName.toLocaleLowerCase() == "i") { - this.onClickTagCross(e); - } else { - this.triggerUrl({ - url: '#!/tag/tagAttribute/' + scope.text(), - urlParams: null, - mergeBrowserUrl: false, - trigger: true, - updateTabState: null - }); - } - }; - events["click " + this.ui.termClick] = function(e) { - var scope = $(e.currentTarget); - if (e.target.nodeName.toLocaleLowerCase() == "i") { - this.onClickTermCross(e); - } else { - this.triggerUrl({ - url: '#!/glossary/' + scope.find('i').data('termguid'), - urlParams: { gType: "term", viewType: "term", fromView: "entity" }, - mergeBrowserUrl: false, - trigger: true, - updateTabState: null - }); - } - }; - events["keyup " + this.ui.gotoPage] = function(e) { - var code = e.which, - goToPage = parseInt(e.currentTarget.value); - if (e.currentTarget.value) { - that.ui.gotoPagebtn.attr('disabled', false); - } else { - that.ui.gotoPagebtn.attr('disabled', true); - } - if (code == 13) { - if (e.currentTarget.value) { - that.gotoPagebtn(); - } - } - }; - events["change " + this.ui.showPage] = 'changePageLimit'; - events["click " + this.ui.gotoPagebtn] = 'gotoPagebtn'; - events["click " + this.ui.addTag] = 'onClickAddTag'; - events["click " + this.ui.addTerm] = 'onClickAddTermBtn'; - events["click " + this.ui.addAssignTag] = 'onClickAddTag'; - events["click " + this.ui.addAssignTerm] = 'onClickAddTermBtn'; - events["click " + this.ui.nextData] = "onClicknextData"; - events["click " + this.ui.previousData] = "onClickpreviousData"; - events["click " + this.ui.createEntity] = 'onClickCreateEntity'; - events["click " + this.ui.checkDeletedEntity] = 'onCheckExcludeIncludeResult'; - events["click " + this.ui.checkSubClassification] = 'onCheckExcludeIncludeResult'; - events["click " + this.ui.checkSubType] = 'onCheckExcludeIncludeResult'; - return events; - }, - /** - * intialize a new SearchResultLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'value', 'guid', 'initialView', 'isTypeTagNotExists', 'classificationDefCollection', 'entityDefCollection', 'typeHeaders', 'searchVent', 'enumDefCollection', 'tagCollection', 'searchTableColumns', 'isTableDropDisable', 'fromView', 'glossaryCollection', 'termName', 'businessMetadataDefCollection', 'profileDBView')); - this.entityModel = new VEntity(); - this.searchCollection = new VSearchList(); - this.limit = 25; - this.asyncFetchCounter = 0; - this.offset = 0; - this.bindEvents(); - this.multiSelectEntity = []; - this.activeEntityCountSelected = 0; - this.searchType = 'Basic Search'; - this.columnOrder = null; - this.defaultColumns = ["selected", "name", "description", "typeName", "owner", "tag", "term"]; - if (this.value) { - if (this.value.searchType && this.value.searchType == 'dsl') { - this.searchType = 'Advanced Search'; - } - if (this.value.pageLimit) { - var pageLimit = parseInt(this.value.pageLimit, 10); - if (_.isNaN(pageLimit) || pageLimit == 0 || pageLimit <= -1) { - this.value.pageLimit = this.limit; - this.triggerUrl(); - } else { - this.limit = pageLimit; - } - } - if (this.value.pageOffset) { - var pageOffset = parseInt(this.value.pageOffset, 10); - if (_.isNaN(pageOffset) || pageLimit <= -1) { - this.value.pageOffset = this.offset; - this.triggerUrl(); - } else { - this.offset = pageOffset; - } - } - }; - if (platform.name === "IE") { - this.isTableDropDisable = true; - } - }, - bindEvents: function() { - var that = this; - this.onClickLoadMore(); - this.listenTo(this.searchCollection, 'backgrid:selected', function(model, checked) { - this.multiSelectEntity = []; - that.activeEntityCountSelected = 0; - if (checked === true) { - model.set("isEnable", true); - } else { - model.set("isEnable", false); - } - this.searchCollection.find(function(item) { - if (item.get('isEnable')) { - var obj = item.toJSON(); - if (item.get('status') === 'ACTIVE') { - that.activeEntityCountSelected++; - } - that.multiSelectEntity.push({ - id: obj.guid, - model: obj - }); - } - }); - this.updateMultiSelect(); - }); - this.listenTo(this.searchCollection, "error", function(model, response) { - this.hideLoader({ type: 'error' }); - var responseJSON = response && response.responseJSON ? response.responseJSON : null, - errorText = (responseJSON && (responseJSON.errorMessage || responseJSON.message || responseJSON.error)) || 'Invalid Expression'; - if (errorText) { - Utils.notifyError({ - content: errorText - }); - this.$('.searchTable > .well').html('
        ' + _.escape(errorText) + '
        ') - } - }, this); - this.listenTo(this.searchCollection, "state-changed", function(state) { - if (Utils.getUrlState.isSearchTab()) { - this.updateColumnList(state); - var excludeDefaultColumn = []; - if (this.value && this.value.type) { - excludeDefaultColumn = _.difference(this.searchTableColumns[this.value.type], this.defaultColumns); - if (this.searchTableColumns[this.value.type] === null) { - this.ui.columnEmptyInfo.show(); - } else { - this.ui.columnEmptyInfo.hide(); - } - } - this.columnOrder = this.getColumnOrder(this.REntityTableLayoutView.$el.find('.colSort th.renderable')); - this.triggerUrl(); - var attributes = this.searchCollection.filterObj.attributes; - if ((excludeDefaultColumn && attributes) && (excludeDefaultColumn.length > attributes.length || _.difference(excludeDefaultColumn, attributes).length)) { - this.fetchCollection(this.value); - } - } - }, this); - this.listenTo(this.searchVent, "search:refresh", function(model, response) { - this.fetchCollection(); - }, this); - this.listenTo(this.searchCollection, "backgrid:sorted", function(model, response) { - this.checkTableFetch(); - }, this) - }, - onRender: function() { - var that = this; - this.checkEntityImage = {}; - this.commonTableOptions = { - collection: this.searchCollection, - includePagination: false, - includeFooterRecords: false, - includeColumnManager: (Utils.getUrlState.isSearchTab() && this.value && this.value.searchType === "basic" && !this.profileDBView ? true : false), - includeOrderAbleColumns: false, - includeSizeAbleColumns: false, - includeTableLoader: false, - includeAtlasTableSorting: true, - showDefaultTableSorted: true, - updateFullCollectionManually: true, - columnOpts: { - opts: { - initialColumnsVisible: null, - saveState: false - }, - visibilityControlOpts: { - buttonTemplate: _.template("") - }, - el: this.ui.colManager - }, - gridOpts: { - emptyText: 'No Records found!', - className: 'table table-hover backgrid table-quickMenu colSort' - }, - sortOpts: { - sortColumn: "name", - sortDirection: "ascending" - }, - filterOpts: {}, - paginatorOpts: {} - }; - if (!this.initialView) { - var value = {}, - that = this; - if (this.value) { - value = this.value; - if (value && value.includeDE) { - this.ui.checkDeletedEntity.prop('checked', true); - } - if (value && value.excludeSC) { - this.ui.checkSubClassification.prop('checked', true); - } - if (value && value.excludeST) { - this.ui.checkSubType.prop('checked', true); - } - - } else { - value = { - 'query': null, - 'searchType': 'basic' - }; - } - this.updateColumnList(); - if (this.value && this.searchTableColumns && this.searchTableColumns[this.value.type] === null) { - this.ui.columnEmptyInfo.show(); - } else { - this.ui.columnEmptyInfo.hide(); - } - this.fetchCollection(value, _.extend({ 'fromUrl': true }, (this.value && this.value.pageOffset ? { 'next': true } : null))); - this.ui.showPage.select2({ - data: _.sortBy(_.union([25, 50, 100, 150, 200, 250, 300, 350, 400, 450, 500], [this.limit])), - tags: true, - dropdownCssClass: "number-input", - multiple: false - }); - if (this.value && this.value.pageLimit) { - this.ui.showPage.val(this.limit).trigger('change', { "skipViewChange": true }); - } - } else { - if (Globals.entityTypeConfList) { - this.$(".entityLink").show(); - } - if (this.isTypeTagNotExists) { - Utils.notifyError({ - content: Messages.search.notExists - }); - } - } - }, - getColumnOrderWithPosition: function() { - var that = this; - return _.map(that.columnOrder, function(value, key) { - return key + "::" + value; - }).join(","); - }, - triggerUrl: function(options) { - Utils.setUrl(_.extend({ - url: Utils.getUrlState.getQueryUrl().queyParams[0], - urlParams: this.columnOrder ? _.extend(this.value, { 'uiParameters': this.getColumnOrderWithPosition() }) : this.value, - mergeBrowserUrl: false, - trigger: false, - updateTabState: true - }, options)); - }, - updateMultiSelect: function() { - var addTermTagButton = this.$('.multiSelectTag,.multiSelectTerm'); - if (this.activeEntityCountSelected > 0) { - addTermTagButton.show(); - } else { - addTermTagButton.hide(); - } - }, - updateColumnList: function(updatedList) { - if (updatedList) { - var listOfColumns = []; - _.map(updatedList, function(obj) { - var key = obj.name; - if (obj.renderable) { - listOfColumns.push(obj.name); - } - }); - listOfColumns = _.sortBy(listOfColumns); - this.value.attributes = listOfColumns.length ? listOfColumns.join(",") : null; - if (this.value && this.value.type && this.searchTableColumns) { - this.searchTableColumns[this.value.type] = listOfColumns.length ? listOfColumns : null; - } - } else if (this.value && this.value.type && this.searchTableColumns && this.value.attributes) { - this.searchTableColumns[this.value.type] = this.value.attributes.split(","); - } - }, - fetchCollection: function(value, options) { - var that = this, - isPostMethod = (this.value && this.value.searchType === "basic"), - isSearchTab = Utils.getUrlState.isSearchTab(), - tagFilters = null, - entityFilters = null; - that.activeEntityCountSelected = 0; - that.updateMultiSelect(); - if (isSearchTab) { - tagFilters = CommonViewFunction.attributeFilter.generateAPIObj(this.value.tagFilters); - entityFilters = CommonViewFunction.attributeFilter.generateAPIObj(this.value.entityFilters); - } - - if (isPostMethod && isSearchTab) { - var excludeDefaultColumn = this.value.type && this.searchTableColumns ? _.difference(this.searchTableColumns[this.value.type], this.defaultColumns) : null, - filterObj = { - 'entityFilters': entityFilters, - 'tagFilters': tagFilters, - 'attributes': excludeDefaultColumn ? excludeDefaultColumn : null - }; - } - - this.showLoader(); - if (Globals.searchApiCallRef && Globals.searchApiCallRef.readyState === 1) { - Globals.searchApiCallRef.abort(); - } - var apiObj = { - skipDefaultError: true, - sort: false, - success: function(dataOrCollection, response) { - if (that.isDestroyed) { - return; - } - Globals.searchApiCallRef = undefined; - var isFirstPage = that.offset === 0, - dataLength = 0, - goToPage = that.ui.gotoPage.val(); - that.ui.gotoPage.val(''); - that.ui.gotoPage.parent().removeClass('has-error'); - that.ui.gotoPagebtn.prop("disabled", true); - if (!(that.ui.pageRecordText instanceof jQuery)) { - return; - } - if (isPostMethod && dataOrCollection && dataOrCollection.entities) { - dataLength = dataOrCollection.entities.length; - } else { - dataLength = dataOrCollection.length; - } - - if (!dataLength && that.offset >= that.limit && ((options && options.next) || goToPage) && (options && !options.fromUrl)) { - /* User clicks on next button and server returns - empty response then disabled the next button without rendering table*/ - - that.hideLoader(); - var pageNumber = that.activePage + 1; - if (goToPage) { - pageNumber = goToPage; - that.offset = (that.activePage - 1) * that.limit; - } else { - that.finalPage = that.activePage; - that.ui.nextData.attr('disabled', true); - that.offset = that.offset - that.limit; - } - if (that.value) { - that.value.pageOffset = that.offset; - that.triggerUrl(); - } - Utils.notifyInfo({ - html: true, - content: Messages.search.noRecordForPage + '' + Utils.getNumberSuffix({ number: pageNumber, sup: true }) + ' page' - }); - return; - } - if (isPostMethod) { - Utils.findAndMergeRefEntity({ - attributeObject: dataOrCollection.entities, - referredEntities: dataOrCollection.referredEntities - }); - that.searchCollection.reset(dataOrCollection.entities, { silent: true }); - that.searchCollection.fullCollection.reset(dataOrCollection.entities, { silent: true }); - } - - - /*Next button check. - It's outside of Previous button else condition - because when user comes from 2 page to 1 page than we need to check next button.*/ - if (dataLength < that.limit) { - that.ui.nextData.attr('disabled', true); - } else { - that.ui.nextData.attr('disabled', false); - } - - if (isFirstPage && (!dataLength || dataLength < that.limit)) { - that.ui.paginationDiv.hide(); - } else { - that.ui.paginationDiv.show(); - } - - // Previous button check. - if (isFirstPage) { - that.ui.previousData.attr('disabled', true); - that.pageFrom = 1; - that.pageTo = that.limit; - } else { - that.ui.previousData.attr('disabled', false); - } - - if (options && options.next) { - //on next click, adding "1" for showing the another records. - that.pageTo = that.offset + that.limit; - that.pageFrom = that.offset + 1; - } else if (!isFirstPage && options && options.previous) { - that.pageTo = that.pageTo - that.limit; - that.pageFrom = (that.pageTo - that.limit) + 1; - } - that.ui.pageRecordText.html("Showing " + that.searchCollection.models.length + " records From " + that.pageFrom + " - " + that.pageTo); - that.activePage = Math.round(that.pageTo / that.limit); - that.ui.activePage.attr('title', "Page " + that.activePage); - that.ui.activePage.text(that.activePage); - that.renderTableLayoutView(); - that.multiSelectEntity = []; - - if (dataLength > 0) { - that.$('.searchTable').removeClass('noData') - } - - if (Utils.getUrlState.isSearchTab() && value && !that.profileDBView) { - var searchString = 'Results for: ' + CommonViewFunction.generateQueryOfFilter(that.value) + ""; - if (Globals.entityCreate && Globals.entityTypeConfList && Utils.getUrlState.isSearchTab()) { - searchString += "

        If you do not find the entity in search result below then you can" + ' create new entity

        '; - } - that.$('.searchResult').html(searchString); - } - }, - silent: true, - reset: true - } - if (this.value) { - var checkBoxValue = { - 'excludeDeletedEntities': (this.value.includeDE ? false : true), - 'includeSubClassifications': (this.value.excludeSC ? false : true), - 'includeSubTypes': (this.value.excludeST ? false : true), - 'includeClassificationAttributes': true // server will return classication details with guid - } - } - if (value) { - if (value.searchType) { - this.searchCollection.url = UrlLinks.searchApiUrl(value.searchType); - } - _.extend(this.searchCollection.queryParams, { 'limit': this.limit, 'offset': this.offset, 'query': _.trim(value.query), 'typeName': value.type || null, 'classification': value.tag || null, 'termName': value.term || null }); - if (this.profileDBView && value.typeName && value.guid) { - var profileParam = {}; - profileParam['guid'] = value.guid; - profileParam['relation'] = value.typeName === 'hive_db' ? '__hive_table.db' : '__hbase_table.namespace'; - profileParam['sortBy'] = 'name'; - profileParam['sortOrder'] = 'ASCENDING'; - _.extend(this.searchCollection.queryParams, profileParam); - } - if (isPostMethod) { - this.searchCollection.filterObj = _.extend({}, filterObj); - apiObj['data'] = _.extend(checkBoxValue, filterObj, _.pick(this.searchCollection.queryParams, 'query', 'excludeDeletedEntities', 'limit', 'offset', 'typeName', 'classification', 'termName')); - Globals.searchApiCallRef = this.searchCollection.getBasicRearchResult(apiObj); - } else { - apiObj.data = null; - this.searchCollection.filterObj = null; - if (this.profileDBView) { - _.extend(this.searchCollection.queryParams, checkBoxValue); - } - Globals.searchApiCallRef = this.searchCollection.fetch(apiObj); - } - } else { - _.extend(this.searchCollection.queryParams, { 'limit': this.limit, 'offset': this.offset }); - if (isPostMethod) { - apiObj['data'] = _.extend(checkBoxValue, filterObj, _.pick(this.searchCollection.queryParams, 'query', 'excludeDeletedEntities', 'limit', 'offset', 'typeName', 'classification', 'termName')); - Globals.searchApiCallRef = this.searchCollection.getBasicRearchResult(apiObj); - } else { - apiObj.data = null; - if (this.profileDBView) { - _.extend(this.searchCollection.queryParams, checkBoxValue); - } - Globals.searchApiCallRef = this.searchCollection.fetch(apiObj); - } - } - }, - tableRender: function(options) { - var that = this, - savedColumnOrder = options.order, - TableLayout = options.table, - columnCollection = Backgrid.Columns.extend({ - sortKey: "displayOrder", - className: "my-awesome-css-animated-grid", - comparator: function(item) { - return item.get(this.sortKey) || 999; - }, - setPositions: function() { - _.each(this.models, function(model, index) { - model.set("displayOrder", (savedColumnOrder == null ? index : parseInt(savedColumnOrder[model.get('label')])) + 1, { silent: true }); - }); - return this; - } - }); - var columns = new columnCollection((that.searchCollection.dynamicTable ? that.getDaynamicColumns(that.searchCollection.toJSON()) : that.getFixedDslColumn())); - columns.setPositions().sort(); - if (this.searchType == "Advanced Search" && columns.length && that.searchCollection.length) { - //for dsl search with Select clause, default column to be use as sorting - var tableColumnNames = Object.keys(that.searchCollection.toJSON()[0]); - that.commonTableOptions['sortOpts'] = { - sortColumn: tableColumnNames[0], - sortDirection: "ascending" - }; - } - var table = new TableLayout(_.extend({}, that.commonTableOptions, { - columns: columns - })); - if (table.collection.length === 0) { - that.$(".searchTable").addClass('noData'); - } - if (!that.REntityTableLayoutView) { - return; - } - if (!that.value) { - that.value = that.options.value; - } - that.REntityTableLayoutView.show(table); - if (that.value.searchType !== "dsl") { - that.ui.containerCheckBox.show(); - } else { - that.ui.containerCheckBox.hide(); - } - that.$(".ellipsis-with-margin .inputAssignTag").hide(); - table.trigger("grid:refresh"); /*Event fire when table rendered*/ - // that.REntityTableLayoutView.$el.find('.colSort thead tr th:not(:first)').addClass('dragHandler'); - if (that.isTableDropDisable !== true) { - var tableDropFunction = function(from, to, el) { - tableDragger(document.querySelector(".colSort")).destroy(); - that.columnOrder = that.getColumnOrder(el.querySelectorAll('th.renderable')); - that.triggerUrl(); - that.tableRender({ "order": that.columnOrder, "table": TableLayout }); - that.checkTableFetch(); - } - that.REntityTableLayoutView.$el.find('.colSort thead tr th:not(.select-all-header-cell)').addClass('dragHandler'); - tableDragger(document.querySelector(".colSort"), { dragHandler: ".dragHandler" }).on('drop', tableDropFunction); - } - }, - renderTableLayoutView: function(col) { - var that = this; - require(['utils/TableLayout'], function(TableLayout) { - // displayOrder added for column manager - if (that.value.uiParameters) { - var savedColumnOrder = _.object(that.value.uiParameters.split(',').map(function(a) { - return a.split('::'); - })); // get Column position from string to object - } - - that.tableRender({ "order": savedColumnOrder, "table": TableLayout }); - that.checkTableFetch(); - }); - }, - getColumnOrder: function(arr) { - var obj = {}; - for (var i = 0; i < arr.length; ++i) { - var innerText = arr[i].innerText.trim(); - obj[(innerText == "" ? 'Select' : innerText)] = i; - } - return obj; - }, - checkTableFetch: function() { - if (this.asyncFetchCounter <= 0) { - this.hideLoader(); - Utils.generatePopover({ - el: this.$('[data-id="showMoreLess"]'), - contentClass: 'popover-tag-term', - viewFixedPopover: true, - popoverOptions: { - container: null, - content: function() { - return $(this).find('.popup-tag-term').children().clone(); - } - } - }); - } - }, - getFixedDslColumn: function() { - var that = this, - nameCheck = 0, - columnToShow = null, - col = {}; - this.value = this.fromView === "glossary" ? this.value : Utils.getUrlState.getQueryParams() || this.value; - if (this.value && this.value.searchType === "basic" && this.searchTableColumns && (this.searchTableColumns[this.value.type] !== undefined)) { - columnToShow = this.searchTableColumns[this.value.type] == null ? [] : this.searchTableColumns[this.value.type]; - } - col['Check'] = { - name: "selected", - label: "Select", - cell: "select-row", - resizeable: false, - orderable: false, - renderable: (columnToShow ? _.contains(columnToShow, 'selected') : true), - headerCell: "select-all" - }; - - - col['name'] = { - label: this.value && this.profileDBView ? "Table Name" : "Name", - cell: "html", - editable: false, - resizeable: true, - orderable: false, - renderable: true, - className: "searchTableName", - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var obj = model.toJSON(), - nameHtml = "", - name = Utils.getName(obj); - if (!obj.attributes || obj.attributes.serviceType === undefined) { - if (Globals.serviceTypeMap[obj.typeName] === undefined && that.entityDefCollection) { - var defObj = that.entityDefCollection.fullCollection.find({ name: obj.typeName }); - if (defObj) { - Globals.serviceTypeMap[obj.typeName] = defObj.get('serviceType'); - } - } - } else if (Globals.serviceTypeMap[obj.typeName] === undefined) { - Globals.serviceTypeMap[obj.typeName] = obj.attributes ? obj.attributes.serviceType : null; - } - obj.serviceType = Globals.serviceTypeMap[obj.typeName]; - if (obj.guid) { - if (obj.guid == "-1") { - nameHtml = '' + name + ''; - } else { - nameHtml = '' + name + ''; - } - } else { - nameHtml = '' + name + ''; - } - if (obj.status && Enums.entityStateReadOnly[obj.status]) { - nameHtml += ''; - nameHtml = ''; - } - var getImageData = function(options) { - var imagePath = options.imagePath, - returnImgUrl = null; - that.checkEntityImage[model.get('guid')] = false; - $.ajax({ - "url": imagePath, - "method": "get", - "cache": true - }) - .always(function(data, status, xhr) { - if (data.status == 404) { - returnImgUrl = getImageData({ - "imagePath": Utils.getEntityIconPath({ entityData: obj, errorUrl: imagePath }) - }); - } else if (data) { - that.checkEntityImage[model.get('guid')] = imagePath; - returnImgUrl = imagePath; - that.$("img[data-imgGuid='" + obj.guid + "']").removeClass("searchTableLogoLoader").attr("src", imagePath); - } - }); - } - var img = ""; - img = "
        "; - if (that.checkEntityImage[model.get('guid')] == undefined) { - getImageData({ imagePath: Utils.getEntityIconPath({ entityData: obj }) }); - } else { - if (that.checkEntityImage[model.get('guid')] != false) { - img = "
        "; - } - } - return (img + nameHtml); - } - }) - }; - - col['owner'] = { - label: "Owner", - cell: "String", - editable: false, - resizeable: true, - orderable: true, - renderable: true, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var obj = model.toJSON(); - if (obj && obj.attributes && obj.attributes.owner) { - return obj.attributes.owner; - } - } - }) - }; - if (this.value && this.profileDBView) { - col['createTime'] = { - label: "Date Created", - cell: "Html", - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var obj = model.toJSON(); - if (obj && obj.attributes && obj.attributes.createTime) { - return Utils.formatDate({ date: obj.attributes.createTime }); - } else { - return '-' - } - } - }) - } - } - if (this.value && !this.profileDBView) { - col['description'] = { - label: "Description", - cell: "String", - editable: false, - resizeable: true, - orderable: true, - renderable: true, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var obj = model.toJSON(); - if (obj && obj.attributes && obj.attributes.description) { - return obj.attributes.description; - } - } - }) - }; - - - col['typeName'] = { - label: "Type", - cell: "Html", - editable: false, - resizeable: true, - orderable: true, - renderable: (columnToShow ? _.contains(columnToShow, 'typeName') : true), - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var obj = model.toJSON(); - if (obj && obj.typeName) { - return '' + obj.typeName + ''; - } - } - }) - }; - this.getTagCol({ 'col': col, 'columnToShow': columnToShow }); - if ((!_.contains(["glossary"], this.fromView))) { - this.getTermCol({ 'col': col, 'columnToShow': columnToShow }); - } - - if (this.value && this.value.searchType === "basic") { - var def = this.entityDefCollection.fullCollection.find({ name: this.value.type }), - systemAttr = [], - businessMetadataAttr = [], - businessAttributes = {}; - if (this.value.type == "_ALL_ENTITY_TYPES") { - this.businessMetadataDefCollection.each(function(model) { - var sortedAttributes = model.get('attributeDefs') || null, - name = model.get('name'); - if (sortedAttributes) { - sortedAttributes = _.sortBy(sortedAttributes, function(obj) { - return obj.name; - }); - businessAttributes[name] = $.extend(true, {}, sortedAttributes); - } - }) - } else { - businessAttributes = def ? ($.extend(true, {}, def.get('businessAttributeDefs')) || null) : null; - } - if (def || Globals[this.value.type] || ( - this.value.tag ? - Globals[this.value.tag] ? - Globals[this.value.tag] : - Globals[Enums.addOnClassification[0]] : - undefined)) { - var attrObj = def ? Utils.getNestedSuperTypeObj({ data: def.toJSON(), collection: this.entityDefCollection, attrMerge: true }) : []; - if (this.value.type && (Globals[this.value.type] || Globals[Enums.addOnEntities[0]])) { - systemAttr = (Globals[this.value.type] || Globals[Enums.addOnEntities[0]]).attributeDefs; - } - if (this.value.tag && (Globals[this.value.tag] || Globals[Enums.addOnClassification[0]])) { - systemAttr = (Globals[this.value.tag] || Globals[Enums.addOnClassification[0]]).attributeDefs; - } - attrObj = attrObj.concat(systemAttr); - if (businessAttributes) { - _.each(businessAttributes, function(businessMetadata, businessMetadataName) { - _.each(businessMetadata, function(attr, index) { - var attribute = attr; - attribute.isBusinessAttributes = true; - attribute.name = businessMetadataName + '.' + attribute.name; - businessMetadataAttr.push(attribute); - }) - }) - } - attrObj = attrObj.concat(businessMetadataAttr); - _.each(attrObj, function(obj, key) { - var key = obj.name, - isRenderable = _.contains(columnToShow, key), - isSortable = obj.typeName.search(/(array|map)/i) == -1; - if (key == "name" || key == "description" || key == "owner") { - if (columnToShow) { - col[key].renderable = isRenderable; - } - return; - } - if (key == "__historicalGuids" || key == "__classificationsText" || key == "__classificationNames" || key == "__propagatedClassificationNames") { - return; - } - col[obj.name] = { - label: Enums.systemAttributes[obj.name] ? Enums.systemAttributes[obj.name] : (_.escape(obj.isBusinessAttributes ? obj.name : obj.name.capitalize())), - cell: "Html", - headerCell: Backgrid.HeaderHTMLDecodeCell, - editable: false, - resizeable: true, - orderable: true, - sortable: isSortable, - renderable: isRenderable, - headerClassName: obj.isBusinessAttributes ? "no-capitalize" : "", - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var modelObj = model.toJSON(); - if (modelObj && modelObj.attributes && !_.isUndefined(modelObj.attributes[key])) { - var tempObj = { - 'scope': that, - 'attributeDefs': [obj], - 'valueObject': {}, - 'isTable': false - }; - if (key == "__labels") { - var values = modelObj.attributes[key] ? modelObj.attributes[key].split("|") : null, - valueOfArray = []; - if (values) { - if (values[values.length - 1] === "") { values.pop(); } - if (values[0] === "") { values.shift(); } - _.each(values, function(names) { - valueOfArray.push('' + _.escape(names) + ''); - }); - return valueOfArray.join(' '); - } - } - if (key == "__customAttributes") { - var customAttributes = modelObj.attributes[key] ? JSON.parse(modelObj.attributes[key]) : null, - valueOfArray = []; - if (customAttributes) { - _.each(Object.keys(customAttributes), function(value, index) { - valueOfArray.push('' + _.escape(value) + ' : ' + _.escape(Object.values(customAttributes)[index]) + ''); - }); - return valueOfArray.join(' '); - } - } - tempObj.valueObject[key] = modelObj.attributes[key]; - var tablecolumn = CommonViewFunction.propertyTable(tempObj); - if (_.isArray(modelObj.attributes[key])) { - var column = $("
        " + tablecolumn + "
        ") - if (tempObj.valueObject[key].length > 2) { - column.addClass("toggleList semi-collapsed").append("Show More"); - } - return column; - } - return tablecolumn; - } - } - }) - }; - }); - } - } - } - return this.searchCollection.constructor.getTableCols(col, this.searchCollection); - }, - onClickLoadMore: function() { - var that = this; - this.$el.on('click', "[data-id='load-more-columns']", function(event) { - event.stopPropagation(); - event.stopImmediatePropagation(); - var $this = $(this), - $toggleList = $(this).parents('.toggleList'); - if ($toggleList.length) { - if ($toggleList.hasClass('semi-collapsed')) { - $toggleList.removeClass('semi-collapsed'); - $this.text("Show Less"); - } else { - $toggleList.addClass('semi-collapsed'); - $this.text("Show More"); - } - } - }); - }, - getDaynamicColumns: function(valueObj) { - var that = this, - col = {}; - if (valueObj && valueObj.length) { - var firstObj = _.first(valueObj); - _.each(_.keys(firstObj), function(key) { - col[key] = { - label: key.capitalize(), - cell: "Html", - editable: false, - resizeable: true, - orderable: true, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var modelObj = model.toJSON(); - if (key == "name") { - var nameHtml = "", - name = _.escape(modelObj[key]); - if (modelObj.guid) { - nameHtml = '' + name + ''; - } else { - nameHtml = '' + name + ''; - } - if (modelObj.status && Enums.entityStateReadOnly[modelObj.status]) { - nameHtml += ''; - return ''; - } - return nameHtml; - } else if (modelObj && !_.isUndefined(modelObj[key])) { - var tempObj = { - 'scope': that, - // 'attributeDefs': - 'valueObject': {}, - 'isTable': false - }; - tempObj.valueObject[key] = modelObj[key]; - return CommonViewFunction.propertyTable(tempObj); - } - } - }) - }; - }); - } - return this.searchCollection.constructor.getTableCols(col, this.searchCollection); - }, - getTagCol: function(options) { - var that = this, - columnToShow = options.columnToShow, - col = options.col; - if (col) { - col['tag'] = { - label: "Classifications", - cell: "Html", - editable: false, - sortable: false, - resizeable: true, - orderable: true, - renderable: (columnToShow ? _.contains(columnToShow, 'tag') : true), - className: 'searchTag', - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var obj = model.toJSON(); - if (obj.guid == "-1") { - return - } - if (obj.status && Enums.entityStateReadOnly[obj.status]) { - return '
        ' + CommonViewFunction.tagForTable(obj); + '
        '; - } else { - return CommonViewFunction.tagForTable(obj); - } - - } - }) - }; - } - }, - getTermCol: function(options) { - var that = this, - columnToShow = options.columnToShow, - col = options.col; - if (col) { - col['term'] = { - label: "Term", - cell: "Html", - editable: false, - sortable: false, - resizeable: true, - orderable: true, - renderable: (columnToShow ? _.contains(columnToShow, 'term') : true), - className: 'searchTag', - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var obj = model.toJSON(); - if (obj.guid == "-1") { - return - } - if (obj.typeName && !(_.startsWith(obj.typeName, "AtlasGlossary"))) { - if (obj.status && Enums.entityStateReadOnly[obj.status]) { - return '
        ' + CommonViewFunction.termForTable(obj); + '
        '; - } else { - return CommonViewFunction.termForTable(obj); - } - } - } - }) - }; - } - }, - addTagModalView: function(guid, multiple, entityCount) { - var that = this; - require(['views/tag/AddTagModalView'], function(AddTagModalView) { - var view = new AddTagModalView({ - guid: guid, - multiple: multiple, - entityCount: entityCount, - callback: function() { - that.multiSelectEntity = []; - that.fetchCollection(); - if (that.searchVent) { - that.searchVent.trigger('entityList:refresh'); - } - }, - tagList: that.getTagList(guid, multiple), - showLoader: that.showLoader.bind(that), - hideLoader: that.hideLoader.bind(that), - collection: that.classificationDefCollection, - enumDefCollection: that.enumDefCollection - }); - }); - }, - getTagList: function(guid, multiple) { - var that = this; - if (!multiple || multiple.length === 0) { - var model = this.searchCollection.find(function(item) { - var obj = item.toJSON(); - if (obj.guid === guid) { - return true; - } - }); - if (model) { - var obj = model.toJSON(); - } else { - return []; - } - return _.compact(_.map(obj.classifications, function(val) { - if (val.entityGuid == guid) { - return val.typeName - } - })); - } else { - return []; - } - }, - showLoader: function() { - this.$('.fontLoader:not(.for-ignore)').addClass('show'); - this.$('.tableOverlay').addClass('show'); - }, - hideLoader: function(options) { - this.$('.fontLoader:not(.for-ignore)').removeClass('show'); - options && options.type === 'error' ? this.$('.ellipsis-with-margin,.pagination-box').hide() : this.$('.ellipsis-with-margin,.pagination-box').show(); // only show for first time and hide when type is error - this.$('.tableOverlay').removeClass('show'); - }, - onClickAddTag: function(e) { - var guid = "", - that = this, - isTagMultiSelect = $(e.currentTarget).hasClass('multiSelectTag'); - if (isTagMultiSelect && this.multiSelectEntity && this.multiSelectEntity.length) { - that.addTagModalView(guid, this.multiSelectEntity, this.activeEntityCountSelected); - } else { - guid = that.$(e.currentTarget).data("guid"); - that.addTagModalView(guid); - } - }, - //This function checks for the lenght of Available terms and modal for adding terms is displayed accordingly. - assignTermModalView: function(glossaryCollection, obj) { - var that = this, - terms = 0; - _.each(glossaryCollection.fullCollection.models, function(model) { - if (model.get('terms')) { - terms += model.get('terms').length; - }; - }); - if (terms) { - require(['views/glossary/AssignTermLayoutView'], function(AssignTermLayoutView) { - var view = new AssignTermLayoutView({ - guid: obj.guid, - multiple: obj.multiple, - associatedTerms: obj.associatedTerms, - callback: function() { - that.multiSelectEntity = []; - that.fetchCollection(); - }, - glossaryCollection: glossaryCollection, - }); - }); - } else { - Utils.notifyInfo({ - content: "There are no available terms" - }); - } - }, - onClickAddTermBtn: function(e) { - var that = this, - guid = "", - entityGuid = $(e.currentTarget).data("guid"), - obj = { - guid: entityGuid, - multiple: undefined, - associatedTerms: undefined, - }, - isTermMultiSelect = $(e.currentTarget).hasClass('multiSelectTerm'); - - that.assignTermModalView(this.glossaryCollection, obj); - if (isTermMultiSelect && this.multiSelectEntity && this.multiSelectEntity.length) { - obj.multiple = this.multiSelectEntity; - } else if (entityGuid) { - obj.associatedTerms = this.searchCollection.find({ guid: entityGuid }).get('meanings'); - } - }, - onClickTagCross: function(e) { - var that = this, - tagName = $(e.target).data("name"), - guid = $(e.target).data("guid"), - entityGuid = $(e.target).data("entityguid"), - assetName = $(e.target).data("assetname"); - CommonViewFunction.deleteTag({ - tagName: tagName, - guid: guid, - associatedGuid: guid != entityGuid ? entityGuid : null, - msg: "
        Remove: " + "" + _.escape(tagName) + " assignment from " + _.escape(assetName) + " ?
        ", - titleMessage: Messages.removeTag, - okText: "Remove", - showLoader: that.showLoader.bind(that), - hideLoader: that.hideLoader.bind(that), - callback: function() { - that.fetchCollection(); - if (that.searchVent) { - that.searchVent.trigger('entityList:refresh'); - } - } - }); - - }, - onClickTermCross: function(e) { - var $el = $(e.target), - termGuid = $el.data('termguid'), - guid = $el.data('guid'), - termName = $(e.currentTarget).text(), - assetname = $el.data('assetname'), - meanings = this.searchCollection.find({ "guid": guid }).get("meanings"), - that = this, - termObj = _.find(meanings, { termGuid: termGuid }); - CommonViewFunction.removeCategoryTermAssociation({ - termGuid: termGuid, - model: { - guid: guid, - relationshipGuid: termObj.relationGuid - }, - collection: that.glossaryCollection, - msg: "
        Remove: " + "" + _.escape(termName) + " assignment from " + _.escape(assetname) + "?
        ", - titleMessage: Messages.glossary.removeTermfromEntity, - isEntityView: true, - buttonText: "Remove", - callback: function() { - that.fetchCollection(); - } - }); - }, - onClicknextData: function() { - this.offset = this.offset + this.limit; - _.extend(this.searchCollection.queryParams, { - offset: this.offset - }); - if (this.value) { - this.value.pageOffset = this.offset; - this.triggerUrl(); - } - this.fetchCollection(null, { - next: true - }); - }, - onClickpreviousData: function() { - this.offset = this.offset - this.limit; - if (this.offset <= -1) { - this.offset = 0; - } - _.extend(this.searchCollection.queryParams, { - offset: this.offset - }); - if (this.value) { - this.value.pageOffset = this.offset; - this.triggerUrl(); - } - this.fetchCollection(null, { - previous: true - }); - }, - onClickCreateEntity: function(e) { - var that = this; - $(e.currentTarget).blur(); - require([ - 'views/entity/CreateEntityLayoutView' - ], function(CreateEntityLayoutView) { - var view = new CreateEntityLayoutView({ - entityDefCollection: that.entityDefCollection, - typeHeaders: that.typeHeaders, - searchVent: that.searchVent, - callback: function() { - that.fetchCollection(); - } - }); - }); - }, - onCheckExcludeIncludeResult: function(e) { - var flag = false, - val = $(e.currentTarget).attr('data-value'); - if (e.target.checked) { - flag = true; - } - if (this.value) { - this.value[val] = flag; - this.triggerUrl(); - } - _.extend(this.searchCollection.queryParams, { limit: this.limit, offset: this.offset }); - this.fetchCollection(); - - }, - changePageLimit: function(e, obj) { - if (!obj || (obj && !obj.skipViewChange)) { - var limit = parseInt(this.ui.showPage.val()); - if (limit == 0) { - this.ui.showPage.data('select2').$container.addClass('has-error'); - return; - } else { - this.ui.showPage.data('select2').$container.removeClass('has-error'); - } - this.limit = limit; - this.offset = 0; - if (this.value) { - this.value.pageLimit = this.limit; - this.value.pageOffset = this.offset; - this.triggerUrl(); - } - _.extend(this.searchCollection.queryParams, { limit: this.limit, offset: this.offset }); - this.fetchCollection(); - } - }, - gotoPagebtn: function(e) { - var that = this; - var goToPage = parseInt(this.ui.gotoPage.val()); - if (!(_.isNaN(goToPage) || goToPage <= -1)) { - if (this.finalPage && this.finalPage < goToPage) { - Utils.notifyInfo({ - html: true, - content: Messages.search.noRecordForPage + '' + Utils.getNumberSuffix({ number: goToPage, sup: true }) + ' page' - }); - return; - } - this.offset = (goToPage - 1) * this.limit; - if (this.offset <= -1) { - this.offset = 0; - } - _.extend(this.searchCollection.queryParams, { limit: this.limit, offset: this.offset }); - if (this.offset == (this.pageFrom - 1)) { - Utils.notifyInfo({ - content: Messages.search.onSamePage - }); - } else { - if (this.value) { - this.value.pageOffset = this.offset; - this.triggerUrl(); - } - // this.offset is updated in gotoPagebtn function so use next button calculation. - this.fetchCollection(null, { 'next': true }); - } - } - } - }); - return SearchResultLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/search/save/SaveModalLayoutView.js b/dashboardv2/public/js/views/search/save/SaveModalLayoutView.js deleted file mode 100644 index 350758874c3..00000000000 --- a/dashboardv2/public/js/views/search/save/SaveModalLayoutView.js +++ /dev/null @@ -1,123 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/search/save/SaveModalLayoutView_tmpl', - 'utils/Utils', - 'modules/Modal', - 'utils/UrlLinks', - 'platform', - 'models/VSearch', - 'utils/CommonViewFunction', - 'utils/Messages' -], function(require, Backbone, SaveModalLayoutViewTmpl, Utils, Modal, UrlLinks, platform, VSearch, CommonViewFunction, Messages) { - - - var SaveModalLayoutView = Backbone.Marionette.LayoutView.extend({ - _viewName: 'SaveModalLayoutView', - template: SaveModalLayoutViewTmpl, - regions: {}, - ui: { - saveAsName: "[data-id='saveAsName']" - }, - templateHelpers: function() { - return { - selectedModel: this.selectedModel ? this.selectedModel.toJSON() : null - }; - }, - events: function() { - var events = {}; - return events; - }, - initialize: function(options) { - var that = this; - _.extend(this, _.pick(options, 'selectedModel', 'collection', 'getValue', 'isBasic', 'saveObj')); - - this.model = new VSearch(); - if (this.saveObj) { - this.onCreateButton(); - } else { - var modal = new Modal({ - title: (this.selectedModel ? 'Update' : 'Create') + ' your favorite search ' + (this.selectedModel ? 'name' : ''), - content: this, - cancelText: "Cancel", - okCloses: false, - okText: this.selectedModel ? 'Update' : 'Create', - allowCancel: true - }).open(); - modal.$el.find('button.ok').attr("disabled", "true"); - modal.on('ok', function() { - modal.$el.find('button.ok').attr("disabled", "true"); - that.onCreateButton(modal); - }); - modal.on('closeModal', function() { - modal.trigger('cancel'); - }); - } - }, - onCreateButton: function(modal) { - var that = this, - obj = { name: this.ui.saveAsName.val ? this.ui.saveAsName.val() : null }; - if (this.selectedModel) { - // Update Name only. - var saveObj = this.selectedModel.toJSON(); - saveObj.name = obj.name; - } else { - obj.value = this.getValue(); - if (this.saveObj) { - // Save search Filter - _.extend(obj, this.saveObj); - } - var saveObj = CommonViewFunction.generateObjectForSaveSearchApi(obj); - if (this.isBasic) { - saveObj['searchType'] = "BASIC"; - } else { - saveObj['searchType'] = "ADVANCED"; - } - } - this.model.urlRoot = UrlLinks.saveSearchApiUrl(); - this.model.save(saveObj, { - type: (saveObj.guid ? 'PUT' : 'POST'), - success: function(model, data) { - if (that.collection) { - if (saveObj.guid) { - var collectionRef = that.collection.find({ guid: data.guid }); - if (collectionRef) { - collectionRef.set(data); - } - Utils.notifySuccess({ - content: obj.name + Messages.getAbbreviationMsg(false, "editSuccessMessage") - }); - } else { - that.collection.add(data); - Utils.notifySuccess({ - content: obj.name + Messages.getAbbreviationMsg(false, "addSuccessMessage") - }); - } - } - - } - }); - if (modal) { - modal.trigger('cancel'); - } - } - }); - return SaveModalLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/search/save/SaveSearchItemView.js b/dashboardv2/public/js/views/search/save/SaveSearchItemView.js deleted file mode 100644 index a86eff4e099..00000000000 --- a/dashboardv2/public/js/views/search/save/SaveSearchItemView.js +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -define(['require', - 'backbone', - 'hbs!tmpl/search/save/SaveSearchItemView_tmpl', - 'utils/UrlLinks', - 'utils/Utils', - 'utils/CommonViewFunction', - 'utils/Messages' -], function(require, Backbone, SaveSearchItemViewTmpl, UrlLinks, Utils, CommonViewFunction, Messages) { - 'use strict'; - return Backbone.Marionette.ItemView.extend({ - template: SaveSearchItemViewTmpl, - tagName: 'li', - className: 'parent-node', - ui: { - stateChange: '.item', - tools: '.tools' - }, - events: function() { - var events = {}; - events['click ' + this.ui.stateChange] = 'stateChange'; - events['click ' + this.ui.tools] = function(e) { - e.stopPropagation(); - }; - return events; - }, - initialize: function(options) { - _.extend(this, _.pick(options, 'collection', 'typeHeaders', 'applyValue', 'fetchFavioriteCollection', 'isBasic', 'classificationDefCollection', 'entityDefCollection', 'searchTypeObj')); - this.model.id = this.model.get('guid'); - this.model.idAttribute = 'guid'; - }, - onRender: function() { - this.showToolTip(); - }, - stateChange: function() { - this.applyValue(this.model, this.searchTypeObj); - this.trigger('item:clicked'); // to enable save button - this.ui.stateChange.parent('li').addClass('active').siblings().removeClass('active'); - }, - modelEvents: { - 'change': 'render' - }, - showToolTip: function(e) { - var that = this; - Utils.generatePopover({ - el: this.$('.saveSearchPopover'), - viewFixedPopover: true, - popoverOptions: { - content: function() { - return ""; - } - } - }); - } - }); -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/search/save/SaveSearchView.js b/dashboardv2/public/js/views/search/save/SaveSearchView.js deleted file mode 100644 index 436d83db7e9..00000000000 --- a/dashboardv2/public/js/views/search/save/SaveSearchView.js +++ /dev/null @@ -1,209 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/search/save/SaveSearchView_tmpl', - 'views/search/save/SaveSearchItemView', - 'collection/VSearchList', - 'utils/Utils', - 'utils/UrlLinks', - 'utils/CommonViewFunction', - 'utils/Messages' -], function(require, Backbone, SaveSearchViewTmpl, SaveSearchItemView, VSearchList, Utils, UrlLinks, CommonViewFunction, Messages) { - 'use strict'; - - return Backbone.Marionette.CompositeView.extend({ - template: SaveSearchViewTmpl, - childView: SaveSearchItemView, - childViewContainer: "[data-id='itemViewContent']", - ui: { - saveAs: "[data-id='saveAsBtn']", - save: "[data-id='saveBtn']" - }, - childViewOptions: function() { - return { - collection: this.collection, - typeHeaders: this.typeHeaders, - applyValue: this.applyValue, - isBasic: this.isBasic, - classificationDefCollection: this.classificationDefCollection, - entityDefCollection: this.entityDefCollection, - fetchFavioriteCollection: this.fetchCollection.bind(this), - searchTypeObj: this.searchTypeObj - }; - }, - childEvents: function() { - return { - "item:clicked": function() { - this.ui.save.attr('disabled', false); - } - } - }, - events: function() { - var events = {}; - events['click ' + this.ui.saveAs] = "saveAs"; - events['click ' + this.ui.save] = "save"; - return events; - }, - initialize: function(options) { - var that = this; - _.extend(this, _.pick(options, 'collection', 'value', 'searchVent', 'typeHeaders', 'applyValue', 'getValue', 'isBasic', 'fetchCollection', 'classificationDefCollection', 'entityDefCollection')); - this.searchTypeObj = { - 'searchType': 'dsl', - 'dslChecked': 'true' - } - if (this.isBasic) { - this.searchTypeObj.dslChecked = false; - this.searchTypeObj.searchType = 'basic'; - } - }, - onRender: function() { - this.bindEvents(); - }, - bindEvents: function() { - var that = this; - this.listenTo(this.collection, "add reset error remove", function(model, collection) { - this.$('.fontLoader-relative').hide(); - if (this.collection && this.collection.length) { - this.$(".noFavoriteSearch").hide(); - } else { - this.$(".noFavoriteSearch").show(); - } - }, this); - $('body').on('click', '.saveSearchPopoverList_' + (this.isBasic ? 'isBasic' : 'isAdvance') + ' li', function(e) { - that.$('.saveSearchPopover').popover('hide'); - var id = $(this).parent('ul').data('id'); - that[$(this).find('a').data('fn')]({ - 'model': that.collection.find({ 'guid': id }) - }); - }); - }, - saveAs: function(e) { - var value = this.getValue(); - if (value && (value.type || value.tag || value.query || value.term)) { - this.callSaveModalLayoutView({ - 'collection': this.collection, - 'getValue': this.getValue, - 'isBasic': this.isBasic - }); - } else { - Utils.notifyInfo({ - content: Messages.search.favoriteSearch.notSelectedSearchFilter - }) - } - }, - save: function() { - var that = this, - obj = {}, - notifyObj = { - modal: true, - html: true, - ok: function(argument) { - that.callSaveModalLayoutView({ - 'saveObj': obj, - 'collection': that.collection, - 'getValue': that.getValue, - 'isBasic': that.isBasic - }) - }, - cancel: function(argument) {} - }, - selectedEl = this.$('.saveSearchList li.active').find('div.item'); - obj.name = selectedEl.find('a').text(); - obj.guid = selectedEl.data('id'); - if (selectedEl && selectedEl.length) { - notifyObj['text'] = Messages.search.favoriteSearch.save + " " + _.escape(obj.name) + " ?"; - Utils.notifyConfirm(notifyObj); - } else { - Utils.notifyInfo({ - content: Messages.search.favoriteSearch.notSelectedFavoriteElement - }) - } - }, - callSaveModalLayoutView: function(options) { - require([ - 'views/search/save/SaveModalLayoutView' - ], function(SaveModalLayoutView) { - new SaveModalLayoutView(options); - }); - }, - onSearch: function(options) { - if (options && options.model) { - var searchParameters = options.model.toJSON().searchParameters, - params = CommonViewFunction.generateUrlFromSaveSearchObject({ - value: { "searchParameters": searchParameters, "uiParameters": options.model.get('uiParameters') }, - classificationDefCollection: this.classificationDefCollection, - entityDefCollection: this.entityDefCollection - }); - Utils.setUrl({ - url: '#!/search/searchResult', - urlParams: _.extend({}, this.searchTypeObj, params), - mergeBrowserUrl: false, - trigger: true, - updateTabState: true - }); - } - }, - onRename: function(options) { - if (options && options.model) { - var that = this; - require([ - 'views/search/save/SaveModalLayoutView' - ], function(SaveModalLayoutView) { - new SaveModalLayoutView({ 'selectedModel': options.model, 'collection': that.collection, 'getValue': that.getValue, 'isBasic': that.isBasic }); - }); - } - }, - onDelete: function(options) { - if (options && options.model) { - var that = this; - var notifyObj = { - modal: true, - html: true, - text: Messages.conformation.deleteMessage + "" + _.escape(options.model.get('name')) + "" + " ?", - ok: function(obj) { - that.notificationModal = obj; - obj.showButtonLoader(); - that.onDeleteNotifyOk(options); - }, - okCloses: false, - cancel: function(argument) {} - } - Utils.notifyConfirm(notifyObj); - } - }, - onDeleteNotifyOk: function(options) { - var that = this; - options.model.urlRoot = UrlLinks.saveSearchApiUrl(); - options.model.destroy({ - wait: true, - success: function(model, data) { - if (that.collection) { - that.collection.remove(model); - } - that.notificationModal.hideButtonLoader(); - that.notificationModal.remove(); - Utils.notifySuccess({ - content: options.model.get('name') + Messages.getAbbreviationMsg(false, 'deleteSuccessMessage') - }); - } - }); - } - }); -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/site/AboutAtlas.js b/dashboardv2/public/js/views/site/AboutAtlas.js deleted file mode 100644 index b6c26723853..00000000000 --- a/dashboardv2/public/js/views/site/AboutAtlas.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/site/AboutAtlas_tmpl', - 'modules/Modal', - 'models/VCommon', - 'utils/UrlLinks', -], function(require, Backbone, AboutAtlasTmpl, Modal, VCommon, UrlLinks) { - 'use strict'; - - var AboutAtlasView = Backbone.Marionette.LayoutView.extend( - /** @lends AboutAtlasView */ - { - template: AboutAtlasTmpl, - /** Layout sub regions */ - regions: {}, - /** ui selector cache */ - ui: { - atlasVersion: "[data-id='atlasVersion']" - }, - /** ui events hash */ - events: function() {}, - /** - * intialize a new AboutAtlasView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, options); - var modal = new Modal({ - title: 'Apache Atlas', - content: this, - okCloses: true, - showFooter: true, - allowCancel: false, - }).open(); - - modal.on('closeModal', function() { - modal.trigger('cancel'); - }); - }, - bindEvents: function() {}, - onRender: function() { - var that = this; - var url = UrlLinks.versionApiUrl(); - var VCommonModel = new VCommon(); - VCommonModel.aboutUs(url, { - success: function(data) { - var str = "Version : " + _.escape(data.Version); - that.ui.atlasVersion.html(str); - }, - complete: function() {} - }); - }, - - }); - return AboutAtlasView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/site/DebugMetricsTableLayoutView.js b/dashboardv2/public/js/views/site/DebugMetricsTableLayoutView.js deleted file mode 100644 index 407e489adb9..00000000000 --- a/dashboardv2/public/js/views/site/DebugMetricsTableLayoutView.js +++ /dev/null @@ -1,201 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/site/DebugMetricsTableLayoutView_tmpl', - 'utils/UrlLinks', - 'collection/VEntityList', - 'utils/CommonViewFunction', - 'utils/Utils' -], function(require, Backbone, DebugMetricsTableLayoutViewTmpl, UrlLinks, VEntityList, CommonViewFunction, Utils) { - 'use strict'; - - var DebugMetricsTableLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends DebugMetricsTableLayoutView */ - { - _viewName: 'DebugMetricsTableLayoutView', - template: DebugMetricsTableLayoutViewTmpl, - /** Layout sub regions */ - regions: { - RDebugMetricsTableLayoutView: "#r_debugMetricsTableLayoutView" - }, - /** ui selector cache */ - ui: { - refreshMetricsBtn: '[data-id="refreshMetricsBtn"]', - metricsInfoBtn: '[data-id="metricsInfo"]' - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.refreshMetricsBtn] = function(e) { - this.currPage = 1; - this.limit = 26; - this.debugMetricsCollection.state.pageSize = 25; - this.debugMetricsCollection.state.currentPage = 0; - this.fetchMetricData(); - }; - events["click " + this.ui.metricsInfoBtn] = 'metricsInfo'; - return events; - }, - /** - * intialize a new DebugMetricsTableLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, options); - var that = this; - this.DATA_MAX_LENGTH = 25; - this.debugMetricsCollection = new VEntityList(); - this.debugMetricsCollection.url = UrlLinks.debugMetricsApiUrl(); - this.debugMetricsCollection.modelAttrName = "data"; - this.commonTableOptions = { - collection: this.debugMetricsCollection, - includeFilter: false, - includePagination: true, - includeFooterRecords: true, - includePageSize: true, - includeGotoPage: true, - includeAtlasTableSorting: true, - includeTableLoader: true, - includeColumnManager: false, - gridOpts: { - className: "table table-hover backgrid table-quickMenu", - emptyText: 'No records found!' - }, - filterOpts: {}, - paginatorOpts: {} - }; - this.currPage = 1; - this.limit = 26; - }, - bindEvents: function() { - var that = this; - }, - onRender: function() { - this.bindEvents(); - this.$('.debug-metrics-table').show(); - this.fetchMetricData(); - }, - metricsInfo: function(e) { - require([ - 'views/site/MetricsUIInfoView', - 'modules/Modal' - ], function(MetricsUIInfoView, Modal) { - var view = new MetricsUIInfoView(); - var modal = new Modal({ - title: 'Debug Metrics', - content: view, - okCloses: true, - showFooter: false, - allowCancel: false - }).open(); - view.on('closeModal', function() { - modal.trigger('cancel'); - }); - }); - }, - fetchMetricData: function(options) { - var that = this; - this.debugMetricsCollection.fetch({ - success: function(data) { - var data = _.first(data.toJSON()), - metricsDataKeys = data ? Object.keys(data) : null; - that.debugMetricsCollection.fullCollection.reset(); - _.each(metricsDataKeys.sort(), function(keyName) { - that.debugMetricsCollection.fullCollection.add(data[keyName]); - }); - }, - complete: function(data) { - that.renderTableLayoutView(); - } - }); - }, - renderTableLayoutView: function() { - var that = this; - require(['utils/TableLayout'], function(TableLayout) { - var cols = new Backgrid.Columns(that.getAuditTableColumns()); - that.RDebugMetricsTableLayoutView.show(new TableLayout(_.extend({}, that.commonTableOptions, { - columns: cols - }))); - if (!(that.debugMetricsCollection.models.length < that.limit)) { - that.RDebugMetricsTableLayoutView.$el.find('table tr').last().hide(); - } - }); - }, - millisecondsToSeconds: function(rawValue) { - return parseFloat((rawValue % 60000) / 1000).toFixed(3); - }, - getAuditTableColumns: function() { - var that = this; - return this.debugMetricsCollection.constructor.getTableCols({ - name: { - label: "Name", - cell: "html", - sortable: true, - editable: false - }, - numops: { - label: "Count", - cell: "html", - toolTip: "Number of times the API has been hit since Atlas started", - sortable: true, - editable: false - }, - minTime: { - label: "Min Time (secs)", - cell: "html", - toolTip: "Minimum API execution time since Atlas started", - sortable: true, - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return that.millisecondsToSeconds(rawValue); - } - }) - }, - maxTime: { - label: "Max Time (secs)", - cell: "html", - toolTip: "Maximum API execution time since Atlas started", - sortable: true, - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return that.millisecondsToSeconds(rawValue); - } - }) - }, - avgTime: { - label: "Average Time (secs)", - cell: "html", - toolTip: "Average time taken to execute by an API within an interval of time", - sortable: true, - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - return that.millisecondsToSeconds(rawValue); - } - }) - } - }, this.debugMetricsCollection); - - } - }); - return DebugMetricsTableLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/site/Header.js b/dashboardv2/public/js/views/site/Header.js deleted file mode 100644 index ffb582ed4bb..00000000000 --- a/dashboardv2/public/js/views/site/Header.js +++ /dev/null @@ -1,333 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'hbs!tmpl/site/Header', - 'utils/CommonViewFunction', - 'utils/Globals', - 'utils/Utils', - 'utils/UrlLinks', - 'jquery-ui' -], function(require, tmpl, CommonViewFunction, Globals, Utils, UrlLinks) { - 'use strict'; - - var Header = Marionette.LayoutView.extend({ - template: tmpl, - regions: {}, - templateHelpers: function() { - return { - glossaryImportTempUrl: UrlLinks.glossaryImportTempUrl(), - businessMetadataImportTempUrl: UrlLinks.businessMetadataImportTempUrl(), - apiDocUrl: UrlLinks.apiDocUrl(), - isDebugMetricsEnabled: Globals.isDebugMetricsEnabled - }; - }, - ui: { - backButton: "[data-id='backButton']", - menuHamburger: "[data-id='menuHamburger']", - globalSearch: "[data-id='globalSearch']", - clearGlobalSearch: "[data-id='clearGlobalSearch']", - signOut: "[data-id='signOut']", - administrator: "[data-id='administrator']", - showDebug: "[data-id='showDebug']", - uiSwitch: "[data-id='uiSwitch']", - glossaryImport: "[data-id='glossaryImport']", - businessMetadataImport: "[data-id='businessMetadataImport']" - }, - events: function() { - var events = {}; - events['click ' + this.ui.backButton] = function() { - Utils.backButtonClick(); - }; - events['click ' + this.ui.clearGlobalSearch] = function() { - this.ui.globalSearch.val(""); - this.ui.globalSearch.autocomplete("search"); - this.ui.clearGlobalSearch.removeClass("in"); - }; - events['click ' + this.ui.menuHamburger] = function() { - this.setSearchBoxWidth({ - updateWidth: function(atlasHeaderWidth) { - return $('body').hasClass('full-screen') ? atlasHeaderWidth - 350 : atlasHeaderWidth + 350 - } - }); - $('body').toggleClass("full-screen"); - }; - events['click ' + this.ui.signOut] = function() { - Utils.localStorage.setValue("last_ui_load", "v1"); - var path = Utils.getBaseUrl(window.location.pathname); - window.location = path + "/logout.html"; - }; - events["click " + this.ui.uiSwitch] = function() { - var path = Utils.getBaseUrl(window.location.pathname) + "/n/index.html"; - if (window.location.hash.length > 2) { - path += window.location.hash; - } - window.location.href = path; - }; - events['click ' + this.ui.administrator] = function() { - Utils.setUrl({ - url: "#!/administrator", - mergeBrowserUrl: false, - trigger: true, - updateTabState: true - }); - }; - events['click ' + this.ui.glossaryImport] = function() { - this.onClickImport(true); - }; - events['click ' + this.ui.businessMetadataImport] = function() { - this.onClickImport() - }; - events['click ' + this.ui.showDebug] = function() { - Utils.setUrl({ - url: "#!/debugMetrics", - mergeBrowserUrl: false, - trigger: true, - updateTabState: true - }); - }; - - return events; - }, - initialize: function(options) { - this.bindEvent(); - this.options = options; - }, - setSearchBoxWidth: function(options) { - var atlasHeaderWidth = this.$el.find(".atlas-header").width(), - minusWidth = (Utils.getUrlState.isDetailPage() || Utils.getUrlState.isBSDetail()) ? 360 : 210; - if (options && options.updateWidth) { - atlasHeaderWidth = options.updateWidth(atlasHeaderWidth); - } - if (atlasHeaderWidth > minusWidth) { - this.$el.find(".global-search-container").width(atlasHeaderWidth - minusWidth); - } - }, - bindEvent: function() { - var that = this; - $(window).resize(function() { - that.setSearchBoxWidth(); - }); - }, - onRender: function() { - var that = this; - if (Globals.userLogedIn.status) { - that.$('.userName').html(Globals.userLogedIn.response.userName); - } - this.initializeGlobalSearch(); - }, - onShow: function() { - this.setSearchBoxWidth(); - }, - onBeforeDestroy: function() { - this.ui.globalSearch.atlasAutoComplete("destroy"); - }, - manualRender: function() { - this.setSearchBoxWidth(); - }, - fetchSearchData: function(options) { - var that = this, - request = options.request, - response = options.response, - inputEl = options.inputEl, - term = request.term, - data = {}, - sendResponse = function() { - var query = data.query, - suggestions = data.suggestions; - if (query !== undefined && suggestions !== undefined) { - inputEl.siblings('span.fa-refresh').removeClass("fa-refresh fa-spin-custom").addClass("fa-search"); - response(data); - } - }; - $.ajax({ - url: UrlLinks.searchApiUrl('quick'), - contentType: 'application/json', - data: { - "query": term, - "limit": 5, - "offset": 0 - }, - cache: true, - success: function(response) { - var rData = response.searchResults.entities || []; - data.query = { category: "entities", data: rData, order: 1 }; - sendResponse(); - } - }); - - $.ajax({ - url: UrlLinks.searchApiUrl('suggestions'), - contentType: 'application/json', - data: { - "prefixString": term - }, - cache: true, - success: function(response) { - var rData = response.suggestions || []; - data.suggestions = { category: "suggestions", data: rData, order: 2 }; - sendResponse(); - } - }); - }, - getSearchString: function(str) { - if (str && str.length) { - return (str.match(/[+\-&|!(){}[\]^"~*?:/]/g) === null ? (str + "*") : str); - } else { - return str; - } - }, - triggerBuasicSearch: function(query) { - Utils.setUrl({ - url: '#!/search/searchResult?query=' + encodeURIComponent(query) + '&searchType=basic', - mergeBrowserUrl: false, - trigger: true, - updateTabState: true - }); - }, - initializeGlobalSearch: function() { - var that = this; - this.ui.globalSearch.atlasAutoComplete({ - minLength: 1, - autoFocus: false, - search: function() { - $(this).siblings('span.fa-search').removeClass("fa-search").addClass("fa-refresh fa-spin-custom"); - }, - select: function(event, ui) { - var item = ui && ui.item; - event.preventDefault(); - event.stopPropagation(); - var $el = $(this); - if (_.isString(item)) { - $el.val(item); - $el.data("valSelected", true); - that.triggerBuasicSearch(item); - } else if (_.isObject(item) && item.guid) { - Utils.setUrl({ - url: '#!/detailPage/' + item.guid, - mergeBrowserUrl: false, - trigger: true - }); - } - $el.blur(); - return true; - }, - source: function(request, response) { - that.fetchSearchData({ - request: request, - response: response, - inputEl: this.element - }); - } - }).focus(function() { - $(this).atlasAutoComplete("search"); - }).keyup(function(event) { - if ($(this).val().trim() === "") { - that.ui.clearGlobalSearch.removeClass("in"); - } else { - that.ui.clearGlobalSearch.addClass("in"); - if (event.keyCode == 13) { - if ($(this).data("valSelected") !== true) { - that.triggerBuasicSearch($(this).val()); - } else { - $(this).data("valSelected", false); - } - } - } - }).atlasAutoComplete("instance")._renderItem = function(ul, searchItem) { - if (searchItem) { - var data = searchItem.data, - searchTerm = this.term, - getHighlightedTerm = function(resultStr) { - try { - return resultStr.replace(new RegExp(searchTerm, "gi"), function(foundStr) { - return "" + foundStr + ""; - }); - } catch (error) { - return resultStr; - } - } - if (data) { - if (data.length == 0) { - return $("
      • ") - .append("No " + searchItem.category + " found") - .appendTo(ul); - } else { - var items = []; - _.each(data, function(item) { - var li = null; - if (_.isObject(item)) { - item.itemText = Utils.getName(item) + " (" + item.typeName + ")"; - var options = {}, - table = ''; - if (item.serviceType === undefined) { - if (Globals.serviceTypeMap[item.typeName] === undefined && that.entityDefCollection) { - var defObj = that.entityDefCollection.fullCollection.find({ name: item.typeName }); - if (defObj) { - Globals.serviceTypeMap[item.typeName] = defObj.get("serviceType"); - } - } - } else if (Globals.serviceTypeMap[item.typeName] === undefined) { - Globals.serviceTypeMap[item.typeName] = item.serviceType; - } - item.serviceType = Globals.serviceTypeMap[item.typeName]; - options.entityData = item; - var img = $('').on("error", function(error, s) { - this.src = Utils.getEntityIconPath(_.extend(options, { errorUrl: this.src })); - }); - var span = $("" + (getHighlightedTerm(item.itemText)) + "") - .prepend(img); - li = $("
      • ") - .append(span); - } else { - li = $("
      • ") - .append("" + (getHighlightedTerm(_.escape(item))) + ""); - } - li.data("ui-autocomplete-item", item); - if (searchItem.category) { - items.push(li.attr("aria-label", searchItem.category + " : " + (_.isObject(item) ? item.itemText : item))); - } - }); - return ul.append(items); - } - } - } - }; - }, - onClickImport: function(isGlossary) { - var that = this; - require([ - 'views/import/ImportLayoutView' - ], function(ImportLayoutView) { - var view = new ImportLayoutView({ - callback: function() { - if (that.options.importVent) { - if (isGlossary) { - that.options.importVent.trigger("Import:Glossary:Update"); - } else { - that.options.importVent.trigger("Import:BM:Update"); - } - } - }, - isGlossary: isGlossary - }); - }); - } - }); - return Header; -}); diff --git a/dashboardv2/public/js/views/site/MetricsUIInfoView.js b/dashboardv2/public/js/views/site/MetricsUIInfoView.js deleted file mode 100644 index f46b5b84f57..00000000000 --- a/dashboardv2/public/js/views/site/MetricsUIInfoView.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/site/MetricsUIInfoView_tmpl', -], function(require, Backbone, MetricsUIInfoViewTmpl) { - - var MetricsUIInfoViewView = Backbone.Marionette.LayoutView.extend( - /** @lends MetricsUIInfoViewView */ - { - _viewName: 'MetricsUIInfoViewView', - - template: MetricsUIInfoViewTmpl, - - - - /** Layout sub regions */ - regions: {}, - - - /** ui selector cache */ - ui: { - - }, - /** ui events hash */ - events: function() { - var events = {}; - return events; - }, - /** - * intialize a new MetricsUIInfoViewView Layout - * @constructs - */ - initialize: function(options) { - - }, - bindEvents: function() {}, - onRender: function() { - - }, - - - }); - return MetricsUIInfoViewView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/site/SideNavLayoutView.js b/dashboardv2/public/js/views/site/SideNavLayoutView.js deleted file mode 100644 index e0f717a24cf..00000000000 --- a/dashboardv2/public/js/views/site/SideNavLayoutView.js +++ /dev/null @@ -1,140 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'hbs!tmpl/site/SideNavLayoutView_tmpl', - 'utils/Utils', - 'utils/Globals', - 'utils/UrlLinks' -], function(require, tmpl, Utils, Globals, UrlLinks) { - 'use strict'; - - var SideNavLayoutView = Marionette.LayoutView.extend({ - template: tmpl, - - regions: { - RTagLayoutView: "#r_tagLayoutView", - RSearchLayoutView: "#r_searchLayoutView", - RGlossaryLayoutView: "#r_glossaryLayoutView" - }, - ui: { - tabs: '.tabs li a', - }, - templateHelpers: function() { - return { - apiBaseUrl: UrlLinks.apiBaseUrl - }; - }, - events: function() { - var events = {}, - that = this; - events["click " + this.ui.tabs] = function(e) { - var urlString = "", - elementName = $(e.currentTarget).data(), - tabStateUrls = Globals.saveApplicationState.tabState, - urlStateObj = Utils.getUrlState, - hashUrl = Utils.getUrlState.getQueryUrl().hash; - - if (urlStateObj.isTagTab()) { - if (hashUrl != tabStateUrls.tagUrl) { - Globals.saveApplicationState.tabState.tagUrl = hashUrl; - } - } else if (urlStateObj.isSearchTab()) { - if (hashUrl != tabStateUrls.searchUrl) { - Globals.saveApplicationState.tabState.searchUrl = hashUrl; - } - } - - if (elementName.name == "tab-classification") { - urlString = tabStateUrls.tagUrl; //'#!/tag'; - } else if (elementName.name == "tab-search") { - urlString = tabStateUrls.searchUrl; // '#!/search'; - } else if (elementName.name == "tab-glossary") { - urlString = tabStateUrls.glossaryUrl; // '#!/glossary'; - } - - Utils.setUrl({ - url: urlString, - mergeBrowserUrl: false, - trigger: true, - updateTabState: true - }); - }; - return events; - }, - initialize: function(options) { - this.options = options; - }, - onRender: function() { - this.renderTagLayoutView(); - this.renderSearchLayoutView(); - this.renderGlossaryLayoutView(); - this.selectTab(); - - }, - renderTagLayoutView: function() { - var that = this; - require(['views/tag/TagLayoutView'], function(TagLayoutView) { - that.RTagLayoutView.show(new TagLayoutView( - _.extend(that.options, { - "collection": that.options.classificationDefCollection - }) - )); - }); - }, - renderSearchLayoutView: function() { - var that = this; - require(['views/search/SearchLayoutView'], function(SearchLayoutView) { - that.RSearchLayoutView.show(new SearchLayoutView(that.options)); - }); - }, - renderGlossaryLayoutView: function() { - var that = this; - require(['views/glossary/GlossaryLayoutView'], function(GlossaryLayoutView) { - that.RGlossaryLayoutView.show(new GlossaryLayoutView(that.options)); - }); - }, - selectTab: function() { - var that = this; - var activeTab = function(options) { - var view = options.view; - that.$('.tabs').find('li a[aria-controls="tab-' + view + '"]').parents('li').addClass('active').siblings().removeClass('active'); - that.$('.tab-content').find('div#tab-' + view).addClass('active').siblings().removeClass('active'); - }; - if (Utils.getUrlState.isSearchTab() || Utils.getUrlState.isInitial() || Utils.getUrlState.isAdministratorTab() || Utils.getUrlState.isDebugMetricsTab()) { - activeTab({ "view": "search" }); - } else if (Utils.getUrlState.isTagTab()) { - activeTab({ "view": "classification" }); - } else if (Utils.getUrlState.isGlossaryTab()) { - activeTab({ "view": "glossary" }); - } else if (Utils.getUrlState.isDetailPage()) { - var queryParams = Utils.getUrlState.getQueryParams(), - view = "search"; - if (queryParams && queryParams.from) { - if (queryParams.from == "classification") { - view = "classification"; - } else if (queryParams.from == "glossary") { - view = "glossary"; - } - } - activeTab({ "view": view }); - } - } - }); - return SideNavLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/site/Statistics.js b/dashboardv2/public/js/views/site/Statistics.js deleted file mode 100644 index 32a66691c71..00000000000 --- a/dashboardv2/public/js/views/site/Statistics.js +++ /dev/null @@ -1,507 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/site/Statistics_tmpl', - 'hbs!tmpl/site/Statistics_Notification_table_tmpl', - 'hbs!tmpl/site/Statistics_Topic_Offset_table_tmpl', - 'hbs!tmpl/site/entity_tmpl', - 'modules/Modal', - 'models/VCommon', - 'utils/UrlLinks', - 'collection/VTagList', - 'utils/CommonViewFunction', - 'utils/Enums', - 'utils/MigrationEnums', - 'moment', - 'utils/Utils', - 'utils/Globals', - 'moment-timezone' -], function(require, Backbone, StatTmpl, StatsNotiTable, TopicOffsetTable, EntityTable, Modal, VCommon, UrlLinks, VTagList, CommonViewFunction, Enums, MigrationEnums, moment, Utils, Globals) { - 'use strict'; - - var StatisticsView = Backbone.Marionette.LayoutView.extend( - /** @lends AboutAtlasView */ - { - template: StatTmpl, - - /** Layout sub regions */ - regions: {}, - /** ui selector cache */ - ui: { - entity: "[data-id='entity']", - classification: "[data-id='classification']", - serverCard: "[data-id='server-card']", - connectionCard: "[data-id='connection-card']", - notificationCard: "[data-id='notification-card']", - statsNotificationTable: "[data-id='stats-notification-table']", - entityCard: "[data-id='entity-card']", - classificationCard: "[data-id='classification-card']", - offsetCard: "[data-id='offset-card']", - osCard: "[data-id='os-card']", - runtimeCard: "[data-id='runtime-card']", - memoryCard: "[data-id='memory-card']", - memoryPoolUsage: "[data-id='memory-pool-usage-card']", - statisticsRefresh: "[data-id='statisticsRefresh']", - notificationDetails: "[data-id='notificationDetails']", - migrationProgressBar: "[data-id='migrationProgressBar']", - migrationProgressBarValue: "[data-id='migrationProgressBarValue']" - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.statisticsRefresh] = function(e) { - this.showLoader(); - this.fetchMetricData(); - this.fetchStatusData(); - }; - return events; - }, - /** - * intialize a new AboutAtlasView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, options); - var that = this; - this.DATA_MAX_LENGTH = 25; - this.loaderCount = 0; - if (this.isMigrationView) { - this.migrationImportStatus = new VTagList(); - this.migrationImportStatus.url = UrlLinks.migrationStatusApiUrl(); - } else { - var modal = new Modal({ - title: 'Statistics', - content: this, - okCloses: true, - okText: "Close", - showFooter: true, - allowCancel: false, - width: "60%", - headerButtons: [{ - title: "Refresh Data", - btnClass: "fa fa-refresh", - onClick: function() { - modal.$el.find('.header-button .fa-refresh').tooltip('hide').prop('disabled', true).addClass('fa-spin'); - that.fetchMetricData({ update: true }); - } - }] - }); - modal.on('closeModal', function() { - modal.trigger('cancel'); - }); - this.modal = modal; - modal.open(); - } - - }, - bindEvents: function() { - var that = this; - if (this.modal) { - this.$el.on('click', '.linkClicked', function() { - that.modal.close(); - }) - } - }, - fetchStatusData: function() { - var that = this; - ++this.loaderCount; - that.migrationImportStatus.fetch({ - success: function(data) { - var data = _.first(data.toJSON()), - migrationStatus = data.MigrationStatus || null, - operationStatus = migrationStatus.operationStatus, - showProgress = true, - totalProgress = 0, - progressMessage = ""; - if (migrationStatus) { - if (MigrationEnums.migrationStatus[operationStatus] === "DONE") { - showProgress = false; - } else if (MigrationEnums.migrationStatus[operationStatus] === "IN_PROGRESS" || MigrationEnums.migrationStatus[operationStatus] === "STARTED") { - var currentIndex = migrationStatus.currentIndex || 0, - totalCount = migrationStatus.totalCount || 0; - totalProgress = Math.ceil((migrationStatus.currentIndex / migrationStatus.totalCount) * 100) - progressMessage = totalProgress + "%"; - that.ui.migrationProgressBar.removeClass("progress-bar-danger"); - that.ui.migrationProgressBar.addClass("progress-bar-success"); - } else if (MigrationEnums.migrationStatus[operationStatus] === "FAIL") { - totalProgress = "100"; - progressMessage = "Failed"; - that.ui.migrationProgressBar.addClass("progress-bar-danger"); - that.ui.migrationProgressBar.removeClass("progress-bar-success"); - } - if (showProgress) { - that.$el.find(".statistics-header>.progress").removeClass("hide"); - that.$el.find(".statistics-header>.successStatus").addClass("hide"); - that.ui.migrationProgressBar.css({ width: totalProgress + '%' }); - that.ui.migrationProgressBarValue.text(progressMessage); - } else { - that.$el.find(".statistics-header>.progress").addClass("hide"); - that.$el.find(".statistics-header>.successStatus").removeClass("hide"); - } - } - - }, - complete: function() { - --that.loaderCount; - that.hideLoader(); - } - }); - }, - fetchMetricData: function(options) { - var that = this; - ++this.loaderCount; - this.metricCollection.fetch({ - success: function(data) { - var data = _.first(data.toJSON()); - that.renderStats({ valueObject: data.general.stats, dataObject: data.general }); - that.renderEntities({ data: data }); - that.renderSystemDeatils({ data: data }); - that.renderClassifications({ data: data }); - if (options && options.update) { - if (that.modal) { - that.modal.$el.find('.header-button .fa-refresh').prop('disabled', false).removeClass('fa-spin'); - } - Utils.notifySuccess({ - content: "Metric data is refreshed" - }) - } - }, - complete: function() { - --that.loaderCount; - that.hideLoader() - } - }); - }, - hideLoader: function() { - if (this.loaderCount === 0) { - var className = ".statsContainer"; - if (this.isMigrationView) { - className += ",.statistics-header"; - } - this.$(className).removeClass('hide'); - this.$('.statsLoader').removeClass('show'); - } - }, - showLoader: function() { - var className = ".statsContainer"; - if (this.isMigrationView) { - className += ",.statistics-header"; - } - this.$(className).addClass('hide'); - this.$('.statsLoader').addClass('show'); - }, - onRender: function() { - this.bindEvents(); - if (this.isMigrationView) { - this.showLoader(); - this.fetchStatusData(); - } - this.fetchMetricData(); - }, - closePanel: function(options) { - var el = options.el; - el.find(">.panel-heading").attr("aria-expanded", "false"); - el.find(">.panel-collapse.collapse").removeClass("in"); - }, - genrateStatusData: function(stateObject) { - var that = this, - stats = {}; - _.each(stateObject, function(val, key) { - var keys = key.split(":"), - key = keys[0], - subKey = keys[1]; - if (stats[key]) { - stats[key][subKey] = val; - } else { - stats[key] = {}; - stats[key][subKey] = val; - } - }); - return stats; - }, - createTable: function(obj) { - var that = this, - tableBody = '', - type = obj.type, - data = obj.data; - _.each(data, function(value, key, list) { - var newValue = that.getValue({ - "value": value - }); - if (type === "classification") { - newValue = '' + newValue + ''; - } - tableBody += '' + key + '' + newValue + ''; - }); - return tableBody; - - }, - renderClassifications: function(options) { - var that = this, - data = options.data, - classificationData = data.tag || {}, - tagEntitiesData = classificationData ? classificationData.tagEntities || {} : {}, - tagsCount = 0, - newTagEntitiesData = {}, - tagEntitiesKeys = _.keys(tagEntitiesData); - _.each(_.sortBy(tagEntitiesKeys, function(o) { - return o.toLocaleLowerCase(); - }), function(key) { - var val = tagEntitiesData[key]; - newTagEntitiesData[key] = val; - tagsCount += val; - }); - tagEntitiesData = newTagEntitiesData; - - if (!_.isEmpty(tagEntitiesData)) { - this.ui.classificationCard.html( - that.createTable({ - "data": tagEntitiesData, - "type": "classification" - }) - ); - this.ui.classification.find(".count").html(" (" + _.numberFormatWithComma(tagsCount) + ")"); - if (tagEntitiesKeys.length > this.DATA_MAX_LENGTH) { - this.closePanel({ - el: this.ui.classification - }) - } - } - }, - renderEntities: function(options) { - var that = this, - data = options.data, - entityData = data.entity, - activeEntities = entityData.entityActive || {}, - deletedEntities = entityData.entityDeleted || {}, - shellEntities = entityData.entityShell || {}, - stats = {}, - activeEntityCount = 0, - deletedEntityCount = 0, - shellEntityCount = 0, - createEntityData = function(opt) { - var entityData = opt.entityData, - type = opt.type; - _.each(entityData, function(val, key) { - var intVal = _.isUndefined(val) ? 0 : val; - if (type == "active") { - activeEntityCount += intVal; - } - if (type == "deleted") { - deletedEntityCount += intVal; - } - if (type == "shell") { - shellEntityCount += intVal - } - intVal = _.numberFormatWithComma(intVal) - if (stats[key]) { - stats[key][type] = intVal; - } else { - stats[key] = {}; - stats[key][type] = intVal; - } - }) - }; - - createEntityData({ - "entityData": activeEntities, - "type": "active" - }) - createEntityData({ - "entityData": deletedEntities, - "type": "deleted" - }); - createEntityData({ - "entityData": shellEntities, - "type": "shell" - }); - if (!_.isEmpty(stats)) { - var statsKeys = _.keys(stats); - this.ui.entityCard.html( - EntityTable({ - "data": _.pick(stats, _.sortBy(statsKeys, function(o) { - return o.toLocaleLowerCase(); - })), - }) - ); - this.$('[data-id="activeEntity"]').html(" (" + _.numberFormatWithComma(activeEntityCount) + ")"); - this.$('[data-id="deletedEntity"]').html(" (" + _.numberFormatWithComma(deletedEntityCount) + ")"); - this.$('[data-id="shellEntity"]').html(" (" + _.numberFormatWithComma(shellEntityCount) + ")"); - this.ui.entity.find(".count").html(" (" + _.numberFormatWithComma(data.general.entityCount) + ")"); - if (statsKeys.length > this.DATA_MAX_LENGTH) { - this.closePanel({ - el: this.ui.entity - }) - } - } - }, - renderStats: function(options) { - var that = this, - data = this.genrateStatusData(options.valueObject), - generalData = options.dataObject, - createTable = function(obj) { - var tableBody = '', - enums = obj.enums, - data = obj.data; - _.each(data, function(value, key, list) { - tableBody += '' + key + '' + that.getValue({ - "value": value, - "type": enums[key] - }) + ''; - }); - return tableBody; - }; - if (!that.isMigrationView && data.Notification) { - var tableCol = [{ - label: "Total
        (from " + (that.getValue({ - "value": data.Server["startTimeStamp"], - "type": Enums.stats.Server["startTimeStamp"], - })) + ")", - key: "total" - }, - { - label: "Current Hour
        (from " + (that.getValue({ - "value": data.Notification["currentHourStartTime"], - "type": Enums.stats.Notification["currentHourStartTime"], - })) + ")", - key: "currentHour" - }, - { label: "Previous Hour", key: "previousHour" }, - { - label: "Current Day
        (from " + (that.getValue({ - "value": data.Notification["currentDayStartTime"], - "type": Enums.stats.Notification["currentDayStartTime"], - })) + ")", - key: "currentDay" - }, - { label: "Previous Day", key: "previousDay" } - ], - tableHeader = ["count", "AvgTime", "EntityCreates", "EntityUpdates", "EntityDeletes", "Failed"]; - that.ui.notificationCard.html( - StatsNotiTable({ - "enums": Enums.stats.Notification, - "data": data.Notification, - "tableHeader": tableHeader, - "tableCol": tableCol, - "getTmplValue": function(argument, args) { - var pickValueFrom = argument.key.concat(args); - if (argument.key == "total" && args == "EntityCreates") { - pickValueFrom = "totalCreates"; - } else if (argument.key == "total" && args == "EntityUpdates") { - pickValueFrom = "totalUpdates"; - } else if (argument.key == "total" && args == "EntityDeletes") { - pickValueFrom = "totalDeletes"; - } else if (args == "count") { - pickValueFrom = argument.key; - } - var returnVal = data.Notification[pickValueFrom]; - return returnVal ? _.numberFormatWithComma(returnVal) : 0; - } - }) - ); - - var offsetTableColumn = function(obj) { - var returnObj = [] - _.each(obj, function(value, key) { - returnObj.push({ "label": key, "dataValue": value }); - }); - return returnObj - } - - that.ui.offsetCard.html( - TopicOffsetTable({ - data: data.Notification.topicDetails, - tableHeader: ["offsetStart", "offsetCurrent", "processedMessageCount", "failedMessageCount", "lastMessageProcessedTime"], - tableCol: offsetTableColumn(data.Notification.topicDetails), - getTmplValue: function(argument, args) { - var returnVal = data.Notification.topicDetails[argument.label][args]; - return returnVal ? that.getValue({ value: returnVal, type: Enums.stats.Notification[args] }) : 0; - } - }) - ) - that.ui.notificationDetails.removeClass('hide'); - } - - if (data.Server) { - that.ui.serverCard.html( - createTable({ - "enums": _.extend(Enums.stats.Server, Enums.stats.ConnectionStatus, Enums.stats.generalData), - "data": _.extend( - _.pick(data.Server, 'startTimeStamp', 'activeTimeStamp', 'upTime', 'statusBackendStore', 'statusIndexStore'), - _.pick(generalData, 'collectionTime')) - }) - ); - } - }, - renderSystemDeatils: function(options) { - var that = this, - data = options.data, - systemData = data.system, - systemOS = systemData.os || {}, - systemRuntimeData = systemData.runtime || {}, - systemMemoryData = systemData.memory || {}; - if (!_.isEmpty(systemOS)) { - that.ui.osCard.html( - that.createTable({ - "data": systemOS - }) - ); - } - if (!_.isEmpty(systemRuntimeData)) { - _.each(systemRuntimeData, function(val, key) { - var space - }) - that.ui.runtimeCard.html( - that.createTable({ - "data": systemRuntimeData - }) - ); - } - if (!_.isEmpty(systemMemoryData)) { - var memoryTable = CommonViewFunction.propertyTable({ - scope: this, - formatStringVal: true, - valueObject: systemMemoryData, - numberFormat: _.numberFormatWithBytes - }); - that.ui.memoryCard.html( - memoryTable); - } - }, - getValue: function(options) { - var value = options.value, - type = options.type; - if (type == 'time') { - return Utils.millisecondsToTime(value); - } else if (type == 'day') { - return Utils.formatDate({ date: value }) - } else if (type == 'number') { - return _.numberFormatWithComma(value); - } else if (type == 'millisecond') { - return _.numberFormatWithComma(value) + " millisecond/s"; - } else if (type == "status-html") { - return ''; - } else { - return value; - } - } - }); - return StatisticsView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/tag/AddTagAttributeView.js b/dashboardv2/public/js/views/tag/AddTagAttributeView.js deleted file mode 100644 index f59476e933d..00000000000 --- a/dashboardv2/public/js/views/tag/AddTagAttributeView.js +++ /dev/null @@ -1,100 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/tag/AddTagAttributeView_tmpl', - 'views/tag/TagAttributeItemView', - 'utils/UrlLinks', - 'collection/VTagList' - -], function(require, Backbone, AddTagAttributeView_tmpl, TagAttributeItemView, UrlLinks, VTagList) { - 'use strict'; - - return Backbone.Marionette.CompositeView.extend( - /** @lends GlobalExclusionListView */ - { - - template: AddTagAttributeView_tmpl, - templateHelpers: function() { - return { - create: this.create, - description: this.description - }; - }, - - childView: TagAttributeItemView, - - childViewContainer: "[data-id='addAttributeDiv']", - - childViewOptions: function() { - return { - // saveButton: this.ui.saveButton, - parentView: this - }; - }, - /** ui selector cache */ - ui: { - close: "[data-id='close']", - attributeId: "[data-id='attributeId']", - attributeData: "[data-id='attributeData']", - addAttributeDiv: "[data-id='addAttributeDiv']" - }, - events: function() { - var events = {}; - events["click " + this.ui.attributeData] = "onClickAddAttriBtn"; - return events; - }, - initialize: function(options) { - _.extend(this, _.pick(options, 'enumDefCollection')); - this.collection = new Backbone.Collection(); - this.collectionAttribute(); - }, - onRender: function() { - var that = this; - this.ui.addAttributeDiv.find('.closeInput').hide(); - if (!('placeholder' in HTMLInputElement.prototype)) { - this.ui.addAttributeDiv.find('input,textarea').placeholder(); - } - that.$('.hide').removeClass('hide'); - }, - bindEvents: function() {}, - collectionAttribute: function() { - this.collection.add(new Backbone.Model({ - "name": "", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": true - })); - - }, - onClickAddAttriBtn: function() { - if (this.ui.addAttributeDiv.find("input").length > 0) { - this.ui.addAttributeDiv.find('.closeInput').show(); - }; - this.collectionAttribute(); - if (!('placeholder' in HTMLInputElement.prototype)) { - this.ui.addAttributeDiv.find('input,textarea').placeholder(); - } - } - }); -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/tag/AddTagModalView.js b/dashboardv2/public/js/views/tag/AddTagModalView.js deleted file mode 100644 index da70dc47d16..00000000000 --- a/dashboardv2/public/js/views/tag/AddTagModalView.js +++ /dev/null @@ -1,512 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'hbs!tmpl/tag/AddTagModalView_tmpl', - 'views/tag/AddTimezoneItemView', - 'collection/VTagList', - 'collection/VCommonList', - 'modules/Modal', - 'models/VEntity', - 'utils/Utils', - 'utils/UrlLinks', - 'utils/Enums', - 'utils/Messages', - 'moment', - 'utils/Globals', - 'moment-timezone', - 'daterangepicker' -], function(require, AddTagModalViewTmpl, AddTimezoneItemView, VTagList, VCommonList, Modal, VEntity, Utils, UrlLinks, Enums, Messages, moment, Globals) { - 'use strict'; - - var AddTagModel = Backbone.Marionette.CompositeView.extend({ - template: AddTagModalViewTmpl, - templateHelpers: function() { - return { - tagModel: this.tagModel - }; - }, - childView: AddTimezoneItemView, - childViewOptions: function() { - return { - // saveButton: this.ui.saveButton, - parentView: this, - tagModel: this.tagModel - }; - }, - childViewContainer: "[data-id='addTimezoneDiv']", - regions: {}, - ui: { - addTagOptions: "[data-id='addTagOptions']", - tagAttribute: "[data-id='tagAttribute']", - checkTimeZone: "[data-id='checkTimezoneProperty']", - timeZoneDiv: "[data-id='timeZoneDiv']", - checkTagModalPropagate: "[data-id='checkModalTagProperty']", - addTimezoneParms: "[data-id='addTimezoneParms']", - validityPeriodBody: "[data-id='validityPeriodBody']", - removePropagationOnEntityDelete: "[data-id='removePropagationOnEntityDelete']", - removePropagationOnEntityDeleteBox: "[data-id='removePropagationOnEntityDeleteBox']" - }, - events: function() { - var events = {}, - that = this; - events["change " + this.ui.addTagOptions] = 'onChangeTagDefination'; - events["change " + this.ui.checkTagModalPropagate] = function(e) { - if (e.target.checked) { - that.ui.removePropagationOnEntityDeleteBox.show(); - that.$('.addtag-propagte-box').removeClass('no-border'); - } else { - that.$('.addtag-propagte-box').addClass('no-border'); - that.ui.removePropagationOnEntityDeleteBox.hide(); - } - if (that.tagModel) { - that.buttonActive({ isButtonActive: true }); - } - }; - events["change " + this.ui.removePropagationOnEntityDelete] = function() { - if (that.tagModel) { - that.buttonActive({ isButtonActive: true }); - } - }; - events["change " + this.ui.checkTimeZone] = function(e) { - if (this.tagModel) { - this.buttonActive({ isButtonActive: true }); - } - if (e.target.checked) { - this.ui.timeZoneDiv.show(); - this.ui.validityPeriodBody.show(); - if (_.isEmpty(this.collection.models)) { - this.collection.add(new Backbone.Model({ - "startTime": "", - "endTime": "", - "timeZone": "" - })); - } - } else { - this.ui.timeZoneDiv.hide(); - this.ui.validityPeriodBody.hide(); - } - }; - events["click " + this.ui.addTimezoneParms] = 'addTimezoneBtn' - return events; - }, - /** - * intialize a new AddTagModel Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'modalCollection', 'guid', 'callback', 'multiple', 'entityCount', 'showLoader', 'hideLoader', 'tagList', 'tagModel', 'enumDefCollection')); - this.commonCollection = new VTagList(); - if (this.tagModel) { - this.collection = new Backbone.Collection(this.tagModel.validityPeriods); - } else { - this.collection = new Backbone.Collection(); - } - this.tagCollection = options.collection; - var that = this, - modalObj = { - title: 'Add Classification', - content: this, - okText: 'Add', - cancelText: "Cancel", - mainClass: 'modal-lg', - allowCancel: true, - okCloses: false - }; - if (this.tagModel) { - modalObj.title = 'Edit Classification'; - modalObj.okText = 'Update'; - } - this.modal = new Modal(modalObj) - this.modal.open(); - this.modal.$el.find('button.ok').attr("disabled", true); - this.on('ok', function() { - if (this.ui.checkTimeZone.is(':checked')) { - if (this.validateValues()) { - if (this.hideLoader) { - this.hideLoader(); - }; - return; - }; - } - that.modal.$el.find('button.ok').showButtonLoader(); - var tagName = this.tagModel ? this.tagModel.typeName : this.ui.addTagOptions.val(), - tagAttributes = {}, - tagAttributeNames = this.$(".attrName"), - obj = { - tagName: tagName, - tagAttributes: tagAttributes, - guid: [], - skipEntity: [], - deletedEntity: [] - }; - tagAttributeNames.each(function(i, item) { - var selection = $(item).data("key"); - var datatypeSelection = $(item).data("type"); - if (datatypeSelection === "date") { - tagAttributes[selection] = Date.parse($(item).val()) || null; - } else { - tagAttributes[selection] = $(item).val() || null; - } - }); - - if (that.multiple) { - _.each(that.multiple, function(entity, i) { - var name = Utils.getName(entity.model); - if (Enums.entityStateReadOnly[entity.model.status]) { - obj.deletedEntity.push(name); - } else { - if (_.indexOf((entity.model.classificationNames || _.pluck(entity.model.classifications, 'typeName')), tagName) === -1) { - obj.guid.push(entity.model.guid) - } else { - obj.skipEntity.push(name); - } - } - }); - if (obj.deletedEntity.length) { - Utils.notifyError({ - html: true, - content: "" + obj.deletedEntity.join(', ') + - " " + (obj.deletedEntity.length === 1 ? "entity " : "entities ") + - Messages.assignDeletedEntity - }); - that.modal.close(); - } - if (obj.skipEntity.length) { - var text = "" + obj.skipEntity.length + " of " + that.multiple.length + - " entities selected have already been associated with " + tagName + - " tag, Do you want to associate the tag with other entities ?", - removeCancelButton = false; - if ((obj.skipEntity.length + obj.deletedEntity.length) === that.multiple.length) { - text = (obj.skipEntity.length > 1 ? "All selected" : "Selected") + " entities have already been associated with " + tagName + " tag"; - removeCancelButton = true; - } - var notifyObj = { - text: text, - modal: true, - ok: function(argument) { - if (obj.guid.length) { - that.saveTagData(obj); - } else { - that.hideLoader(); - } - }, - cancel: function(argument) { - that.hideLoader(); - obj = { - tagName: tagName, - tagAttributes: tagAttributes, - guid: [], - skipEntity: [], - deletedEntity: [] - } - } - } - if (removeCancelButton) { - notifyObj['confirm'] = { - confirm: true, - buttons: [{ - text: 'Ok', - addClass: 'btn-atlas btn-md', - click: function(notice) { - notice.remove(); - obj = { - tagName: tagName, - tagAttributes: tagAttributes, - guid: [], - skipEntity: [], - deletedEntity: [] - } - } - }, - null - ] - } - } - Utils.notifyConfirm(notifyObj) - } else { - if (obj.guid.length) { - that.saveTagData(obj); - } else { - that.hideLoader(); - } - } - } else { - obj.guid.push(that.guid); - that.saveTagData(obj); - } - }); - this.on('closeModal', function() { - this.modal.trigger('cancel'); - }); - this.bindEvents(); - }, - validateValues: function(attributeDefs) { - var isValidate = true, - applyErrorClass = function(scope) { - if (this.value == '' || this.value == null || this.value.indexOf('Select Timezone') > -1) { - $(this).addClass('errorValidate'); - if (isValidate) { isValidate = false; } - } else { - $(this).removeClass('errorValidate'); - } - }; - - this.$el.find('.start-time').each(function(element) { - applyErrorClass.call(this); - }); - this.$el.find('.end-time').each(function(element) { - applyErrorClass.call(this); - }); - this.$el.find('.time-zone').each(function(element) { - applyErrorClass.call(this); - }); - if (!isValidate) { - Utils.notifyInfo({ - content: "Please fill the details" - }); - return true; - } - }, - - onRender: function() { - var that = this; - this.propagate, - this.hideAttributeBox(); - this.tagsCollection(); - if (this.tagModel) { - this.fetchTagSubData(that.tagModel.typeName); - // Added === true because if value is null then use false. - that.ui.checkTagModalPropagate.prop('checked', this.tagModel.propagate === true ? true : false).trigger('change'); - that.ui.checkTimeZone.prop('checked', _.isEmpty(this.tagModel.validityPeriods) ? false : true); - that.ui.removePropagationOnEntityDelete.prop('checked', this.tagModel.removePropagationsOnEntityDelete == true ? true : false); - if (_.isEmpty(this.tagModel.validityPeriods)) { - that.ui.timeZoneDiv.hide() - } else { - that.ui.timeZoneDiv.show(); - } - that.checkTimezoneProperty(that.ui.checkTimeZone[0]); - } - that.showAttributeBox(); - }, - addTimezoneBtn: function() { - this.ui.validityPeriodBody.show(); - this.collection.add(new Backbone.Model({ - "startTime": "", - "endTime": "", - "timeZone": "" - })); - }, - bindEvents: function() { - var that = this; - this.enumArr = []; - this.listenTo(this.tagCollection, 'reset', function() { - this.tagsCollection(); - }, this); - this.listenTo(this.commonCollection, 'reset', function() { - this.subAttributeData(); - }, this); - }, - tagsCollection: function() { - var that = this, - str = ''; - this.tagCollection.fullCollection.each(function(obj, key) { - var name = Utils.getName(obj.toJSON(), 'name'); - // using obj.get('name') insted of name variable because if html is presen in name then escaped name will not found in tagList. - if (_.indexOf(that.tagList, obj.get('name')) === -1) { - str += ''; - } - }); - this.ui.addTagOptions.html(str); - this.ui.addTagOptions.select2({ - placeholder: "Select Tag", - allowClear: false - }); - }, - onChangeTagDefination: function() { - this.ui.addTagOptions.select2("open").select2("close"); - this.ui.tagAttribute.empty(); - var saveBtn = this.modal.$el.find('button.ok'); - saveBtn.prop("disabled", false); - var tagname = this.ui.addTagOptions.val(); - this.hideAttributeBox(); - this.fetchTagSubData(tagname); - }, - fetchTagSubData: function(tagname) { - var attributeDefs = Utils.getNestedSuperTypeObj({ - data: this.tagCollection.fullCollection.find({ name: tagname }).toJSON(), - collection: this.tagCollection, - attrMerge: true - }); - this.subAttributeData(attributeDefs); - }, - showAttributeBox: function() { - var that = this, - isButtonactive; - this.$('.attrLoader').hide(); - this.$('.form-group.hide').removeClass('hide'); - if (this.ui.tagAttribute.children().length !== 0) { - this.ui.tagAttribute.parent().show(); - } - this.ui.tagAttribute.find('input,select').on("keyup change", function(e) { - if (e.keyCode != 32) { - that.buttonActive({ isButtonActive: true }); - } - }); - }, - buttonActive: function(option) { - if (option) { - var isButton = option.isButtonActive; - this.modal.$el.find('button.ok').attr("disabled", isButton === true ? false : true); - } - }, - hideAttributeBox: function() { - this.ui.tagAttribute.children().empty(); - this.ui.tagAttribute.parent().hide(); - this.$('.attrLoader').show(); - }, - subAttributeData: function(attributeDefs) { - var that = this; - if (attributeDefs) { - _.each(attributeDefs, function(obj) { - var name = Utils.getName(obj, 'name'); - var typeName = Utils.getName(obj, 'typeName'); - var typeNameValue = that.enumDefCollection.fullCollection.findWhere({ 'name': typeName }); - if (typeNameValue) { - var str = '"; - var enumValue = typeNameValue.get('elementDefs'); - _.each(enumValue, function(key, value) { - str += ''; - }) - that.ui.tagAttribute.append('
        ' + ' (' + typeName + ')' + - '
        '); - } else { - var textElement = that.getElement(name, typeName); - if (_.isTypePrimitive(typeName)) { - that.ui.tagAttribute.append('
        ' + ' (' + typeName + ')' + textElement + '
        '); - } - } - }); - that.$('input[data-type="date"]').each(function() { - if (!$(this).data('daterangepicker')) { - var dateObj = { - "singleDatePicker": true, - "showDropdowns": true, - "timePicker": true, - startDate: new Date(), - locale: { - format: Globals.dateTimeFormat - } - }; - if (that.tagModel) { - if (this.value.length) { - var formatDate = Number(this.value); - dateObj["startDate"] = new Date(formatDate); - } - } - $(this).daterangepicker(dateObj); - } - }); - that.$('select[data-type="boolean"]').each(function() { - var labelName = $(this).data('key'); - if (that.tagModel) { - this.value = that.tagModel.attributes[labelName]; - } - }); - this.showAttributeBox(); - } - }, - getElement: function(labelName, typeName) { - var value = this.tagModel && this.tagModel.attributes ? (this.tagModel.attributes[_.unescape(labelName)] || "") : "", - isTypeNumber = typeName === "int" || typeName === "byte" || typeName === "short" || typeName === "double" || typeName === "float", - inputClassName = "form-control attributeInputVal attrName"; - if (isTypeNumber) { - inputClassName += ((typeName === "int" || typeName === "byte" || typeName === "short") ? " number-input-negative" : " number-input-exponential"); - } - if (typeName === "boolean") { - return ''; - } else { - return ''; - } - - }, - checkTimezoneProperty: function(e) { - if (e.checked) { - this.ui.timeZoneDiv.show(); - this.ui.validityPeriodBody.show(); - } else { - this.ui.timeZoneDiv.hide(); - this.ui.validityPeriodBody.hide(); - } - }, - saveTagData: function(options) { - var that = this; - this.entityModel = new VEntity(); - var tagName = options.tagName, - tagAttributes = options.tagAttributes, - validityPeriodVal = that.ui.checkTimeZone.is(':checked') ? that.collection.toJSON() : [], - classificationData = { - "typeName": tagName, - "attributes": tagAttributes, - "propagate": that.ui.checkTagModalPropagate.is(":checked") === true ? true : false, - "removePropagationsOnEntityDelete": that.ui.removePropagationOnEntityDelete.is(":checked") === true ? true : false, - "validityPeriods": validityPeriodVal - }, - json = { - "classification": classificationData, - "entityGuids": options.guid - }; - if (this.tagModel) { - json = [classificationData] - } - if (this.showLoader) { - this.showLoader(); - } - this.entityModel.saveTraitsEntity(this.tagModel ? options.guid : null, { - data: JSON.stringify(json), - type: this.tagModel ? 'PUT' : 'POST', - defaultErrorMessage: "Tag " + tagName + " could not be added", - success: function(data) { - var addupdatetext = that.tagModel ? 'updated successfully to ' : 'added to '; - Utils.notifySuccess({ - content: "Classification " + tagName + " has been " + addupdatetext + (that.entityCount > 1 ? "entities" : "entity") - }); - if (options.modalCollection) { - options.modalCollection.fetch({ reset: true }); - } - if (that.callback) { - that.callback(); - } - }, - cust_error: function(model, response) { - that.modal.$el.find('button.ok').hideButtonLoader(); - if (that.hideLoader) { - that.hideLoader(); - } - }, - complete: function() { - that.modal.close(); - } - }); - }, - }); - return AddTagModel; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/tag/AddTimezoneItemView.js b/dashboardv2/public/js/views/tag/AddTimezoneItemView.js deleted file mode 100644 index c07eecfe6a1..00000000000 --- a/dashboardv2/public/js/views/tag/AddTimezoneItemView.js +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -define(['require', - 'backbone', - 'hbs!tmpl/tag/AddTimezoneView_tmpl', - 'moment', - 'utils/Utils', - 'utils/Globals', - 'moment-timezone', - 'daterangepicker' -], function(require, Backbone, AddTimezoneViewTmpl, moment, Utils, Globals) { - 'use strict'; - - return Backbone.Marionette.ItemView.extend( - /** @lends GlobalExclusionListView */ - { - - template: AddTimezoneViewTmpl, - - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - close: "[data-id='close']", - startTime: '[data-id="startTime"]', - endTime: '[data-id="endTime"]', - timeZone: '[data-id="timeZone"]' - }, - /** ui events hash */ - events: function() { - var events = {}, - that = this; - events["change " + this.ui.startTime] = function(e) { - this.model.set({ "startTime": that.getDateFormat(this.ui.startTime.val()) }); - this.buttonActive({ isButtonActive: true }); - }; - events["change " + this.ui.endTime] = function(e) { - this.model.set({ "endTime": that.getDateFormat(this.ui.endTime.val()) }); - this.buttonActive({ isButtonActive: true }); - }; - events["change " + this.ui.timeZone] = function(e) { - this.model.set({ "timeZone": this.ui.timeZone.val() }); - this.buttonActive({ isButtonActive: true }); - }; - events["click " + this.ui.close] = 'onCloseButton'; - return events; - }, - - /** - * intialize a new GlobalExclusionComponentView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'parentView', 'model', 'tagModel')); - }, - onRender: function() { - var that = this, - tzstr = '', - dateConfig = { - "singleDatePicker": true, - "showDropdowns": true, - "timePicker": true, - "timePicker24Hour": Globals.dateTimeFormat.indexOf("hh") > -1 ? false : true, - "timePickerSeconds": true, - "startDate": new Date(), - "autoApply": true, - "autoUpdateInput": false, - "locale": { - format: Globals.dateTimeFormat, - cancelLabel: 'Clear' - }, - }, - startDateObj = _.extend({}, dateConfig), - endDateObj = _.extend({}, dateConfig); - - this.ui.timeZone.html(tzstr); - this.ui.timeZone.select2({ - data: Globals.userLogedIn.response.timezones - }); - - if (!_.isEmpty(this.model.get('startTime')) || !_.isEmpty(this.model.get('endTime')) || !_.isEmpty(this.model.get('timeZone'))) { - if (_.isEmpty(this.model.get('startTime'))) { - startDateObj["autoUpdateInput"] = false; - } else { - startDateObj["autoUpdateInput"] = true; - startDateObj["startDate"] = Utils.formatDate({ date: Date.parse(this.model.get('startTime')), zone: false }); - } - if (_.isEmpty(this.model.get('endTime'))) { - endDateObj["autoUpdateInput"] = false; - endDateObj["minDate"] = Utils.formatDate({ date: Date.parse(this.model.get('startTime')), zone: false }); - } else { - endDateObj["autoUpdateInput"] = true; - endDateObj["minDate"] = Utils.formatDate({ date: Date.parse(this.model.get('startTime')), zone: false }); - endDateObj["startDate"] = Utils.formatDate({ date: Date.parse(this.model.get('endTime')), zone: false }); - } - if (!_.isEmpty(this.model.get('timeZone'))) { - this.ui.timeZone.val(this.model.get('timeZone')).trigger("change", { 'manual': true }); - } - } else { - this.model.set('startTime', that.getDateFormat(that.ui.startTime.val())); - this.model.set('endTime', that.getDateFormat(that.ui.endTime.val())); - } - this.ui.startTime.daterangepicker(startDateObj).on('apply.daterangepicker', function(ev, picker) { - that.ui.startTime.val(Utils.formatDate({ date: picker.startDate, zone: false })); - _.extend(endDateObj, { "minDate": that.ui.startTime.val() }) - that.endDateInitialize(endDateObj); - that.model.set('startTime', that.getDateFormat(that.ui.startTime.val())); - that.buttonActive({ isButtonActive: true }); - }).on('cancel.daterangepicker', function(ev, picker) { - that.ui.startTime.val(''); - delete endDateObj.minDate; - that.endDateInitialize(endDateObj); - that.model.set('startTime', that.getDateFormat(that.ui.startTime.val())); - }); - this.endDateInitialize(endDateObj); - this.buttonActive({ isButtonActive: true }); - }, - getDateFormat: function(option) { - if (option && option.length) { - if (Globals.dateTimeFormat.indexOf("HH") > -1) { - option = option.slice(0, -3); // remove AM/PM from 24hr format - } - return moment(Date.parse(option)).format('YYYY/MM/DD HH:mm:ss'); - } - return ""; - }, - buttonActive: function(option) { - var that = this; - if (option && option.isButtonActive && that.tagModel) { - var isButton = option.isButtonActive; - this.parentView.modal.$el.find('button.ok').attr("disabled", isButton === true ? false : true); - } - }, - onCloseButton: function() { - if (this.tagModel) { - this.buttonActive({ isButtonActive: true }); - } - if (this.parentView.collection.models.length > 0) { - this.model.destroy(); - } - if (this.parentView.collection.models.length <= 0) { - this.parentView.ui.timeZoneDiv.hide(); - this.parentView.ui.checkTimeZone.prop('checked', false); - } - }, - endDateInitialize: function(option) { - var that = this; - this.ui.endTime.daterangepicker(option).on('apply.daterangepicker', function(ev, picker) { - that.ui.endTime.val(Utils.formatDate({ date: picker.startDate, zone: false })); - that.model.set('endTime', that.getDateFormat(that.ui.endTime.val())); - that.buttonActive({ isButtonActive: true }); - }).on('cancel.daterangepicker', function(ev, picker) { - that.ui.endTime.val(''); - that.model.set('endTime', that.getDateFormat(that.ui.endTime.val())); - }); - } - }); -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/tag/CreateTagLayoutView.js b/dashboardv2/public/js/views/tag/CreateTagLayoutView.js deleted file mode 100644 index 476007a2c7f..00000000000 --- a/dashboardv2/public/js/views/tag/CreateTagLayoutView.js +++ /dev/null @@ -1,142 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/tag/CreateTagLayoutView_tmpl', - 'utils/Utils', - 'views/tag/TagAttributeItemView', - 'collection/VTagList', - 'utils/UrlLinks', - 'platform' -], function(require, Backbone, CreateTagLayoutViewTmpl, Utils, TagAttributeItemView, VTagList, UrlLinks, platform) { - - var CreateTagLayoutView = Backbone.Marionette.CompositeView.extend( - /** @lends CreateTagLayoutView */ - { - _viewName: 'CreateTagLayoutView', - - template: CreateTagLayoutViewTmpl, - - templateHelpers: function() { - return { - create: this.create, - description: this.description - }; - }, - - /** Layout sub regions */ - regions: {}, - - childView: TagAttributeItemView, - - childViewContainer: "[data-id='addAttributeDiv']", - - childViewOptions: function() { - return { - // saveButton: this.ui.saveButton, - parentView: this - }; - }, - /** ui selector cache */ - ui: { - tagName: "[data-id='tagName']", - parentTag: "[data-id='parentTagList']", - description: "[data-id='description']", - title: "[data-id='title']", - attributeData: "[data-id='attributeData']", - addAttributeDiv: "[data-id='addAttributeDiv']", - createTagForm: '[data-id="createTagForm"]' - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.attributeData] = "onClickAddAttriBtn"; - return events; - }, - /** - * intialize a new CreateTagLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'tagCollection', 'enumDefCollection', 'model', 'tag', 'descriptionData', 'selectedTag')); - if (this.model) { - this.description = this.model.get('description'); - } else { - this.create = true; - } - this.collection = new Backbone.Collection(); - }, - bindEvents: function() {}, - onRender: function() { - var that = this; - this.$('.fontLoader').show(); - if (this.create) { - this.tagCollectionList(); - } else { - this.ui.title.html('' + _.escape(this.tag) + ''); - } - if (!('placeholder' in HTMLInputElement.prototype)) { - this.ui.createTagForm.find('input,textarea').placeholder(); - } - that.hideLoader(); - }, - tagCollectionList: function() { - var that = this, - str = ''; - this.ui.parentTag.empty(); - this.tagCollection.fullCollection.each(function(val) { - var name = Utils.getName(val.toJSON()); - str += ''; - }); - that.ui.parentTag.html(str); - // IE9 support - if (platform.name === "IE") { - that.ui.parentTag.select2({ - multiple: true, - placeholder: "Search Classification", - allowClear: true - }); - } - }, - hideLoader: function() { - this.$('.fontLoader').hide(); - this.$('.hide').removeClass('hide'); - }, - collectionAttribute: function() { - this.collection.add(new Backbone.Model({ - "name": "", - "typeName": "string", - "isOptional": true, - "cardinality": "SINGLE", - "valuesMinCount": 0, - "valuesMaxCount": 1, - "isUnique": false, - "isIndexable": true - })); - }, - onClickAddAttriBtn: function() { - this.collectionAttribute(); - if (!('placeholder' in HTMLInputElement.prototype)) { - this.ui.addAttributeDiv.find('input,textarea').placeholder(); - } - - } - }); - return CreateTagLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/tag/TagAttributeDetailLayoutView.js b/dashboardv2/public/js/views/tag/TagAttributeDetailLayoutView.js deleted file mode 100644 index be33e7c3257..00000000000 --- a/dashboardv2/public/js/views/tag/TagAttributeDetailLayoutView.js +++ /dev/null @@ -1,321 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/tag/TagAttributeDetailLayoutView_tmpl', - 'utils/Utils', - 'views/tag/AddTagAttributeView', - 'collection/VTagList', - 'models/VTag', - 'utils/Messages', - 'utils/UrlLinks', - 'utils/Globals' -], function(require, Backbone, TagAttributeDetailLayoutViewTmpl, Utils, AddTagAttributeView, VTagList, VTag, Messages, UrlLinks, Globals) { - 'use strict'; - - var TagAttributeDetailLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends TagAttributeDetailLayoutView */ - { - template: TagAttributeDetailLayoutViewTmpl, - /** Layout sub regions */ - regions: {}, - /** ui selector cache */ - ui: { - title: '[data-id="title"]', - editButton: '[data-id="editButton"]', - editBox: '[data-id="editBox"]', - saveButton: "[data-id='saveButton']", - showAttribute: "[data-id='showAttribute']", - addAttribute: '[data-id="addAttribute"]', - description: '[data-id="description"]', - publishButton: '[data-id="publishButton"]', - superType: "[data-id='superType']", - subType: "[data-id='subType']", - entityType: "[data-id='entityType']" - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.addAttribute] = 'onClickAddTagAttributeBtn'; - events["click " + this.ui.editButton] = 'onEditButton'; - return events; - }, - /** - * intialize a new TagAttributeDetailLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'tag', 'collection', 'enumDefCollection')); - }, - bindEvents: function() { - this.listenTo(this.collection, 'reset', function() { - if (!this.model) { - this.model = this.collection.fullCollection.findWhere({ name: this.tag }); - if (this.model) { - this.renderTagDetail(); - } else { - this.$('.fontLoader').hide(); - Utils.notifyError({ - content: 'Tag Not Found' - }); - } - } - }, this); - this.listenTo(this.tagCollection, 'error', function(error, response) { - if (response.responseJSON && response.responseJSON.error) { - Utils.notifyError({ - content: response.responseJSON.error - }); - } else { - Utils.notifyError({ - content: 'Something went wrong' - }); - } - this.$('.fontLoader').hide(); - }, this); - }, - onRender: function() { - Utils.showTitleLoader(this.$('.page-title .fontLoader'), this.$('.tagDetail')); - if (this.collection.models.length && !this.model) { - if (Globals[this.tag]) { - this.collection.fullCollection.push(Globals[this.tag]); - } - this.model = this.collection.fullCollection.findWhere({ name: this.tag }); - this.renderTagDetail(); - } - this.bindEvents(); - this.ui.saveButton.attr("disabled", "true"); - this.ui.publishButton.prop('disabled', true); - }, - renderTagDetail: function() { - var that = this, - attributeData = "", - attributeDefs = this.model.get("attributeDefs"), - genrateType = function(options) { - var data = options.data; - _.each(data, function(value, key) { - var str = "", - el = that.ui[key]; - _.each(value, function(name) { - el.parents("." + key).show(); - str += '
        ' + name + ''; - }); - el.html(str); - }); - } - this.ui.title.html('' + (Utils.getName(this.model.toJSON())) + ''); - if (this.model.get("description")) { - this.ui.description.text(this.model.get("description")); - } - if (attributeDefs) { - if (!_.isArray(attributeDefs)) { - attributeDefs = [attributeDefs]; - } - _.each(attributeDefs, function(value, key) { - attributeData += ''; - }); - this.ui.showAttribute.html(attributeData); - } - - genrateType({ - data: { - superType: this.model.get('superTypes'), - subType: this.model.get('subTypes'), - entityType: this.model.get('entityTypes'), - } - }); - Utils.hideTitleLoader(this.$('.fontLoader'), this.$('.tagDetail')); - }, - onSaveButton: function(saveObject, message) { - var that = this; - var validate = true; - - this.modal.$el.find(".attributeInput").each(function() { - if ($(this).val().trim() === "") { - $(this).css('borderColor', "red") - validate = false; - } - }); - - this.modal.$el.find(".attributeInput").keyup(function() { - $(this).css('borderColor', "#e8e9ee"); - }); - if (!validate) { - Utils.notifyInfo({ - content: "Please fill the attributes or delete the input box" - }); - return; - } - Utils.showTitleLoader(this.$('.page-title .fontLoader'), this.$('.tagDetail')); - this.model.saveTagAttribute({ - data: JSON.stringify({ - classificationDefs: [saveObject], - entityDefs: [], - enumDefs: [], - structDefs: [] - - }), - success: function(model, response) { - if (model.classificationDefs) { - that.model.set(model.classificationDefs[0]); - } - that.renderTagDetail(); - Utils.notifySuccess({ - content: message - }); - }, - cust_error: function() { - Utils.hideTitleLoader(that.$('.fontLoader'), that.$('.tagDetail')); - } - }); - that.modal.close(); - }, - onClickAddTagAttributeBtn: function(e) { - var that = this; - require(['views/tag/AddTagAttributeView', - 'modules/Modal' - ], - function(AddTagAttributeView, Modal) { - var view = new AddTagAttributeView({ - "enumDefCollection": that.enumDefCollection - }); - that.modal = new Modal({ - title: 'Add Attribute', - content: view, - cancelText: "Cancel", - okText: 'Add', - allowCancel: true, - okCloses: false - }).open(); - that.modal.$el.find('button.ok').attr("disabled", "true"); - view.ui.addAttributeDiv.on('keyup', '.attributeInput', function(e) { - if (e.target.value.trim() == "") { - that.modal.$el.find('button.ok').attr("disabled", "disabled"); - } else { - that.modal.$el.find('button.ok').removeAttr("disabled"); - } - }); - that.modal.on('ok', function() { - var newAttributeList = view.collection.toJSON(), - activeTagAttribute = _.extend([], that.model.get('attributeDefs')), - superTypes = that.model.get('superTypes'); - - _.each(superTypes, function(name) { - var parentTags = that.collection.fullCollection.findWhere({ name: name }); - activeTagAttribute = activeTagAttribute.concat(parentTags.get('attributeDefs')); - }); - - var duplicateAttributeList = [], - saveObj = $.extend(true, {}, that.model.toJSON()); - _.each(newAttributeList, function(obj) { - var duplicateCheck = _.find(activeTagAttribute, function(activeTagObj) { - return activeTagObj.name.toLowerCase() === obj.name.toLowerCase(); - }); - if (duplicateCheck) { - duplicateAttributeList.push(_.escape(obj.name)); - } else { - saveObj.attributeDefs.push(obj); - } - }); - var notifyObj = { - modal: true, - confirm: { - confirm: true, - buttons: [{ - text: 'Ok', - addClass: 'btn-atlas btn-md', - click: function(notice) { - notice.remove(); - } - }, - null - ] - } - } - if (saveObj && !duplicateAttributeList.length) { - that.onSaveButton(saveObj, Messages.tag.addAttributeSuccessMessage); - } else { - if (duplicateAttributeList.length < 2) { - var text = "Attribute " + duplicateAttributeList.join(",") + " is duplicate !" - } else { - if (newAttributeList.length > duplicateAttributeList.length) { - var text = "Attributes: " + duplicateAttributeList.join(",") + " are duplicate ! Do you want to continue with other attributes ?" - notifyObj = { - ok: function(argument) { - that.onSaveButton(saveObj, Messages.tag.addAttributeSuccessMessage); - }, - cancel: function(argument) {} - } - } else { - var text = "All attributes are duplicate !" - } - } - notifyObj['text'] = text; - Utils.notifyConfirm(notifyObj); - } - }); - that.modal.on('closeModal', function() { - that.modal.trigger('cancel'); - }); - }); - }, - textAreaChangeEvent: function(view) { - if (this.model.get('description') === view.ui.description.val() || view.ui.description.val().length == 0 || view.ui.description.val().trim().length === 0) { - this.modal.$el.find('button.ok').prop('disabled', true); - } else { - this.modal.$el.find('button.ok').prop('disabled', false); - } - }, - onPublishClick: function(view) { - var saveObj = _.extend(this.model.toJSON(), { 'description': view.ui.description.val().trim() }); - this.onSaveButton(saveObj, Messages.tag.updateTagDescriptionMessage); - this.ui.description.show(); - }, - onEditButton: function(e) { - var that = this; - $(e.currentTarget).blur(); - require([ - 'views/tag/CreateTagLayoutView', - 'modules/Modal' - ], function(CreateTagLayoutView, Modal) { - var view = new CreateTagLayoutView({ 'tagCollection': that.collection, 'model': that.model, 'tag': that.tag, 'enumDefCollection': enumDefCollection }); - that.modal = new Modal({ - title: 'Edit Classification', - content: view, - cancelText: "Cancel", - okText: 'Save', - allowCancel: true, - }).open(); - view.ui.description.on('keyup input', function(e) { - $(this).val($(this).val().replace(/\s+/g, ' ')); - that.textAreaChangeEvent(view); - e.stopPropagation(); - }); - that.modal.$el.find('button.ok').prop('disabled', true); - that.modal.on('ok', function() { - that.onPublishClick(view); - }); - that.modal.on('closeModal', function() { - that.modal.trigger('cancel'); - }); - }); - } - }); - return TagAttributeDetailLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/tag/TagAttributeItemView.js b/dashboardv2/public/js/views/tag/TagAttributeItemView.js deleted file mode 100644 index 0016bbe3331..00000000000 --- a/dashboardv2/public/js/views/tag/TagAttributeItemView.js +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -define(['require', - 'backbone', - 'hbs!tmpl/tag/TagAttributeItemView_tmpl' - -], function(require, Backbone, TagAttributeItemViewTmpl) { - 'use strict'; - - return Backbone.Marionette.ItemView.extend( - /** @lends GlobalExclusionListView */ - { - - template: TagAttributeItemViewTmpl, - - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - attributeInput: "[data-id='attributeInput']", - close: "[data-id='close']", - dataTypeSelector: "[data-id='dataTypeSelector']" - }, - /** ui events hash */ - events: function() { - var events = {}; - events["keyup " + this.ui.attributeInput] = function(e) { - this.model.set({ "name": e.target.value.trim() }); - }; - events["change " + this.ui.dataTypeSelector] = function(e) { - this.model.set({ "typeName": e.target.value.trim() }); - }; - events["click " + this.ui.close] = 'onCloseButton'; - return events; - }, - - /** - * intialize a new GlobalExclusionComponentView Layout - * @constructs - */ - initialize: function(options) { - this.parentView = options.parentView; - - }, - onRender: function() { - var that = this; - this.parentView.enumDefCollection.fullCollection.each(function(model) { - that.ui.dataTypeSelector.append(""); - }); - }, - onCloseButton: function() { - var tagName = this.parentView.$el.find('[data-id="tagName"]').val(); - if (this.parentView.collection.models.length > 0) { - this.model.destroy(); - } - if (this.parentView.$el.find('input').length === 1) { - $(this.ui.close).hide(); - } - } - }); -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/tag/TagDetailLayoutView.js b/dashboardv2/public/js/views/tag/TagDetailLayoutView.js deleted file mode 100644 index e5a62a01559..00000000000 --- a/dashboardv2/public/js/views/tag/TagDetailLayoutView.js +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/tag/TagDetailLayoutView_tmpl', -], function(require, Backbone, TagDetailLayoutView_tmpl) { - 'use strict'; - - var TagDetailLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends TagDetailLayoutView */ - { - _viewName: 'TagDetailLayoutView', - - template: TagDetailLayoutView_tmpl, - - /** Layout sub regions */ - regions: { - RSearchResultLayoutView: "#r_searchResultLayoutView", - RTagAttributeDetailLayoutView: "#r_TagAttributeDetailLayoutView" - }, - - /** ui selector cache */ - ui: {}, - /** ui events hash */ - events: function() {}, - /** - * intialize a new TagDetailLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'tag', 'value', 'glossaryCollection', 'classificationDefCollection', 'entityDefCollection', 'typeHeaders', 'enumDefCollection', 'searchVent')); - this.collection = this.classificationDefCollection; - }, - bindEvents: function() {}, - onRender: function() { - this.renderSearchResultLayoutView(); - this.renderTagAttributeCompositeView(); - }, - renderSearchResultLayoutView: function() { - var that = this; - require(['views/search/SearchResultLayoutView'], function(SearchResultLayoutView) { - var value = { - 'tag': that.tag, - 'searchType': 'basic' - }; - if (that.RSearchResultLayoutView) { - that.RSearchResultLayoutView.show(new SearchResultLayoutView({ - value: _.extend({}, that.value, value), - entityDefCollection: that.entityDefCollection, - typeHeaders: that.typeHeaders, - tagCollection: that.collection, - enumDefCollection: that.enumDefCollection, - classificationDefCollection: that.classificationDefCollection, - glossaryCollection: that.glossaryCollection, - searchVent: that.searchVent, - fromView: "classification" - })); - } - }); - }, - renderTagAttributeCompositeView: function() { - var that = this; - require(['views/tag/TagAttributeDetailLayoutView'], function(TagAttributeDetailLayoutView) { - if (that.RTagAttributeDetailLayoutView) { - that.RTagAttributeDetailLayoutView.show(new TagAttributeDetailLayoutView({ - tag: that.tag, - collection: that.collection, - enumDefCollection: that.enumDefCollection - })); - } - }); - } - }); - return TagDetailLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/tag/TagDetailTableLayoutView.js b/dashboardv2/public/js/views/tag/TagDetailTableLayoutView.js deleted file mode 100644 index c780deb7d33..00000000000 --- a/dashboardv2/public/js/views/tag/TagDetailTableLayoutView.js +++ /dev/null @@ -1,347 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/tag/TagDetailTableLayoutView_tmpl', - 'utils/CommonViewFunction', - 'utils/Utils', - 'collection/VTagList', - 'utils/Messages', - 'utils/Enums' -], function(require, Backbone, TagDetailTableLayoutView_tmpl, CommonViewFunction, Utils, VTagList, Messages, Enums) { - 'use strict'; - - var TagDetailTableLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends TagDetailTableLayoutView */ - { - _viewName: 'TagDetailTableLayoutView', - - template: TagDetailTableLayoutView_tmpl, - - /** Layout sub regions */ - regions: { - RTagTableLayoutView: "#r_tagTableLayoutView" - }, - - /** ui selector cache */ - ui: { - detailValue: "[data-id='detailValue']", - tagList: "[data-id='tagList']", - addTag: "[data-id='addTag']", - deleteTag: "[data-id='delete']", - editTag: "[data-id='edit']", - checkPropagtedTag: "[data-id='checkPropagtedTag']", - propagatedFromClick: "[data-id='propagatedFromClick']" - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.addTag] = function(e) { - this.addModalView(e); - }; - events["click " + this.ui.deleteTag] = function(e) { - this.onClickTagCross(e); - }; - events["click " + this.ui.editTag] = function(e) { - this.editTagDataModal(e); - }; - events["click " + this.ui.propagatedFromClick] = function(e) { - Utils.setUrl({ - url: '#!/detailPage/' + $(e.currentTarget).data("guid"), - mergeBrowserUrl: false, - trigger: true - }); - }; - events["click " + this.ui.checkPropagtedTag] = 'onCheckPropagtedTag'; - return events; - }, - /** - * intialize a new TagDetailTableLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'entity', 'guid', 'tags', 'entityName', 'fetchCollection', 'enumDefCollection', 'classificationDefCollection')); - this.collectionObject = this.entity; - this.tagCollection = new VTagList(); - this.allTags = _.sortBy(_.toArray(this.collectionObject.classifications), "typeName"); - var paramObj = Utils.getUrlState.getQueryParams(); - this.value = { tabActive: "classification", showPC: "true", filter: "all" }; - if (paramObj) { - if (paramObj.showPC) { - this.value.showPC = paramObj.showPC; - } - if (paramObj.filter) { - this.value.filter = paramObj.filter; - } - } - this.commonTableOptions = { - collection: this.tagCollection, - includeFilter: false, - includePagination: true, - includeFooterRecords: true, - includePageSize: true, - includeGotoPage: true, - includeAtlasTableSorting: true, - gridOpts: { - className: "table table-hover backgrid table-quickMenu", - emptyText: 'No records found!' - }, - filterOpts: {}, - paginatorOpts: {} - }; - }, - bindEvents: function() {}, - onRender: function() { - this.ui.checkPropagtedTag.prop("checked", this.value.showPC === "true"); - this.renderFilter(); - if (this.tagNotFound === undefined && this.value.filter === "all") { - this.updateCollection(this.value.filter); - } - this.renderTableLayoutView(); - }, - updateCollection: function(value) { - var newList = null - if (this.value.showPC === "true") { - if (value === "all") { - newList = this.allTags; - } else { - newList = _.filter(this.allTags, function(obj) { - if (obj.typeName === value) { - return true; - } - }); - } - } else { - if (value === "all") { - newList = this.tags.self; - } else { - newList = _.filter(this.tags.self, function(obj) { - if (obj.typeName === value) { - return true; - } - }); - } - } - this.tagCollection.fullCollection.reset(newList); - if (value) { - this.value["filter"] = value; - this.triggetUrl(); - } - }, - triggetUrl: function() { - var paramObj = Utils.getUrlState.getQueryParams(); - if (paramObj && paramObj.tabActive === "classification") { - Utils.setUrl({ - url: '#!/detailPage/' + this.guid, - mergeBrowserUrl: false, - urlParams: this.value, - trigger: false - }); - } - }, - renderFilter: function() { - var tagName = "", - that = this; - if (this.value.showPC === "false") { - _.each(this.tags.self, function(val) { - var typeName = val.typeName; - tagName += ''; - }); - } else { - _.each(this.tags.combineMap, function(val, key) { - tagName += ''; - }); - } - this.ui.tagList.html(tagName); - if (this.value.filter && this.ui.tagList.val() !== this.value.filter) { - if (this.ui.tagList.find("option[value='" + this.value.filter + "']").length > 0) { - this.ui.tagList.val(this.value.filter); - this.updateCollection(this.value.filter); - } else { - this.tagNotFound = true; - this.updateCollection("all"); - } - } - this.ui.tagList.select2({ placeholder: "Search for tag" }).on("change", function() { - var value = that.ui.tagList.val(); - that.updateCollection(value); - }); - }, - renderTableLayoutView: function() { - var that = this; - require(['utils/TableLayout'], function(TableLayout) { - var cols = new Backgrid.Columns(that.getSchemaTableColumns()); - if (that.RTagTableLayoutView) { - that.RTagTableLayoutView.show(new TableLayout(_.extend({}, that.commonTableOptions, { - columns: cols - }))); - } - }); - }, - getSchemaTableColumns: function(options) { - var that = this, - col = {}; - - return this.tagCollection.constructor.getTableCols({ - typeName: { - label: "Classification", - cell: "html", - editable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - if (that.guid !== model.get('entityGuid')) { - var purgeEntityBtn = (Enums.isEntityPurged[model.get('entityStatus')]) ? ' title="Entity not available" disabled' : ' data-id="propagatedFromClick"', - propagtedFrom = ' Propagated From '; - return '' + model.get('typeName') + '' + propagtedFrom; - } else { - return '' + model.get('typeName') + ''; - } - } - }) - }, - attributes: { - label: "Attributes", - cell: "html", - editable: false, - sortable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var values = model.get('attributes'), - data = that.classificationDefCollection.fullCollection.findWhere({ 'name': model.get('typeName') }), - attributeDefs = data ? Utils.getNestedSuperTypeObj({ data: data.toJSON(), collection: that.classificationDefCollection, attrMerge: true }) : null, - tagValue = 'NA', - dataType; - if (!_.isEmpty(attributeDefs)) { - var stringValue = ""; - _.each(_.sortBy(_.map(attributeDefs, function(obj) { - obj['sortKey'] = obj.name && _.isString(obj.name) ? obj.name.toLowerCase() : "-"; - return obj; - }), 'sortKey'), function(sortedObj) { - var val = _.isNull(values[sortedObj.name]) ? "-" : values[sortedObj.name], - key = sortedObj.name; - if (_.isObject(val)) { - val = JSON.stringify(val); - } - if (sortedObj.typeName === "date") { - val = Utils.formatDate({ date: val }); - } - stringValue += "" + _.escape(key) + "" + _.escape(val) + ""; - }); - tagValue = "
        " + stringValue + "
        NameValue
        "; - } - return tagValue; - } - }) - }, - tool: { - label: "Action", - cell: "html", - editable: false, - sortable: false, - formatter: _.extend({}, Backgrid.CellFormatter.prototype, { - fromRaw: function(rawValue, model) { - var deleteData = '', - editData = '', - btnObj = null; - if (that.guid === model.get('entityGuid')) { - return '
        ' + deleteData + editData + '
        ' - } else if (that.guid !== model.get('entityGuid') && model.get('entityStatus') === "DELETED") { - return '
        ' + deleteData + '
        '; - } - } - }) - }, - }, - this.tagCollection); - }, - addModalView: function(e) { - var that = this; - require(['views/tag/AddTagModalView'], function(AddTagModalView) { - var view = new AddTagModalView({ - guid: that.guid, - modalCollection: that.collection, - collection: that.classificationDefCollection, - enumDefCollection: that.enumDefCollection - }); - }); - }, - onClickTagCross: function(e) { - var that = this, - tagName = $(e.currentTarget).data("name"), - entityGuid = $(e.currentTarget).data("entityguid"); - CommonViewFunction.deleteTag({ - tagName: tagName, - guid: that.guid, - associatedGuid: that.guid != entityGuid ? entityGuid : null, - msg: "
        Remove: " + "" + _.escape(tagName) + " assignment from " + this.entityName + "?
        ", - titleMessage: Messages.removeTag, - okText: "Remove", - showLoader: function() { - that.$('.fontLoader').show(); - that.$('.tableOverlay').show(); - }, - hideLoader: function() { - that.$('.fontLoader').hide(); - that.$('.tableOverlay').hide(); - }, - callback: function() { - this.hideLoader(); - if (that.fetchCollection) { - that.fetchCollection(); - } - } - }); - }, - editTagDataModal: function(e) { - var that = this, - tagName = $(e.currentTarget).data('name'), - tagModel = _.find(that.collectionObject.classifications, function(tag) { - return (tagName === tag.typeName && that.guid === tag.entityGuid); - }); - require([ - 'views/tag/AddTagModalView' - ], function(AddTagModalView) { - var view = new AddTagModalView({ - 'tagModel': tagModel, - 'callback': function() { - that.fetchCollection(); - }, - 'guid': that.guid, - 'collection': that.classificationDefCollection, - 'enumDefCollection': that.enumDefCollection - }); - }); - }, - onCheckPropagtedTag: function(e) { - var that = this, - unPropagatedTags = []; - e.stopPropagation(); - if (e.target.checked) { - that.tagCollection.fullCollection.reset(this.allTags); - } else { - that.tagCollection.fullCollection.reset(this.tags.self); - } - this.value.showPC = "" + e.target.checked; - this.value.filter = "all"; - this.triggetUrl(); - this.renderFilter(e.target.checked); - } - }); - return TagDetailTableLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/js/views/tag/TagLayoutView.js b/dashboardv2/public/js/views/tag/TagLayoutView.js deleted file mode 100644 index 38df18792d5..00000000000 --- a/dashboardv2/public/js/views/tag/TagLayoutView.js +++ /dev/null @@ -1,661 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'backbone', - 'hbs!tmpl/tag/TagLayoutView_tmpl', - 'utils/Utils', - 'utils/Messages', - 'utils/Globals', - 'utils/UrlLinks', - 'collection/VTagList' -], function(require, Backbone, TagLayoutViewTmpl, Utils, Messages, Globals, UrlLinks, VTagList) { - 'use strict'; - - var TagLayoutView = Backbone.Marionette.LayoutView.extend( - /** @lends TagLayoutView */ - { - _viewName: 'TagLayoutView', - - template: TagLayoutViewTmpl, - - /** Layout sub regions */ - regions: {}, - - /** ui selector cache */ - ui: { - tagsParent: "[data-id='tagsParent']", - tagsList: "[data-id='tagsList']", - createTag: "[data-id='createTag']", - tags: "[data-id='tags']", - offLineSearchTag: "[data-id='offlineSearchTag']", - treeLov: "[data-id='treeLov']", - refreshTag: '[data-id="refreshTag"]', - tagView: 'input[name="tagView"]', - expandArrow: '[data-id="expandArrow"]', - tagTreeLoader: '[data-id="tagTreeLoader"]', - tagTreeTextLoader: '[data-id="tagTreeTextLoader"]', - tagTreeView: '[data-id="tagTreeView"]' - }, - /** ui events hash */ - events: function() { - var events = {}; - events["click " + this.ui.createTag] = 'onClickCreateTag'; - events["click " + this.ui.tags] = 'onTagList'; - events["keyup " + this.ui.offLineSearchTag] = 'offlineSearchTag'; - events["change " + this.ui.treeLov] = 'onTreeSelect'; - events['click ' + this.ui.refreshTag] = 'fetchCollections'; - events["change " + this.ui.tagView] = 'tagViewToggle'; - events["click " + this.ui.expandArrow] = 'toggleChild'; - return events; - }, - /** - * intialize a new TagLayoutView Layout - * @constructs - */ - initialize: function(options) { - _.extend(this, _.pick(options, 'tag', 'collection', 'typeHeaders', 'value', 'enumDefCollection', 'classificationAndMetricEvent')); - this.viewType = "flat"; - this.query = { - flat: { - tagName: null - }, - tree: { - tagName: null - } - }; - if (Utils.getUrlState.isTagTab() && this.value && this.value.viewType) { - this.viewType = this.value.viewType; - } - this.query[this.viewType].tagName = this.tag; - }, - bindEvents: function() { - var that = this; - this.listenTo(this.collection.fullCollection, "reset add remove", function() { - this.tagsGenerator(); - this.changeLoaderTextState(false); - }, this); - this.ui.tagsList.on('click', 'li.parent-node a', function() { - that.setUrl(this.getAttribute("href")); - }); - $('body').on('click', '.tagPopoverOptions li', function(e) { - that.$('.tagPopover').popover('hide'); - that[$(this).find('a').data('fn')](e) - }); - this.classificationAndMetricEvent.on("classification:Update:ClassificationTab", function(options) { - that.changeLoaderTextState(false); - }); - }, - onRender: function() { - var that = this; - this.changeLoaderTextState(false); - this.changeLoaderState(true); - this.bindEvents(); - this.checkTagOnRefresh(); - }, - checkTagOnRefresh: function() { - var that = this, - tagName = this.options.tag, - presentTag = this.collection.fullCollection.findWhere({ name: tagName }), - tag = new VTagList(); - if (!presentTag && tagName) { - tag.url = UrlLinks.classicationApiUrl(tagName); - tag.fetch({ - success: function(dataOrCollection, tagDetails) { - that.collection.fullCollection.add(tagDetails); - that.changeLoaderTextState(true); - }, - cust_error: function(model, response) { - that.tagsGenerator(); - } - }); - } else { - this.tagsGenerator(); - } - }, - changeLoaderState: function(showLoader) { - if (showLoader) { - this.ui.tagTreeLoader.show(); - this.ui.tagTreeView.hide(); - } else { - this.ui.tagTreeLoader.hide(); - this.ui.tagTreeView.show(); - } - }, - changeLoaderTextState: function(showLoader) { - if (showLoader) { - this.ui.tagTreeTextLoader.show(); - } else { - this.ui.tagTreeTextLoader.hide(); - } - }, - fetchCollections: function() { - this.changeLoaderState(true); - this.ui.refreshTag.attr("disabled", true); - this.collection.fetch({ reset: true }); - this.ui.offLineSearchTag.val(""); - }, - manualRender: function(options) { - this.tag = options && options.tagName; - _.extend(this.value, options); - this.query[this.viewType].tagName = this.tag; - if (options && options.viewType) { - this.viewType = options.viewType; - this.changeLoaderTextState(false); - } - if (!this.createTag) { - this.setValues(true); - } - }, - renderTreeList: function() { - var that = this; - this.ui.treeLov.empty(); - var treeStr = ''; - this.collection.fullCollection.each(function(model) { - var name = Utils.getName(model.toJSON(), 'name'); - treeStr += ''; - }); - that.ui.treeLov.html(treeStr); - that.ui.treeLov.select2({ - placeholder: "Search Classification", - allowClear: true - }); - }, - onTreeSelect: function() { - var name = this.ui.treeLov.val(); - Utils.setUrl({ - url: (name ? '#!/tag/tagAttribute/' + name : '#!/tag'), - urlParams: { - viewType: 'tree', - }, - mergeBrowserUrl: false, - trigger: true, - updateTabState: true - }); - }, - setValues: function(manual) { - var el = this.ui.tagsList; - if (this.viewType == "tree") { - el = this.ui.tagsParent; - if (!this.ui.tagView.prop("checked")) { - this.ui.tagView.prop("checked", true).trigger("change"); - } - } else { - if (this.ui.tagView.prop("checked")) { - this.ui.tagView.prop("checked", false).trigger("change"); - } - } - var $firstEl = el.find('li a') ? el.find('li a').first() : null; - if (Utils.getUrlState.isTagTab()) { - if (!this.tag) { - this.selectFirst = false; - el.find('li').first().addClass('active'); - if ($firstEl && $firstEl.length) { - url: $firstEl.attr("href"), - Utils.setUrl({ - url: $firstEl.attr("href"), - mergeBrowserUrl: false, - updateTabState: true - }); - } - } else { - var presentTag = this.collection.fullCollection.findWhere({ name: this.tag }), - url = Utils.getUrlState.getQueryUrl().queyParams[0], - tag = this.tag, - query = Utils.getUrlState.getQueryParams() || null; - if (!presentTag) { - tag = $firstEl.data('name'); - url = $firstEl && $firstEl.length ? $firstEl.attr("href") : '#!/tag'; - if ($firstEl && $firstEl.length) { - _.extend(query, { dlttag: true }) - } - } - Utils.setUrl({ - url: url, - urlParams: query, - updateTabState: true - }); - if (!presentTag) { - return false; - } - el.find('li').removeClass('active'); // remove selected - el.find('li.parent-node').each(function() { - // based on browser url select tag. - var target = $(this); - if (target.children('div').find('a').text() === tag) { - target.addClass('active'); - target.parents('ul').addClass('show').removeClass('hide'); // Don't use toggle - return false; - } - }); - - } - } - }, - tagsGenerator: function(searchString) { - var tagParents = '', - tagLists = ''; - - if (this.collection && this.collection.fullCollection.length >= 0) { - var sortedCollection = this.collection.fullCollection; - this.tagTreeList = this.getTagTreeList({ collection: sortedCollection }); - if (searchString) { - if (this.viewType == "flat") { - this.ui.tagsList.empty().html(this.generateTree({ 'data': sortedCollection, 'searchString': searchString })); - } else { - this.ui.tagsParent.empty().html(this.generateTree({ 'data': this.tagTreeList, 'isTree': true, 'searchString': searchString })); - } - } else { - this.ui.tagsParent.empty().html(this.generateTree({ 'data': this.tagTreeList, 'isTree': true, 'searchString': searchString })); - this.ui.tagsList.empty().html(this.generateTree({ 'data': sortedCollection, 'searchString': searchString })); - - } - this.createTagAction(); - this.setValues(); - this.renderTreeList(); - if (this.createTag) { - this.createTag = false; - } - - } - this.changeLoaderState(false); - this.ui.refreshTag.attr("disabled", false); - }, - getTagTreeList: function(options) { - var that = this, - collection = options.collection, - listOfParents = {}, - getChildren = function(options) { - var children = options.children, - data = []; - if (children && children.length) { - _.each(children, function(name) { - var child = collection.find({ 'name': name }); - if (child) { - var modelJSON = child.toJSON(); - data.push({ - name: name, - children: getChildren({ children: modelJSON.subTypes }) - }); - } - }); - } - return data; - } - collection.each(function(model) { - var modelJSON = model.toJSON(); - if (modelJSON.superTypes.length == 0) { - var name = modelJSON.name; - listOfParents[name] = { - name: name, - children: getChildren({ children: modelJSON.subTypes }) - } - } - }); - return listOfParents; - }, - generateTree: function(options) { - var data = options.data, - isTree = options.isTree, - searchString = options.searchString, - that = this, - element = '', - getElString = function(options) { - var name = options.name, - hasChild = isTree && options.children && options.children.length; - return '
      • ' + - '
        ' + - (hasChild ? '' : '') + - '' + name + '
        ' + - (isTree && hasChild ? '
          ' + that.generateTree({ 'data': options.children, 'isTree': isTree }) + '
        ' : '') + '
      • '; - }; - if (isTree) { - _.each(data, function(obj) { - element += getElString({ - name: obj.name, - children: obj.children - }); - }); - } else { - data.each(function(obj) { - var name = obj.get('name'); - if (searchString) { - if (name.search(new RegExp(searchString, "i")) != -1) { - element += getElString({ - name: obj.get('name'), - children: null - }); - } else { - return; - } - } else { - element += getElString({ - name: obj.get('name'), - children: null - }); - } - - }); - } - return element; - }, - toggleChild: function(e) { - var el = $(e.currentTarget); - if (el) { - el.parent().siblings('ul.child').toggleClass('hide show'); - } - }, - tagViewToggle: function(e) { - if (e.currentTarget.checked) { - this.$('.tree-view').show(); - this.$('.list-view').hide(); - this.viewType = "tree"; - } else { - this.viewType = "flat"; - this.$('.tree-view').hide(); - this.$('.list-view').show(); - } - if (Utils.getUrlState.isTagTab()) { - var name = this.query[this.viewType].tagName; - Utils.setUrl({ - url: (name ? '#!/tag/tagAttribute/' + name : '#!/tag'), - urlParams: { - viewType: this.viewType, - }, - mergeBrowserUrl: false, - trigger: true, - updateTabState: true - }); - } - }, - onClickCreateTag: function(e) { - var that = this, - nodeName = e.currentTarget.nodeName; - $(e.currentTarget).attr("disabled", "true"); - require([ - 'views/tag/CreateTagLayoutView', - 'modules/Modal' - ], function(CreateTagLayoutView, Modal) { - var name = (!(nodeName == "BUTTON") ? that.query[that.viewType].tagName : null); - var view = new CreateTagLayoutView({ 'tagCollection': that.collection, 'selectedTag': name, 'enumDefCollection': enumDefCollection }), - modal = new Modal({ - title: 'Create a new classification', - content: view, - cancelText: "Cancel", - okCloses: false, - okText: 'Create', - allowCancel: true, - }).open(); - modal.$el.find('button.ok').attr("disabled", "true"); - view.ui.tagName.on('keyup input', function(e) { - view.ui.description.val($(this).val().replace(/\s+/g, ' ')); - }); - view.ui.description.on('input keydown', function(e) { - $(this).val($(this).val().replace(/\s+/g, ' ')); - }); - modal.on('shownModal', function() { - view.ui.parentTag.select2({ - multiple: true, - placeholder: "Search Classification", - allowClear: true - }); - }); - modal.on('ok', function() { - modal.$el.find('button.ok').showButtonLoader(); - that.onCreateButton(view, modal); - }); - modal.on('closeModal', function() { - modal.trigger('cancel'); - that.ui.createTag.removeAttr("disabled"); - }); - }); - }, - onCreateButton: function(ref, modal) { - var that = this; - var validate = true; - if (modal.$el.find(".attributeInput").length > 0) { - modal.$el.find(".attributeInput").each(function() { - if ($(this).val() === "") { - $(this).css('borderColor', "red") - validate = false; - } - }); - } - modal.$el.find(".attributeInput").keyup(function() { - $(this).css('borderColor', "#e8e9ee"); - modal.$el.find('button.ok').removeAttr("disabled"); - }); - if (!validate) { - Utils.notifyInfo({ - content: "Please fill the attributes or delete the input box" - }); - modal.$el.find('button.ok').hideButtonLoader(); - return; - } - this.name = ref.ui.tagName.val(); - this.description = ref.ui.description.val(); - var superTypes = []; - if (ref.ui.parentTag.val() && ref.ui.parentTag.val()) { - superTypes = ref.ui.parentTag.val(); - } - var attributeObj = ref.collection.toJSON(); - if (ref.collection.length === 1 && ref.collection.first().get("name") === "") { - attributeObj = []; - } - - if (attributeObj.length) { - var superTypesAttributes = []; - _.each(superTypes, function(name) { - var parentTags = that.collection.fullCollection.findWhere({ name: name }); - superTypesAttributes = superTypesAttributes.concat(parentTags.get('attributeDefs')); - }); - - - var duplicateAttributeList = []; - _.each(attributeObj, function(obj) { - var duplicateCheck = _.find(superTypesAttributes, function(activeTagObj) { - return activeTagObj.name.toLowerCase() === obj.name.toLowerCase(); - }); - if (duplicateCheck) { - duplicateAttributeList.push(_.escape(obj.name)); - } - }); - var notifyObj = { - modal: true, - confirm: { - confirm: true, - buttons: [{ - text: 'Ok', - addClass: 'btn-atlas btn-md', - click: function(notice) { - notice.remove(); - } - }, - null - ] - } - } - if (duplicateAttributeList.length) { - if (duplicateAttributeList.length < 2) { - var text = "Attribute " + duplicateAttributeList.join(",") + " is duplicate !" - } else { - if (attributeObj.length > duplicateAttributeList.length) { - var text = "Attributes: " + duplicateAttributeList.join(",") + " are duplicate !" - } else { - var text = "All attributes are duplicate !" - } - } - notifyObj['text'] = text; - Utils.notifyConfirm(notifyObj); - modal.$el.find('button.ok').hideButtonLoader(); - return false; - } - } - this.json = { - classificationDefs: [{ - 'name': this.name.trim(), - 'description': this.description.trim(), - 'superTypes': superTypes.length ? superTypes : [], - "attributeDefs": attributeObj - }], - entityDefs: [], - enumDefs: [], - structDefs: [] - - }; - new this.collection.model().set(this.json).save(null, { - success: function(model, response) { - that.changeLoaderState(true); - var classificationDefs = model.get('classificationDefs'); - that.ui.createTag.removeAttr("disabled"); - that.createTag = true; - if (classificationDefs[0]) { - _.each(classificationDefs[0].superTypes, function(superType) { - var superTypeModel = that.collection.fullCollection.find({ name: superType }), - subTypes = []; - if (superTypeModel) { - subTypes = superTypeModel.get('subTypes'); - subTypes.push(classificationDefs[0].name); - superTypeModel.set({ 'subTypes': _.uniq(subTypes) }); - } - }); - } - that.collection.fullCollection.add(classificationDefs); - that.setUrl('#!/tag/tagAttribute/' + ref.ui.tagName.val() + '?tag=' + ref.ui.tagName.val(), true); - Utils.notifySuccess({ - content: "Classification " + that.name + Messages.getAbbreviationMsg(false, 'addSuccessMessage') - }); - modal.trigger('cancel'); - modal.$el.find('button.ok').hideButtonLoader(); - that.changeLoaderState(false); - that.typeHeaders.fetch({ reset: true }); - }, - complete: function() { - modal.$el.find("button.ok").hideButtonLoader(); - } - }); - }, - setUrl: function(url, create) { - Utils.setUrl({ - url: url, - mergeBrowserUrl: false, - trigger: true, - updateTabState: true - }); - }, - onTagList: function(e, toggle) { - var that = this; - e.stopPropagation(); - if (e.target.nodeName === "A") { - that.$('.tagPopover').popover('hide'); - $(e.currentTarget).parents('ul.tag-tree').find('li.active').removeClass("active"); - $(e.currentTarget).addClass("active"); - } - }, - offlineSearchTag: function(e) { - var type = $(e.currentTarget).data('type'); - this.tagsGenerator($(e.currentTarget).val()); - }, - createTagAction: function() { - var that = this; - Utils.generatePopover({ - el: this.$('.tagPopover'), - contentClass: 'tagPopoverOptions', - popoverOptions: { - content: function() { - return ""; - } - } - }); - }, - onSearchTag: function() { - var el = this.ui.tagsList; - if (this.viewType == "tree") { - el = this.ui.tagsParent; - } - Utils.setUrl({ - url: '#!/search/searchResult', - urlParams: { - tag: el.find('li.active').find('a[data-name]').data('name'), - searchType: "basic", - dslChecked: false - }, - mergeBrowserUrl: false, - trigger: true, - updateTabState: true - }); - }, - onDeleteTag: function() { - var that = this, - notifyObj = { - modal: true, - ok: function(obj) { - that.notificationModal = obj; - obj.showButtonLoader(); - that.onNotifyOk(); - }, - okCloses: false, - cancel: function(argument) {} - } - var text = "Are you sure you want to delete the classification" - notifyObj['text'] = text; - Utils.notifyConfirm(notifyObj); - }, - onNotifyOk: function(data) { - var that = this, - deleteTagData = this.collection.fullCollection.findWhere({ name: this.tag }), - superTypeOfDeleteTag = deleteTagData.get('superTypes'), - superTypeObj = superTypeOfDeleteTag ? this.collection.fullCollection.findWhere({ name: superTypeOfDeleteTag[0] }) : null; - - deleteTagData.deleteTag({ - typeName: that.tag, - success: function() { - Utils.notifySuccess({ - content: "Classification " + that.tag + Messages.getAbbreviationMsg(false, 'deleteSuccessMessage') - }); - //delete current classification from subTypes list of parent classification if any - if (superTypeObj) { - var parentSubTypeUpdate = _.reject(superTypeObj.get('subTypes'), function(subtype) { - return subtype === that.tag; - }); - superTypeObj.set('subTypes', parentSubTypeUpdate); - } - // if deleted tag is prviously searched then remove that tag url from save state of tab. - var searchUrl = Globals.saveApplicationState.tabState.searchUrl; - var urlObj = Utils.getUrlState.getQueryParams(searchUrl); - if (urlObj && urlObj.tag && urlObj.tag === that.tag) { - Globals.saveApplicationState.tabState.searchUrl = "#!/search"; - } - that.collection.fullCollection.remove(deleteTagData); - // to update tag list of search tab fetch typeHeaders. - that.typeHeaders.fetch({ reset: true }); - }, - cust_error: function() {}, - complete: function() { - that.notificationModal.hideButtonLoader(); - that.notificationModal.remove(); - } - }); - } - }); - return TagLayoutView; -}); \ No newline at end of file diff --git a/dashboardv2/public/migration-status.html.tpl b/dashboardv2/public/migration-status.html.tpl deleted file mode 100644 index 1e7c991e410..00000000000 --- a/dashboardv2/public/migration-status.html.tpl +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - Atlas - - - - - - - - - - - - - - -
        -
        -
        - - - - - - - \ No newline at end of file diff --git a/dashboardv3/.gitignore b/dashboardv3/.gitignore deleted file mode 100644 index f75b10dfa1b..00000000000 --- a/dashboardv3/.gitignore +++ /dev/null @@ -1,29 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. - -.DS_Store -.bower-*/ -.idea/ -node_modules/ -public/js/libs/ -dist -target/ -*.log -*.tgz -node/ -.npmrc -dist/ -!public/js/external_lib/atlas-lineage/dist \ No newline at end of file diff --git a/dashboardv3/gruntfile.js b/dashboardv3/gruntfile.js deleted file mode 100644 index b1b7b59da99..00000000000 --- a/dashboardv3/gruntfile.js +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -'use strict'; -var sass = require('node-sass'); -module.exports = function(grunt) { - var buildTime = new Date().getTime(), - distPath = './dist/n', - libPath = distPath + '/js/libs/', - isDashboardDirectory = grunt.file.isDir('public'), - nodeModulePath = './node_modules/', - modulesPath = 'public/'; - if (!isDashboardDirectory) { - modulesPath = '../public/' - } - - grunt.initConfig({ - watch: { - js: { - files: ['public/**/*.js'], - tasks: ['copy:build'] - }, - html: { - files: ['public/**/*.html'], - tasks: ['copy:build'] - }, - css: { - files: ['public/**/*.scss', 'public/**/*.css'], - tasks: ['copy:build', 'sass'] - }, - image: { - files: ['public/**/*.{ico,gif,png}'], - tasks: ['copy:build'] - } - }, - connect: { - server: { - options: { - port: 9999, - base: distPath, - // change this to '0.0.0.0' to access the server from outside - hostname: '0.0.0.0', - middleware: function(connect, options, middlewares) { - middlewares.unshift(require('grunt-middleware-proxy/lib/Utils').getProxyMiddleware()); - return middlewares; - } - }, - proxies: [{ - context: '/api', // the context of the data service - host: '127.0.0.1', - auth: "admin:admin", - port: 21000, // the port that the data service is running on - https: false - }], - }, - }, - npmcopy: { - js: { - options: { - destPrefix: libPath, - srcPrefix: nodeModulePath - }, - files: { - // FileName : {"src":"dest"} - 'jquery.min.js': { 'jquery/dist': 'jquery/js' }, - 'require.js': { 'requirejs': 'requirejs' }, - 'text.js': { 'requirejs-text': 'requirejs-text' }, - 'underscore-min.js': { 'underscore': 'underscore' }, - 'bootstrap.min.js': { 'bootstrap/dist/js': 'bootstrap/js' }, - 'backbone-min.js': { 'backbone': 'backbone' }, - 'backbone.babysitter.min.js': { 'backbone.babysitter/lib': 'backbone-babysitter' }, - 'backbone.marionette.min.js': { 'backbone.marionette/lib': 'backbone-marionette' }, - 'backbone.paginator.min.js': { 'backbone.paginator/lib': 'backbone-paginator' }, - 'backbone.wreqr.min.js': { 'backbone.wreqr/lib': 'backbone-wreqr' }, - 'backgrid.js': { 'backgrid/lib': 'backgrid/js' }, - 'backgrid-filter.min.js': { 'backgrid-filter': 'backgrid-filter/js' }, - 'backgrid-orderable-columns.js': { 'backgrid-orderable-columns': 'backgrid-orderable-columns/js' }, - 'backgrid-paginator.min.js': { 'backgrid-paginator': 'backgrid-paginator/js' }, - 'backgrid-sizeable-columns.js': { 'backgrid-sizeable-columns': 'backgrid-sizeable-columns/js' }, - 'Backgrid.ColumnManager.js': { 'backgrid-columnmanager/src': 'backgrid-columnmanager/js' }, - 'jquery-asBreadcrumbs.min.js': { 'jquery-asBreadcrumbs/dist': 'jquery-asBreadcrumbs/js' }, - 'd3.min.js': { 'd3/dist': 'd3' }, - 'index.js': { 'd3-tip': 'd3/' }, - 'dagre-d3.min.js': { 'dagre-d3/dist': 'dagre-d3' }, - 'select2.full.min.js': { 'select2/dist/js': 'select2' }, - 'backgrid-select-all.min.js': { 'backgrid-select-all': 'backgrid-select-all' }, - 'moment.min.js': { 'moment/min': 'moment/js' }, - 'moment-timezone-with-data.min.js': { 'moment-timezone/builds': 'moment-timezone' }, - 'jquery.placeholder.js': { 'jquery-placeholder': 'jquery-placeholder/js' }, - 'platform.js': { 'platform': 'platform' }, - 'query-builder.standalone.min.js': { 'jQuery-QueryBuilder/dist/js': 'jQueryQueryBuilder/js' }, - 'daterangepicker.js': { 'bootstrap-daterangepicker': 'bootstrap-daterangepicker/js' }, - 'jquery.sparkline.min.js': { 'jquery-sparkline': 'sparkline' }, - 'table-dragger.js': { 'table-dragger/dist': 'table-dragger' }, - 'jstree.min.js': { 'jstree/dist': 'jstree' }, - 'jquery.steps.min.js': { 'jquery-steps/build': 'jquery-steps' }, - 'dropzone-amd-module.js': { 'dropzone/dist': "dropzone/js" }, - 'lossless-json.js': { 'lossless-json/dist': 'lossless-json' } - } - - }, - css: { - options: { - destPrefix: libPath, - srcPrefix: nodeModulePath - }, - files: { - 'bootstrap.min.css': { 'bootstrap/dist/css': 'bootstrap/css' }, - 'glyphicons-halflings-regular.woff2': { 'bootstrap/fonts': 'bootstrap/fonts' }, - 'backgrid.css': { 'backgrid/lib': 'backgrid/css' }, - 'backgrid-filter.min.css': { 'backgrid-filter': 'backgrid-filter/css' }, - 'backgrid-orderable-columns.css': { 'backgrid-orderable-columns': 'backgrid-orderable-columns/css' }, - 'backgrid-paginator.css': { 'backgrid-paginator': 'backgrid-paginator/css' }, - 'backgrid-sizeable-columns.css': { 'backgrid-sizeable-columns': 'backgrid-sizeable-columns/css' }, - 'Backgrid.ColumnManager.css': { 'backgrid-columnmanager/lib': 'backgrid-columnmanager/css' }, - 'asBreadcrumbs.min.css': { 'jquery-asBreadcrumbs/dist/css': 'jquery-asBreadcrumbs/css' }, - 'select2.min.css': { 'select2/dist/css': 'select2/css' }, - 'backgrid-select-all.min.css': { 'backgrid-select-all': 'backgrid-select-all' }, - 'font-awesome.min.css': { 'font-awesome/css': 'font-awesome/css' }, - '*': [{ - 'expand': true, - 'dot': true, - 'cwd': nodeModulePath + 'font-awesome', - 'src': ['fonts/*.*'], - 'dest': libPath + 'font-awesome/' - }, { - 'expand': true, - 'dot': true, - 'cwd': nodeModulePath + 'jstree/dist/themes/', - 'src': ['**'], - 'dest': libPath + 'jstree/css/' - }, { - 'expand': true, - 'dot': true, - 'cwd': nodeModulePath + 'jstree-bootstrap-theme/dist/themes/proton/', - 'src': ['**'], - 'dest': libPath + 'jstree/css/proton/' - }], - 'query-builder.default.min.css': { 'jQuery-QueryBuilder/dist/css': 'jQueryQueryBuilder/css' }, - 'daterangepicker.css': { 'bootstrap-daterangepicker': 'bootstrap-daterangepicker/css' }, - 'pretty-checkbox.min.css': { 'pretty-checkbox/dist': 'pretty-checkbox/css' }, - 'dropzone.css': { 'dropzone/dist': "dropzone/css" } - } - - }, - license: { - options: { - destPrefix: libPath, - srcPrefix: nodeModulePath - }, - files: { - 'LICENSE.txt': [ - { 'jquery': 'jquery' }, - { 'jquery-placeholder': 'jquery-placeholder' } - ], - 'LICENSE': [{ 'requirejs-text': 'requirejs-text' }, - { 'underscore': 'underscore' }, - { 'bootstrap': 'bootstrap' }, - { 'backgrid-columnmanager': 'backgrid-columnmanager' }, - { 'jquery-asBreadcrumbs': 'jquery-asBreadcrumbs' }, - { 'd3': 'd3' }, - { 'd3-tip': 'd3/' }, - { 'dagre-d3': 'dagre-d3' }, - { 'platform': 'platform/' }, - { 'jQuery-QueryBuilder': 'jQueryQueryBuilder/' }, - { 'moment-timezone': 'moment-timezone' }, - { 'pretty-checkbox': 'pretty-checkbox' } - ], - 'LICENSE.md': [{ 'backbone.babysitter': 'backbone-babysitter' }, - { 'backbone.wreqr': 'backbone-wreqr' }, - { 'lossless-json': 'lossless-json' } - ], - 'license.txt': [{ 'backbone.marionette': 'backbone-marionette' }], - 'license': [{ 'table-dragger': 'table-dragger' }], - 'LICENSE-MIT': [{ 'backbone.paginator': 'backbone-paginator' }, - { 'backgrid': 'backgrid' }, - { 'backgrid-filter': 'backgrid-filter' }, - { 'backgrid-orderable-columns': 'backgrid-orderable-columns' }, - { 'backgrid-paginator': 'backgrid-paginator' }, - { 'backgrid-sizeable-columns': 'backgrid-sizeable-columns' }, - { 'backgrid-select-all': 'backgrid-select-all' } - ] - } - } - }, - rename: { - main: { - files: [ - { src: [libPath + 'jstree/css/default/style.min.css'], dest: libPath + 'jstree/css/default/default-theme.min.css' }, - { src: [libPath + 'jstree/css/default-dark/style.min.css'], dest: libPath + 'jstree/css/default-dark/default-dark-theme.min.css' }, - ] - } - }, - sass: { - options: { - implementation: sass, - sourceMap: false - }, - build: { - files: { - [distPath + '/css/style.css']: modulesPath + 'css/scss/style.scss', - [distPath + '/css/login.css']: modulesPath + 'css/scss/login.scss' - } - } - }, - copy: { - build: { - expand: true, - cwd: modulesPath, - src: ['**', '!**/scss/**', "!**/atlas-lineage/**", "**/atlas-lineage/dist/**", "!index.html.tpl"], - dest: distPath - } - }, - clean: { - build: [distPath, libPath], - options: { - force: true - } - }, - uglify: { - buildlibs: { - options: { - mangle: true, - compress: true, - beautify: false - }, - files: [{ - expand: true, - cwd: distPath + '/js', - src: ['external_lib/**/*.js', 'libs/**/*.js'], - dest: distPath + '/js' - }] - }, - buildjs: { - options: { - mangle: false, - compress: true, - beautify: true - }, - files: [{ - expand: true, - cwd: distPath + '/js', - src: ['**/*.js', '!libs/**', '!external_lib/**'], - dest: distPath + '/js' - }] - } - }, - cssmin: { - build: { - files: [{ - expand: true, - cwd: distPath + '/css', - src: '*.css', - dest: distPath + '/css' - }] - } - }, - htmlmin: { - build: { - options: { - removeComments: true, - collapseWhitespace: true - }, - files: [{ - expand: true, - cwd: distPath + '/js/templates', - src: '**/*.html', - dest: distPath + '/js/templates' - }] - } - }, - template: { - build: { - options: { - data: { - 'bust': buildTime - } - }, - files: { - [distPath + '/index.html']: [modulesPath + 'index.html.tpl'] - } - } - } - }); - - // Dynamically add copy-task using npmcopy - var npmCopy = grunt.config.get('npmcopy'), - libFiles = [], - createPath = function(options) { - var obj = options.obj, - fileName = options.fileName, - pathPrefix = options.pathPrefix; - if (obj.length) { - for (var i in obj) { - createPath({ - 'obj': obj[i], - 'libFiles': options.libFiles, - 'pathPrefix': pathPrefix, - 'fileName': fileName - }); - } - } else { - if (fileName == "*") { - options.libFiles.push(obj); - } else { - key = Object.keys(obj); - options.libFiles.push({ 'src': pathPrefix.srcPrefix + key + "/" + fileName, 'dest': pathPrefix.destPrefix + obj[key] + "/" + fileName }); - } - } - }; - - for (var key in npmCopy) { - var options = npmCopy[key].options, - files = npmCopy[key].files; - for (var fileName in files) { - createPath({ - 'obj': files[fileName], - 'libFiles': libFiles, - 'pathPrefix': options, - 'fileName': fileName - }); - } - }; - grunt.config.set('copy.libs', { files: libFiles }); - - grunt.loadNpmTasks('grunt-contrib-connect'); - grunt.loadNpmTasks('grunt-middleware-proxy'); - grunt.loadNpmTasks('grunt-contrib-watch'); - grunt.loadNpmTasks('grunt-contrib-uglify'); - grunt.loadNpmTasks('grunt-contrib-cssmin'); - grunt.loadNpmTasks('grunt-contrib-htmlmin'); - grunt.loadNpmTasks('grunt-template'); - grunt.loadNpmTasks('grunt-contrib-rename'); - - require('load-grunt-tasks')(grunt); - - grunt.registerTask('dev', [ - 'clean', - 'copy:libs', - 'copy:build', - 'rename', - 'sass:build', - 'template', - 'setupProxies:server', - 'connect:server', - 'watch' - ]); - - grunt.registerTask('build', [ - 'clean', - 'copy:libs', - 'copy:build', - 'rename', - 'sass:build', - 'template' - ]); - - grunt.registerTask('dev-minify', [ - 'clean', - 'copy:libs', - 'copy:build', - 'rename', - 'sass:build', - 'uglify', - 'cssmin', - 'template', - 'setupProxies:server', - 'connect:server', - 'watch' - ]); - - grunt.registerTask('build-minify', [ - 'clean', - 'copy:libs', - 'copy:build', - 'rename', - 'sass:build', - 'uglify', - 'cssmin', - 'template' - ]); -}; \ No newline at end of file diff --git a/dashboardv3/package-lock.json b/dashboardv3/package-lock.json deleted file mode 100644 index 2b00b159e41..00000000000 --- a/dashboardv3/package-lock.json +++ /dev/null @@ -1,3890 +0,0 @@ -{ - "name": "atlas-metadata", - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "dev": true, - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - } - }, - "almond": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/almond/-/almond-0.3.3.tgz", - "integrity": "sha1-oOfJWsdiTWQXtElLHmi/9pMWiiA=" - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - }, - "dependencies": { - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - } - } - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "async-foreach": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atoa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/atoa/-/atoa-1.0.0.tgz", - "integrity": "sha1-DMDpGkgOc4+SPrwQNnZHF3mzSkk=" - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", - "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", - "dev": true - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "backbone": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.2.3.tgz", - "integrity": "sha1-wiz9B/yG676uYdGJKe0RXpmdZbk=", - "requires": { - "underscore": ">=1.7.0" - } - }, - "backbone.babysitter": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/backbone.babysitter/-/backbone.babysitter-0.1.12.tgz", - "integrity": "sha1-fKlGQ07u+94aVTYFx0twSbbfr8E=", - "requires": { - "backbone": ">=0.9.9 <=1.3.x", - "underscore": ">=1.4.0 <=1.8.3" - } - }, - "backbone.marionette": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/backbone.marionette/-/backbone.marionette-2.3.2.tgz", - "integrity": "sha1-9OPGd8n6bIS8bRyJOSIVbV7+ojo=", - "requires": { - "backbone": "1.0.0 - 1.1.2", - "backbone.babysitter": "^0.1.0", - "backbone.wreqr": "^1.0.0", - "underscore": "1.4.4 - 1.6.0" - }, - "dependencies": { - "backbone": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/backbone/-/backbone-1.1.2.tgz", - "integrity": "sha1-wsBMZr+HJo+4LBd6zr7/fTe6by0=", - "requires": { - "underscore": ">=1.5.0" - } - }, - "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" - } - } - }, - "backbone.paginator": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/backbone.paginator/-/backbone.paginator-2.0.5.tgz", - "integrity": "sha1-T9+oJjIDx+7ieqtpYBnTKc1/AG0=", - "requires": { - "backbone": "1.1.2 || 1.2.3 || ^1.3.2", - "underscore": "^1.8.0" - } - }, - "backbone.wreqr": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/backbone.wreqr/-/backbone.wreqr-1.4.0.tgz", - "integrity": "sha1-doIDDJqvCQ7Nhzsh2/SFAWk7JpY=", - "requires": { - "backbone": ">=0.9.9 <=1.3.x", - "underscore": ">=1.3.3 <=1.8.3" - } - }, - "backgrid": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/backgrid/-/backgrid-0.3.8.tgz", - "integrity": "sha1-fSaBZ0LXLIWcrTmxPxnJ8nuv/tc=", - "requires": { - "backbone": "1.1.2 || 1.2.3 || ~1.3.2", - "underscore": "^1.8.0" - } - }, - "backgrid-filter": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/backgrid-filter/-/backgrid-filter-0.3.7.tgz", - "integrity": "sha1-1LGdDnBwE9fxgfnox/67SZfVbwM=", - "requires": { - "backbone": "~1.2.3", - "backgrid": "~0.3.7", - "lunr": "^0.7.0", - "underscore": "^1.8.3" - } - }, - "backgrid-orderable-columns": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/backgrid-orderable-columns/-/backgrid-orderable-columns-0.1.2.tgz", - "integrity": "sha1-hjXt9taG6QsLERLUbt9kEZjG8EI=" - }, - "backgrid-paginator": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/backgrid-paginator/-/backgrid-paginator-0.3.9.tgz", - "integrity": "sha1-2vZhFGwTdmWgqN6ifNrR8jgmk3g=", - "requires": { - "backbone": "1.1.2 || 1.2.3 || ~1.3.2", - "backbone.paginator": "^2.0.5", - "backgrid": "~0.3.7", - "underscore": "^1.8.0" - } - }, - "backgrid-select-all": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/backgrid-select-all/-/backgrid-select-all-0.3.5.tgz", - "integrity": "sha1-FDqADl2V/yrlqE14v0+6QflIHpQ=" - }, - "backgrid-sizeable-columns": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/backgrid-sizeable-columns/-/backgrid-sizeable-columns-0.1.1.tgz", - "integrity": "sha1-7G+lkrJjs5DfHYPlZqSNylA28Cs=" - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "basic-auth": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", - "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "batch": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", - "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "dev": true, - "requires": { - "inherits": "~2.0.0" - } - }, - "body": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", - "integrity": "sha1-5LoM5BCkaTYyM2dgnstOZVMSUGk=", - "dev": true, - "requires": { - "continuable-cache": "^0.3.1", - "error": "^7.0.0", - "raw-body": "~1.1.0", - "safe-json-parse": "~1.0.1" - } - }, - "bootstrap": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.4.1.tgz", - "integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA==" - }, - "bootstrap-daterangepicker": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bootstrap-daterangepicker/-/bootstrap-daterangepicker-3.1.0.tgz", - "integrity": "sha512-oaQZx6ZBDo/dZNyXGVi2rx5GmFXThyQLAxdtIqjtLlYVaQUfQALl5JZMJJZzyDIX7blfy4ppZPAJ10g8Ma4d/g==", - "requires": { - "jquery": ">=1.10", - "moment": "^2.9.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "browserify-zlib": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", - "integrity": "sha1-uzX4pRn2AOD6a4SFJByXnQFB+y0=", - "dev": true, - "requires": { - "pako": "~0.2.0" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", - "integrity": "sha1-NWnt6Lo0MV+rmcPpLLBMciDeH6g=", - "dev": true - }, - "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", - "dev": true, - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "clean-css": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.0.13.tgz", - "integrity": "sha1-/rKhdgYtcqbD5iTZITysagxIXoA=", - "dev": true, - "requires": { - "source-map": "0.5.x" - } - }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "dev": true, - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "coffeescript": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.10.0.tgz", - "integrity": "sha1-56qDAZF+9iGzXYo580jc3R234z4=", - "dev": true - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "colors": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", - "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "connect": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", - "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", - "dev": true, - "requires": { - "debug": "2.6.9", - "finalhandler": "1.1.2", - "parseurl": "~1.3.3", - "utils-merge": "1.0.1" - } - }, - "connect-livereload": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.5.4.tgz", - "integrity": "sha1-gBV9E3HJ83zBQDmrGJWXDRGdw7w=", - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "continuable-cache": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", - "integrity": "sha1-vXJ6f67XfnH/OYWskzUakSczrQ8=", - "dev": true - }, - "contra": { - "version": "1.9.4", - "resolved": "https://registry.npmjs.org/contra/-/contra-1.9.4.tgz", - "integrity": "sha1-9TveQtfltZhcrk2ZqNYQUm3o8o0=", - "requires": { - "atoa": "1.0.0", - "ticky": "1.0.1" - } - }, - "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cross-spawn": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", - "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, - "crossvent": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/crossvent/-/crossvent-1.5.5.tgz", - "integrity": "sha1-rSCHjkkh6b5z2daXb4suzQ9xoLE=", - "requires": { - "custom-event": "^1.0.0" - } - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, - "custom-event": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", - "integrity": "sha1-XQKkaFCt8bSjF5RqOSj8y1v9BCU=" - }, - "d3": { - "version": "5.14.2", - "resolved": "https://registry.npmjs.org/d3/-/d3-5.14.2.tgz", - "integrity": "sha512-Ccipa9XrYW5N0QkP6u0Qb8kU6WekIXBiDenmZm1zLvuq/9pBBhRCJLCICEOsH5Og4B0Xw02bhqGkK5VN/oPH0w==", - "requires": { - "d3-array": "1", - "d3-axis": "1", - "d3-brush": "1", - "d3-chord": "1", - "d3-collection": "1", - "d3-color": "1", - "d3-contour": "1", - "d3-dispatch": "1", - "d3-drag": "1", - "d3-dsv": "1", - "d3-ease": "1", - "d3-fetch": "1", - "d3-force": "1", - "d3-format": "1", - "d3-geo": "1", - "d3-hierarchy": "1", - "d3-interpolate": "1", - "d3-path": "1", - "d3-polygon": "1", - "d3-quadtree": "1", - "d3-random": "1", - "d3-scale": "2", - "d3-scale-chromatic": "1", - "d3-selection": "1", - "d3-shape": "1", - "d3-time": "1", - "d3-time-format": "2", - "d3-timer": "1", - "d3-transition": "1", - "d3-voronoi": "1", - "d3-zoom": "1" - } - }, - "d3-array": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", - "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" - }, - "d3-axis": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz", - "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==" - }, - "d3-brush": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz", - "integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "d3-chord": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", - "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", - "requires": { - "d3-array": "1", - "d3-path": "1" - } - }, - "d3-collection": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", - "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==" - }, - "d3-color": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", - "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==" - }, - "d3-contour": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", - "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", - "requires": { - "d3-array": "^1.1.1" - } - }, - "d3-dispatch": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", - "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==" - }, - "d3-drag": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", - "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", - "requires": { - "d3-dispatch": "1", - "d3-selection": "1" - } - }, - "d3-dsv": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", - "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", - "requires": { - "commander": "2", - "iconv-lite": "0.4", - "rw": "1" - } - }, - "d3-ease": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", - "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==" - }, - "d3-fetch": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz", - "integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==", - "requires": { - "d3-dsv": "1" - } - }, - "d3-force": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz", - "integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==", - "requires": { - "d3-collection": "1", - "d3-dispatch": "1", - "d3-quadtree": "1", - "d3-timer": "1" - } - }, - "d3-format": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", - "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==" - }, - "d3-geo": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz", - "integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==", - "requires": { - "d3-array": "1" - } - }, - "d3-hierarchy": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", - "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==" - }, - "d3-interpolate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", - "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", - "requires": { - "d3-color": "1" - } - }, - "d3-path": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" - }, - "d3-polygon": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", - "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==" - }, - "d3-quadtree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", - "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==" - }, - "d3-queue": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/d3-queue/-/d3-queue-3.0.7.tgz", - "integrity": "sha1-yTouVLQXwJWRKdfXP2z31Ckudhg=" - }, - "d3-random": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz", - "integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==" - }, - "d3-request": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-request/-/d3-request-1.0.6.tgz", - "integrity": "sha512-FJj8ySY6GYuAJHZMaCQ83xEYE4KbkPkmxZ3Hu6zA1xxG2GD+z6P+Lyp+zjdsHf0xEbp2xcluDI50rCS855EQ6w==", - "requires": { - "d3-collection": "1", - "d3-dispatch": "1", - "d3-dsv": "1", - "xmlhttprequest": "1" - } - }, - "d3-scale": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", - "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", - "requires": { - "d3-array": "^1.2.0", - "d3-collection": "1", - "d3-format": "1", - "d3-interpolate": "1", - "d3-time": "1", - "d3-time-format": "2" - } - }, - "d3-scale-chromatic": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz", - "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==", - "requires": { - "d3-color": "1", - "d3-interpolate": "1" - } - }, - "d3-selection": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", - "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==" - }, - "d3-shape": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", - "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", - "requires": { - "d3-path": "1" - } - }, - "d3-time": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", - "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==" - }, - "d3-time-format": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", - "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", - "requires": { - "d3-time": "1" - } - }, - "d3-timer": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", - "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==" - }, - "d3-tip": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/d3-tip/-/d3-tip-0.7.1.tgz", - "integrity": "sha1-eMv1VPZ7cgpw47DxkeFM/+aM3Xk=", - "requires": { - "d3": "^4.2" - }, - "dependencies": { - "d3": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-4.13.0.tgz", - "integrity": "sha512-l8c4+0SldjVKLaE2WG++EQlqD7mh/dmQjvi2L2lKPadAVC+TbJC4ci7Uk9bRi+To0+ansgsS0iWfPjD7DBy+FQ==", - "requires": { - "d3-array": "1.2.1", - "d3-axis": "1.0.8", - "d3-brush": "1.0.4", - "d3-chord": "1.0.4", - "d3-collection": "1.0.4", - "d3-color": "1.0.3", - "d3-dispatch": "1.0.3", - "d3-drag": "1.2.1", - "d3-dsv": "1.0.8", - "d3-ease": "1.0.3", - "d3-force": "1.1.0", - "d3-format": "1.2.2", - "d3-geo": "1.9.1", - "d3-hierarchy": "1.1.5", - "d3-interpolate": "1.1.6", - "d3-path": "1.0.5", - "d3-polygon": "1.0.3", - "d3-quadtree": "1.0.3", - "d3-queue": "3.0.7", - "d3-random": "1.1.0", - "d3-request": "1.0.6", - "d3-scale": "1.0.7", - "d3-selection": "1.3.0", - "d3-shape": "1.2.0", - "d3-time": "1.0.8", - "d3-time-format": "2.1.1", - "d3-timer": "1.0.7", - "d3-transition": "1.1.1", - "d3-voronoi": "1.1.2", - "d3-zoom": "1.7.1" - } - }, - "d3-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.1.tgz", - "integrity": "sha512-CyINJQ0SOUHojDdFDH4JEM0552vCR1utGyLHegJHyYH0JyCpSeTPxi4OBqHMA2jJZq4NH782LtaJWBImqI/HBw==" - }, - "d3-axis": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.8.tgz", - "integrity": "sha1-MacFoLU15ldZ3hQXOjGTMTfxjvo=" - }, - "d3-brush": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.0.4.tgz", - "integrity": "sha1-AMLyOAGfJPbAoZSibUGhUw/+e8Q=", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "d3-chord": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.4.tgz", - "integrity": "sha1-fexPC6iG9xP+ERxF92NBT290yiw=", - "requires": { - "d3-array": "1", - "d3-path": "1" - } - }, - "d3-collection": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.4.tgz", - "integrity": "sha1-NC39EoN8kJdPM/HMCnha6lcNzcI=" - }, - "d3-color": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.0.3.tgz", - "integrity": "sha1-vHZD/KjlOoNH4vva/6I2eWtYUJs=" - }, - "d3-dispatch": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.3.tgz", - "integrity": "sha1-RuFJHqqbWMNY/OW+TovtYm54cfg=" - }, - "d3-drag": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.1.tgz", - "integrity": "sha512-Cg8/K2rTtzxzrb0fmnYOUeZHvwa4PHzwXOLZZPwtEs2SKLLKLXeYwZKBB+DlOxUvFmarOnmt//cU4+3US2lyyQ==", - "requires": { - "d3-dispatch": "1", - "d3-selection": "1" - } - }, - "d3-dsv": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.0.8.tgz", - "integrity": "sha512-IVCJpQ+YGe3qu6odkPQI0KPqfxkhbP/oM1XhhE/DFiYmcXKfCRub4KXyiuehV1d4drjWVXHUWx4gHqhdZb6n/A==", - "requires": { - "commander": "2", - "iconv-lite": "0.4", - "rw": "1" - } - }, - "d3-ease": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.3.tgz", - "integrity": "sha1-aL+8NJM4o4DETYrMT7wzBKotjA4=" - }, - "d3-force": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.1.0.tgz", - "integrity": "sha512-2HVQz3/VCQs0QeRNZTYb7GxoUCeb6bOzMp/cGcLa87awY9ZsPvXOGeZm0iaGBjXic6I1ysKwMn+g+5jSAdzwcg==", - "requires": { - "d3-collection": "1", - "d3-dispatch": "1", - "d3-quadtree": "1", - "d3-timer": "1" - } - }, - "d3-format": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.2.2.tgz", - "integrity": "sha512-zH9CfF/3C8zUI47nsiKfD0+AGDEuM8LwBIP7pBVpyR4l/sKkZqITmMtxRp04rwBrlshIZ17XeFAaovN3++wzkw==" - }, - "d3-geo": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.9.1.tgz", - "integrity": "sha512-l9wL/cEQkyZQYXw3xbmLsH3eQ5ij+icNfo4r0GrLa5rOCZR/e/3am45IQ0FvQ5uMsv+77zBRunLc9ufTWSQYFA==", - "requires": { - "d3-array": "1" - } - }, - "d3-hierarchy": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.5.tgz", - "integrity": "sha1-ochFxC+Eoga88cAcAQmOpN2qeiY=" - }, - "d3-interpolate": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.1.6.tgz", - "integrity": "sha512-mOnv5a+pZzkNIHtw/V6I+w9Lqm9L5bG3OTXPM5A+QO0yyVMQ4W1uZhR+VOJmazaOZXri2ppbiZ5BUNWT0pFM9A==", - "requires": { - "d3-color": "1" - } - }, - "d3-path": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.5.tgz", - "integrity": "sha1-JB6xhJvZ6egCHA0KeZ+KDo5EF2Q=" - }, - "d3-polygon": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.3.tgz", - "integrity": "sha1-FoiOkCZGCTPysXllKtN4Ik04LGI=" - }, - "d3-quadtree": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.3.tgz", - "integrity": "sha1-rHmH4+I/6AWpkPKOG1DTj8uCJDg=" - }, - "d3-random": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.0.tgz", - "integrity": "sha1-ZkLlBsb6OmSFldKyRpeIqNElKdM=" - }, - "d3-scale": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-1.0.7.tgz", - "integrity": "sha512-KvU92czp2/qse5tUfGms6Kjig0AhHOwkzXG0+PqIJB3ke0WUv088AHMZI0OssO9NCkXt4RP8yju9rpH8aGB7Lw==", - "requires": { - "d3-array": "^1.2.0", - "d3-collection": "1", - "d3-color": "1", - "d3-format": "1", - "d3-interpolate": "1", - "d3-time": "1", - "d3-time-format": "2" - } - }, - "d3-selection": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.3.0.tgz", - "integrity": "sha512-qgpUOg9tl5CirdqESUAu0t9MU/t3O9klYfGfyKsXEmhyxyzLpzpeh08gaxBUTQw1uXIOkr/30Ut2YRjSSxlmHA==" - }, - "d3-shape": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.2.0.tgz", - "integrity": "sha1-RdAVOPBkuv0F6j1tLLdI/YxB93c=", - "requires": { - "d3-path": "1" - } - }, - "d3-time": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.0.8.tgz", - "integrity": "sha512-YRZkNhphZh3KcnBfitvF3c6E0JOFGikHZ4YqD+Lzv83ZHn1/u6yGenRU1m+KAk9J1GnZMnKcrtfvSktlA1DXNQ==" - }, - "d3-time-format": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.1.1.tgz", - "integrity": "sha512-8kAkymq2WMfzW7e+s/IUNAtN/y3gZXGRrdGfo6R8NKPAA85UBTxZg5E61bR6nLwjPjj4d3zywSQe1CkYLPFyrw==", - "requires": { - "d3-time": "1" - } - }, - "d3-timer": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.7.tgz", - "integrity": "sha512-vMZXR88XujmG/L5oB96NNKH5lCWwiLM/S2HyyAQLcjWJCloK5shxta4CwOFYLZoY3AWX73v8Lgv4cCAdWtRmOA==" - }, - "d3-transition": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.1.1.tgz", - "integrity": "sha512-xeg8oggyQ+y5eb4J13iDgKIjUcEfIOZs2BqV/eEmXm2twx80wTzJ4tB4vaZ5BKfz7XsI/DFmQL5me6O27/5ykQ==", - "requires": { - "d3-color": "1", - "d3-dispatch": "1", - "d3-ease": "1", - "d3-interpolate": "1", - "d3-selection": "^1.1.0", - "d3-timer": "1" - } - }, - "d3-voronoi": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.2.tgz", - "integrity": "sha1-Fodmfo8TotFYyAwUgMWinLDYlzw=" - }, - "d3-zoom": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.7.1.tgz", - "integrity": "sha512-sZHQ55DGq5BZBFGnRshUT8tm2sfhPHFnOlmPbbwTkAoPeVdRTkB4Xsf9GCY0TSHrTD8PeJPZGmP/TpGicwJDJQ==", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - } - } - }, - "d3-transition": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", - "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", - "requires": { - "d3-color": "1", - "d3-dispatch": "1", - "d3-ease": "1", - "d3-interpolate": "1", - "d3-selection": "^1.1.0", - "d3-timer": "1" - } - }, - "d3-voronoi": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", - "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==" - }, - "d3-zoom": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz", - "integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "dagre": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", - "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", - "requires": { - "graphlib": "^2.1.8", - "lodash": "^4.17.15" - } - }, - "dagre-d3": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz", - "integrity": "sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==", - "requires": { - "d3": "^5.14", - "dagre": "^0.8.5", - "graphlib": "^2.1.8", - "lodash": "^4.17.15" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "dot": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dot/-/dot-1.1.3.tgz", - "integrity": "sha512-/nt74Rm+PcfnirXGEdhZleTwGC2LMnuKTeeTIlI82xb5loBBoXNYzr2ezCroPSMtilK8EZIfcNZwOcHN+ib1Lg==" - }, - "dragula-with-animation": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/dragula-with-animation/-/dragula-with-animation-3.7.4.tgz", - "integrity": "sha512-Kdvld/s4ASLRgP5w8lzK64P+8XUX9ccNGn0rmXDCG9AuvyzUxvVo+HxLQoRMyRPCQWAZ3xzA7b3ghcFIz+QsIA==", - "requires": { - "contra": "1.9.4", - "crossvent": "1.5.4" - }, - "dependencies": { - "crossvent": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/crossvent/-/crossvent-1.5.4.tgz", - "integrity": "sha1-2ixPj0DJR4JRe/K+7BBEFIGUq5I=", - "requires": { - "custom-event": "1.0.0" - } - }, - "custom-event": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.0.tgz", - "integrity": "sha1-LkYovhncSyFLXAJjDFlx6BFhgGI=" - } - } - }, - "dropzone": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/dropzone/-/dropzone-5.7.0.tgz", - "integrity": "sha512-kOltiZXH5cO/72I22JjE+w6BoT6uaVLfWdFMsi1PMKFkU6BZWpqRwjnsRm0o6ANGTBuZar5Piu7m/CbKqRPiYg==" - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "error": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", - "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", - "dev": true, - "requires": { - "string-template": "~0.2.1" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "eventemitter2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", - "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", - "dev": true - }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - } - }, - "file-sync-cmp": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz", - "integrity": "sha1-peeo/7+kk7Q7kju9TKiaU7Y7YSs=", - "dev": true - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "findup-sync": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", - "integrity": "sha1-N5MKpdgWt3fANEXhlmzGeQpMCxY=", - "dev": true, - "requires": { - "glob": "~5.0.0" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "font-awesome": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", - "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=" - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true, - "requires": { - "globule": "^1.0.0" - } - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, - "getobject": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", - "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", - "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "globule": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz", - "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==", - "dev": true, - "requires": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "graphlib": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", - "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", - "requires": { - "lodash": "^4.17.15" - } - }, - "grunt": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.0.4.tgz", - "integrity": "sha512-PYsMOrOC+MsdGEkFVwMaMyc6Ob7pKmq+deg1Sjr+vvMWp35sztfwKE7qoN51V+UEtHsyNuMcGdgMLFkBHvMxHQ==", - "dev": true, - "requires": { - "coffeescript": "~1.10.0", - "dateformat": "~1.0.12", - "eventemitter2": "~0.4.13", - "exit": "~0.1.1", - "findup-sync": "~0.3.0", - "glob": "~7.0.0", - "grunt-cli": "~1.2.0", - "grunt-known-options": "~1.1.0", - "grunt-legacy-log": "~2.0.0", - "grunt-legacy-util": "~1.1.1", - "iconv-lite": "~0.4.13", - "js-yaml": "~3.13.0", - "minimatch": "~3.0.2", - "mkdirp": "~0.5.1", - "nopt": "~3.0.6", - "path-is-absolute": "~1.0.0", - "rimraf": "~2.6.2" - } - }, - "grunt-cli": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.2.0.tgz", - "integrity": "sha1-VisRnrsGndtGSs4oRVAb6Xs1tqg=", - "dev": true, - "requires": { - "findup-sync": "~0.3.0", - "grunt-known-options": "~1.1.0", - "nopt": "~3.0.6", - "resolve": "~1.1.0" - }, - "dependencies": { - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true - } - } - }, - "grunt-contrib-clean": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-1.1.0.tgz", - "integrity": "sha1-Vkq/LQN4qYOhW54/MO51tzjEBjg=", - "dev": true, - "requires": { - "async": "^1.5.2", - "rimraf": "^2.5.1" - } - }, - "grunt-contrib-connect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/grunt-contrib-connect/-/grunt-contrib-connect-1.0.2.tgz", - "integrity": "sha1-XPkzuRpnOGBEJzwLJERgPNmIebo=", - "dev": true, - "requires": { - "async": "^1.5.2", - "connect": "^3.4.0", - "connect-livereload": "^0.5.0", - "http2": "^3.3.4", - "morgan": "^1.6.1", - "opn": "^4.0.0", - "portscanner": "^1.0.0", - "serve-index": "^1.7.1", - "serve-static": "^1.10.0" - } - }, - "grunt-contrib-copy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz", - "integrity": "sha1-cGDGWB6QS4qw0A8HbgqPbj58NXM=", - "dev": true, - "requires": { - "chalk": "^1.1.1", - "file-sync-cmp": "^0.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "grunt-contrib-cssmin": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-cssmin/-/grunt-contrib-cssmin-2.0.0.tgz", - "integrity": "sha1-O8joyIZcgZFZzCd5+C/PgzRzNFs=", - "dev": true, - "requires": { - "chalk": "^1.0.0", - "clean-css": "~4.0.3", - "maxmin": "^1.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "grunt-contrib-htmlmin": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-htmlmin/-/grunt-contrib-htmlmin-2.2.0.tgz", - "integrity": "sha1-FB8M+4cBKO2c5uqGGrEwVlyQzZc=", - "dev": true, - "requires": { - "chalk": "^1.0.0", - "html-minifier": "~3.3.0", - "pretty-bytes": "^4.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "pretty-bytes": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", - "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "grunt-contrib-rename": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-rename/-/grunt-contrib-rename-0.2.0.tgz", - "integrity": "sha1-1CPU+SqZpYcncEX4MikdmM4V/co=", - "dev": true - }, - "grunt-contrib-uglify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-uglify/-/grunt-contrib-uglify-2.1.0.tgz", - "integrity": "sha1-s/8CjaR0g3h/GfCyMrehtRIS/YU=", - "dev": true, - "requires": { - "chalk": "^1.0.0", - "maxmin": "^1.1.0", - "object.assign": "^4.0.4", - "uglify-js": "~2.7.0", - "uri-path": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "grunt-contrib-watch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz", - "integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==", - "dev": true, - "requires": { - "async": "^2.6.0", - "gaze": "^1.1.0", - "lodash": "^4.17.10", - "tiny-lr": "^1.1.1" - }, - "dependencies": { - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dev": true, - "requires": { - "lodash": "^4.17.14" - } - } - } - }, - "grunt-known-options": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-1.1.1.tgz", - "integrity": "sha512-cHwsLqoighpu7TuYj5RonnEuxGVFnztcUqTqp5rXFGYL4OuPFofwC4Ycg7n9fYwvK6F5WbYgeVOwph9Crs2fsQ==", - "dev": true - }, - "grunt-legacy-log": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-2.0.0.tgz", - "integrity": "sha512-1m3+5QvDYfR1ltr8hjiaiNjddxGdQWcH0rw1iKKiQnF0+xtgTazirSTGu68RchPyh1OBng1bBUjLmX8q9NpoCw==", - "dev": true, - "requires": { - "colors": "~1.1.2", - "grunt-legacy-log-utils": "~2.0.0", - "hooker": "~0.2.3", - "lodash": "~4.17.5" - } - }, - "grunt-legacy-log-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.0.1.tgz", - "integrity": "sha512-o7uHyO/J+i2tXG8r2bZNlVk20vlIFJ9IEYyHMCQGfWYru8Jv3wTqKZzvV30YW9rWEjq0eP3cflQ1qWojIe9VFA==", - "dev": true, - "requires": { - "chalk": "~2.4.1", - "lodash": "~4.17.10" - } - }, - "grunt-legacy-util": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-1.1.1.tgz", - "integrity": "sha512-9zyA29w/fBe6BIfjGENndwoe1Uy31BIXxTH3s8mga0Z5Bz2Sp4UCjkeyv2tI449ymkx3x26B+46FV4fXEddl5A==", - "dev": true, - "requires": { - "async": "~1.5.2", - "exit": "~0.1.1", - "getobject": "~0.1.0", - "hooker": "~0.2.3", - "lodash": "~4.17.10", - "underscore.string": "~3.3.4", - "which": "~1.3.0" - } - }, - "grunt-middleware-proxy": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/grunt-middleware-proxy/-/grunt-middleware-proxy-1.0.7.tgz", - "integrity": "sha1-YUPO05nBrzOlRmgvPUBcp2m6fRg=", - "dev": true - }, - "grunt-sass": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/grunt-sass/-/grunt-sass-3.1.0.tgz", - "integrity": "sha512-90s27H7FoCDcA8C8+R0GwC+ntYD3lG6S/jqcavWm3bn9RiJTmSfOvfbFa1PXx4NbBWuiGQMLfQTj/JvvqT5w6A==", - "dev": true - }, - "grunt-template": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/grunt-template/-/grunt-template-1.0.0.tgz", - "integrity": "sha1-Vgj5sFoGp4b6BIymZEfktI09HCE=", - "dev": true - }, - "gzip-size": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-1.0.0.tgz", - "integrity": "sha1-Zs+LEBBHInuVus5uodoMF37Vwi8=", - "dev": true, - "requires": { - "browserify-zlib": "^0.1.4", - "concat-stream": "^1.4.1" - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "dev": true, - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "hooker": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", - "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", - "dev": true - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, - "html-minifier": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.3.3.tgz", - "integrity": "sha1-XoVRayr/PD+5vaNRh5N1hoOG1vY=", - "dev": true, - "requires": { - "camel-case": "3.0.x", - "clean-css": "4.0.x", - "commander": "2.9.x", - "he": "1.1.x", - "ncname": "1.0.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "2.7.x" - }, - "dependencies": { - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } - } - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - }, - "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } - } - }, - "http-parser-js": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.2.tgz", - "integrity": "sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ==", - "dev": true - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "http2": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/http2/-/http2-3.3.7.tgz", - "integrity": "sha512-puSi8M8WNlFJm9Pk4c/Mbz9Gwparuj3gO9/RRO5zv6piQ0FY+9Qywp0PdWshYgsMJSalixFY7eC6oPu0zRxLAQ==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "in-publish": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.1.tgz", - "integrity": "sha512-oDM0kUSNFC31ShNxHKUyfZKy8ZeXZBWMjMdZHKLOk13uvT27VTL/QzRGfRUcevJhpkZAvlhPYuXkF7eNWrtyxQ==", - "dev": true - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "jQuery-QueryBuilder": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/jQuery-QueryBuilder/-/jQuery-QueryBuilder-2.4.3.tgz", - "integrity": "sha1-F3vGKm+YXa0Ozu30kqo/yk5qKuU=", - "requires": { - "bootstrap": ">=3.1.0", - "dot": ">=1.0.3", - "jquery": ">=1.9.0", - "jquery-extendext": ">=0.1.2", - "moment": ">=2.6.0" - } - }, - "jquery": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz", - "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==" - }, - "jquery-asBreadcrumbs": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/jquery-asBreadcrumbs/-/jquery-asBreadcrumbs-0.2.2.tgz", - "integrity": "sha1-eAOj55hzLBI3zni7hmqi11/iJPg=", - "requires": { - "jquery": ">=2.2.0" - } - }, - "jquery-extendext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/jquery-extendext/-/jquery-extendext-1.0.0.tgz", - "integrity": "sha512-gDJjpQ8ISd4ZMwSn0yXSuyufsPMCeWtWJ8kmqE85VromJqyVT2sdkHzS5yL0w1GK81UpOzmr2f9JgFln2sbJSg==", - "requires": { - "jquery": ">=1.9.1" - } - }, - "jquery-mousewheel": { - "version": "3.1.13", - "resolved": "https://registry.npmjs.org/jquery-mousewheel/-/jquery-mousewheel-3.1.13.tgz", - "integrity": "sha1-BvAzXxbjU6aV5yBr9QUDy1I6buU=" - }, - "jquery-placeholder": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/jquery-placeholder/-/jquery-placeholder-2.3.1.tgz", - "integrity": "sha1-YCWhJBAZwIqPs6uO0HYoXAW6XpE=" - }, - "jquery-sparkline": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jquery-sparkline/-/jquery-sparkline-2.4.0.tgz", - "integrity": "sha1-G+i3twTdOFcVJwiu+x1KSzpp+zM=" - }, - "jquery-steps": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/jquery-steps/-/jquery-steps-1.1.0.tgz", - "integrity": "sha1-DO7gsNLkkUOYGtEg1FjtVuqOGSQ=" - }, - "js-base64": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", - "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "jstree": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jstree/-/jstree-3.3.5.tgz", - "integrity": "sha1-nFeNsy0KZDd1zd2AIK1ZkvQRnBM=", - "requires": { - "jquery": ">=1.9.1" - } - }, - "jstree-bootstrap-theme": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/jstree-bootstrap-theme/-/jstree-bootstrap-theme-1.0.1.tgz", - "integrity": "sha1-fV7cc6hG6Np/lPV6HMXd7p2eq0s=", - "requires": { - "jquery": ">=1.9.1" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "livereload-js": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", - "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==", - "dev": true - }, - "load-grunt-tasks": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/load-grunt-tasks/-/load-grunt-tasks-3.5.2.tgz", - "integrity": "sha1-ByhWEYD9IP+KaSdQWFL8WKrqDIg=", - "dev": true, - "requires": { - "arrify": "^1.0.0", - "multimatch": "^2.0.0", - "pkg-up": "^1.0.0", - "resolve-pkg": "^0.1.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "lossless-json": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lossless-json/-/lossless-json-1.0.4.tgz", - "integrity": "sha512-zEkWwELMSQQISdtOF44vk0bRJhN/PJ93qcgJLcodizQjxrJKdFrq2H1+Xv5QDe7v3dTYYbBI5hOsh4a9l0B2Ow==" - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "lunr": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-0.7.2.tgz", - "integrity": "sha1-eaMOky4hbLoWNUHuN6NgfBLNcoE=" - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "maxmin": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/maxmin/-/maxmin-1.1.0.tgz", - "integrity": "sha1-cTZehKmd2Piz99X94vANHn9zvmE=", - "dev": true, - "requires": { - "chalk": "^1.0.0", - "figures": "^1.0.1", - "gzip-size": "^1.0.0", - "pretty-bytes": "^1.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "dev": true - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dev": true, - "requires": { - "mime-db": "1.44.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "moment": { - "version": "2.21.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.21.0.tgz", - "integrity": "sha512-TCZ36BjURTeFTM/CwRcViQlfkMvL1/vFISuNLO5GkcVm1+QHfbSiNqZuWeMFjj1/3+uAjXswgRk30j1kkLYJBQ==" - }, - "moment-timezone": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.14.tgz", - "integrity": "sha1-TrOP+VOLgBCLpGekWPPtQmjM/LE=", - "requires": { - "moment": ">= 2.9.0" - } - }, - "morgan": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", - "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", - "dev": true, - "requires": { - "basic-auth": "~2.0.1", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-finished": "~2.3.0", - "on-headers": "~1.0.2" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "multimatch": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", - "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", - "dev": true, - "requires": { - "array-differ": "^1.0.0", - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "minimatch": "^3.0.0" - } - }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "dev": true - }, - "ncname": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ncname/-/ncname-1.0.0.tgz", - "integrity": "sha1-W1etGLHKCShk72Kwse2BlPODtxw=", - "dev": true, - "requires": { - "xml-char-classes": "^1.0.0" - } - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true - }, - "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "dev": true, - "requires": { - "lower-case": "^1.1.1" - } - }, - "node-gyp": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", - "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", - "dev": true, - "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "dependencies": { - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - } - } - }, - "node-sass": { - "version": "4.13.1", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.13.1.tgz", - "integrity": "sha512-TTWFx+ZhyDx1Biiez2nB0L3YrCZ/8oHagaDalbuBSlqXgUPsdkUSzJsVxeDO9LtPB49+Fh3WQl3slABo6AotNw==", - "dev": true, - "requires": { - "async-foreach": "^0.1.3", - "chalk": "^1.1.1", - "cross-spawn": "^3.0.0", - "gaze": "^1.0.0", - "get-stdin": "^4.0.1", - "glob": "^7.0.3", - "in-publish": "^2.0.0", - "lodash": "^4.17.15", - "meow": "^3.7.0", - "mkdirp": "^0.5.1", - "nan": "^2.13.2", - "node-gyp": "^3.8.0", - "npmlog": "^4.0.0", - "request": "^2.88.0", - "sass-graph": "^2.2.4", - "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "opn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/opn/-/opn-4.0.2.tgz", - "integrity": "sha1-erwi5kTf9jsKltWrfyeQwPAavJU=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "pinkie-promise": "^2.0.0" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU=", - "dev": true - }, - "param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", - "dev": true, - "requires": { - "no-case": "^2.2.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-up": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz", - "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - } - }, - "platform": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.4.tgz", - "integrity": "sha1-bw+xftqqSPIUQrOpdcBjEw8cPr0=" - }, - "pnotify": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/pnotify/-/pnotify-3.2.0.tgz", - "integrity": "sha1-IvQabCjY1CcKgR2o4JuoKOjgI3c=", - "requires": { - "jquery": ">=1.6.0" - } - }, - "portscanner": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-1.2.0.tgz", - "integrity": "sha1-sUu9olfRTDEPqcwJaCrwLUCWGAI=", - "dev": true, - "requires": { - "async": "1.5.2" - } - }, - "pretty-bytes": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", - "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.1.0" - } - }, - "pretty-checkbox": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/pretty-checkbox/-/pretty-checkbox-3.0.3.tgz", - "integrity": "sha1-1JyAE6j8CO4MLW695FNGS/28Qo4=" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "qs": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==", - "dev": true - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", - "integrity": "sha1-HQJ8K/oRasxmI7yo8AAWVyqH1CU=", - "dev": true, - "requires": { - "bytes": "1", - "string_decoder": "0.10" - }, - "dependencies": { - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - } - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "requirejs": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.3.tgz", - "integrity": "sha1-qln9OgKH6vQHlZoTgigES13WpqM=" - }, - "requirejs-text": { - "version": "2.0.15", - "resolved": "https://registry.npmjs.org/requirejs-text/-/requirejs-text-2.0.15.tgz", - "integrity": "sha1-ExOHM2E/xEV7fhJH6Mt1HfeqVCk=" - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-from": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", - "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", - "dev": true - }, - "resolve-pkg": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/resolve-pkg/-/resolve-pkg-0.1.0.tgz", - "integrity": "sha1-AsyZNBDik2livZcWahsHfalyVTE=", - "dev": true, - "requires": { - "resolve-from": "^2.0.0" - } - }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "^0.1.1" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" - }, - "rx": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", - "integrity": "sha1-pfE/957zt0D+MKqAP7CfmIBdR4I=" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safe-json-parse": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", - "integrity": "sha1-PnZyPjjf3aE8mx0poeB//uSzC1c=", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sass-graph": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.6.tgz", - "integrity": "sha512-MKuEYXFSGuRSi8FZ3A7imN1CeVn9Gpw0/SFJKdL1ejXJneI9a5rwlEZrKejhEFAA3O6yr3eIyl/WuvASvlT36g==", - "dev": true, - "requires": { - "glob": "^7.0.0", - "lodash": "^4.0.0", - "scss-tokenizer": "^0.2.3", - "yargs": "^7.0.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "yargs": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz", - "integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "5.0.0-security.0" - } - } - } - }, - "scss-tokenizer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", - "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", - "dev": true, - "requires": { - "js-base64": "^2.1.8", - "source-map": "^0.4.2" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - } - } - }, - "select2": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/select2/-/select2-4.0.3.tgz", - "integrity": "sha1-IHcz/pHqy5yxoT8SRjQB9HJEng8=", - "requires": { - "almond": "~0.3.1", - "jquery-mousewheel": "~3.1.13" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - } - } - }, - "serve-index": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", - "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "batch": "0.6.1", - "debug": "2.6.9", - "escape-html": "~1.0.3", - "http-errors": "~1.6.2", - "mime-types": "~2.1.17", - "parseurl": "~1.3.2" - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", - "dev": true - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stdout-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", - "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, - "string-template": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", - "integrity": "sha1-QpMuWYo1LQH8IuwzZ9nYTuxsmt0=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "table-dragger": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/table-dragger/-/table-dragger-1.0.2.tgz", - "integrity": "sha1-mB9Gxi/SiZs/xeZEBV6nKDGUlwc=", - "requires": { - "babel-runtime": "^6.20.0", - "crossvent": "^1.5.5", - "dragula-with-animation": "^3.7.2", - "rx": "^4.1.0" - } - }, - "tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "dev": true, - "requires": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - }, - "ticky": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ticky/-/ticky-1.0.1.tgz", - "integrity": "sha1-t8+nHnaPHJAAxJe5FRswlHxQ5G0=" - }, - "tiny-lr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", - "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", - "dev": true, - "requires": { - "body": "^5.1.0", - "debug": "^3.1.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.3.0", - "object-assign": "^4.1.0", - "qs": "^6.4.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", - "dev": true, - "requires": { - "glob": "^7.1.2" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "uglify-js": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.7.5.tgz", - "integrity": "sha1-RhLAx7qu4rp8SH3kkErhIgefLKg=", - "dev": true, - "requires": { - "async": "~0.2.6", - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - } - } - }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", - "dev": true - }, - "underscore": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", - "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" - }, - "underscore.string": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz", - "integrity": "sha512-g+dpmgn+XBneLmXXo+sGlW5xQEt4ErkS3mgeN2GFbremYeMBSJKr9Wf2KJplQVaiPY/f7FN6atosWYNm9ovrYg==", - "dev": true, - "requires": { - "sprintf-js": "^1.0.3", - "util-deprecate": "^1.0.2" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true - }, - "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "uri-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/uri-path/-/uri-path-1.0.0.tgz", - "integrity": "sha1-l0fwGDWJM8Md4PzP2C0TjmcmLjI=", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", - "dev": true, - "requires": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" - } - }, - "websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", - "dev": true - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xml-char-classes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/xml-char-classes/-/xml-char-classes-1.0.0.tgz", - "integrity": "sha1-ZGV4SKIP/F31g6Qq2KJ3tFErvE0=", - "dev": true - }, - "xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", - "dev": true, - "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" - }, - "dependencies": { - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", - "dev": true - } - } - }, - "yargs-parser": { - "version": "5.0.0-security.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz", - "integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "object.assign": "^4.1.0" - }, - "dependencies": { - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - } - } - } - } -} \ No newline at end of file diff --git a/dashboardv3/package.json b/dashboardv3/package.json deleted file mode 100644 index 49fd9dfac87..00000000000 --- a/dashboardv3/package.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "name": "atlas-metadata", - "description": "Apache Atlas", - "private": true, - "repository": { - "type": "git", - "url": "https://git-wip-us.apache.org/repos/asf/incubator-atlas.git" - }, - "scripts": { - "start": "grunt dev", - "build": "grunt build", - "dev-minify": "grunt dev-minify", - "build-minify": "grunt build-minify" - }, - "keywords": [ - "Apache", - "Atlas" - ], - "dependencies": { - "backbone": "1.2.3", - "backbone.babysitter": "0.1.12", - "backbone.marionette": "2.3.2", - "backbone.paginator": "2.0.5", - "backbone.wreqr": "1.4.0", - "backgrid": "0.3.8", - "backgrid-filter": "0.3.7", - "backgrid-orderable-columns": "0.1.2", - "backgrid-paginator": "0.3.9", - "backgrid-select-all": "0.3.5", - "backgrid-sizeable-columns": "0.1.1", - "bootstrap": "3.4.1", - "bootstrap-daterangepicker": "3.1.0", - "d3": "5.14.2", - "d3-tip": "^0.7.1", - "dagre-d3": "0.6.4", - "dropzone": "5.7.0", - "font-awesome": "4.7.0", - "jQuery-QueryBuilder": "2.4.3", - "jquery": "3.5.1", - "jquery-asBreadcrumbs": "0.2.2", - "jquery-placeholder": "2.3.1", - "jquery-sparkline": "2.4.0", - "jquery-steps": "1.1.0", - "jstree": "3.3.5", - "jstree-bootstrap-theme": "1.0.1", - "lossless-json": "1.0.4", - "moment": "2.21.0", - "moment-timezone": "0.5.14", - "platform": "1.3.4", - "pnotify": "3.2.0", - "pretty-checkbox": "3.0.3", - "requirejs": "2.3.3", - "requirejs-text": "2.0.15", - "select2": "4.0.3", - "table-dragger": "1.0.2", - "underscore": "1.8.3" - }, - "devDependencies": { - "grunt": "1.0.4", - "grunt-cli": "1.2.0", - "grunt-contrib-clean": "1.1.0", - "grunt-contrib-connect": "1.0.2", - "grunt-contrib-copy": "1.0.0", - "grunt-contrib-cssmin": "2.0.0", - "grunt-contrib-htmlmin": "2.2.0", - "grunt-contrib-rename": "0.2.0", - "grunt-contrib-uglify": "2.1.0", - "grunt-contrib-watch": "1.1.0", - "grunt-middleware-proxy": "1.0.7", - "grunt-sass": "3.1.0", - "grunt-template": "1.0.0", - "load-grunt-tasks": "3.5.2", - "node-sass": "4.13.1" - } -} diff --git a/dashboardv3/pom.xml b/dashboardv3/pom.xml deleted file mode 100644 index 6190f7007c1..00000000000 --- a/dashboardv3/pom.xml +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - 4.0.0 - - org.apache.atlas - apache-atlas - 3.0.0-SNAPSHOT - - - atlas-dashboardv3 - Apache Atlas New UI Application - Apache Atlas New UI - war - https://atlas.apache.org - - - - - - - com.github.eirslett - frontend-maven-plugin - - validate - ${project.build.directory} - - - - - - - org.apache.maven.plugins - maven-war-plugin - - false - - - ${project.build.directory}/dist - - - - - - maven-resources-plugin - 2.7 - - - copy-resources - - copy-resources - - validate - - ${basedir}/target/ - - - ${basedir} - - package.json - package-lock.json - gruntfile.js - - - - - - - - - com.github.eirslett - frontend-maven-plugin - - - install node and npm - - install-node-and-npm - - - ${node-for-v2.version} - ${npm-for-v2.version} - - - - npm install - - npm - - - install - - - - grunt dist - - grunt - - - ${project.build.dashboardv3.gruntBuild} - - - - - - - diff --git a/dashboardv3/public/css/animate.min.css b/dashboardv3/public/css/animate.min.css deleted file mode 100755 index bf71d18417c..00000000000 --- a/dashboardv3/public/css/animate.min.css +++ /dev/null @@ -1 +0,0 @@ -@charset "UTF-8";/*!;Animate.css - http://daneden.me/animate;Licensed under the MIT license - http://opensource.org/licenses/MIT;;Copyright (c) 2015 Daniel Eden;*/.animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.animated.hinge{-webkit-animation-duration:2s;animation-duration:2s}.animated.bounceIn,.animated.bounceOut,.animated.flipOutX,.animated.flipOutY{-webkit-animation-duration:.75s;animation-duration:.75s}@-webkit-keyframes bounce{0%,100%,20%,53%,80%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}40%,43%{-webkit-transition-timing-function:cubic-bezier(0.755,.050,.855,.060);transition-timing-function:cubic-bezier(0.755,.050,.855,.060);-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}70%{-webkit-transition-timing-function:cubic-bezier(0.755,.050,.855,.060);transition-timing-function:cubic-bezier(0.755,.050,.855,.060);-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}@keyframes bounce{0%,100%,20%,53%,80%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}40%,43%{-webkit-transition-timing-function:cubic-bezier(0.755,.050,.855,.060);transition-timing-function:cubic-bezier(0.755,.050,.855,.060);-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}70%{-webkit-transition-timing-function:cubic-bezier(0.755,.050,.855,.060);transition-timing-function:cubic-bezier(0.755,.050,.855,.060);-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}.bounce{-webkit-animation-name:bounce;animation-name:bounce;-webkit-transform-origin:center bottom;transform-origin:center bottom}@-webkit-keyframes flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}@keyframes flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}.flash{-webkit-animation-name:flash;animation-name:flash}@-webkit-keyframes pulse{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes pulse{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.pulse{-webkit-animation-name:pulse;animation-name:pulse}@-webkit-keyframes rubberBand{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(0.75,1.25,1);transform:scale3d(0.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes rubberBand{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(0.75,1.25,1);transform:scale3d(0.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.rubberBand{-webkit-animation-name:rubberBand;animation-name:rubberBand}@-webkit-keyframes shake{0%,100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}@keyframes shake{0%,100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}.shake{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes swing{20%{-webkit-transform:rotate3d(0,0,1,15deg);transform:rotate3d(0,0,1,15deg)}40%{-webkit-transform:rotate3d(0,0,1,-10deg);transform:rotate3d(0,0,1,-10deg)}60%{-webkit-transform:rotate3d(0,0,1,5deg);transform:rotate3d(0,0,1,5deg)}80%{-webkit-transform:rotate3d(0,0,1,-5deg);transform:rotate3d(0,0,1,-5deg)}100%{-webkit-transform:rotate3d(0,0,1,0deg);transform:rotate3d(0,0,1,0deg)}}@keyframes swing{20%{-webkit-transform:rotate3d(0,0,1,15deg);transform:rotate3d(0,0,1,15deg)}40%{-webkit-transform:rotate3d(0,0,1,-10deg);transform:rotate3d(0,0,1,-10deg)}60%{-webkit-transform:rotate3d(0,0,1,5deg);transform:rotate3d(0,0,1,5deg)}80%{-webkit-transform:rotate3d(0,0,1,-5deg);transform:rotate3d(0,0,1,-5deg)}100%{-webkit-transform:rotate3d(0,0,1,0deg);transform:rotate3d(0,0,1,0deg)}}.swing{-webkit-transform-origin:top center;transform-origin:top center;-webkit-animation-name:swing;animation-name:swing}@-webkit-keyframes tada{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes tada{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.tada{-webkit-animation-name:tada;animation-name:tada}@-webkit-keyframes wobble{0%{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}100%{-webkit-transform:none;transform:none}}@keyframes wobble{0%{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}100%{-webkit-transform:none;transform:none}}.wobble{-webkit-animation-name:wobble;animation-name:wobble}@-webkit-keyframes bounceIn{0%,100%,20%,40%,60%,80%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes bounceIn{0%,100%,20%,40%,60%,80%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.bounceIn{-webkit-animation-name:bounceIn;animation-name:bounceIn}@-webkit-keyframes bounceInDown{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInDown{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}100%{-webkit-transform:none;transform:none}}.bounceInDown{-webkit-animation-name:bounceInDown;animation-name:bounceInDown}@-webkit-keyframes bounceInLeft{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0);transform:translate3d(-3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0);transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInLeft{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0);transform:translate3d(-3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0);transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}100%{-webkit-transform:none;transform:none}}.bounceInLeft{-webkit-animation-name:bounceInLeft;animation-name:bounceInLeft}@-webkit-keyframes bounceInRight{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(3000px,0,0);transform:translate3d(3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0);transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInRight{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(3000px,0,0);transform:translate3d(3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0);transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}100%{-webkit-transform:none;transform:none}}.bounceInRight{-webkit-animation-name:bounceInRight;animation-name:bounceInRight}@-webkit-keyframes bounceInUp{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,3000px,0);transform:translate3d(0,3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes bounceInUp{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(0.215,.61,.355,1);transition-timing-function:cubic-bezier(0.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,3000px,0);transform:translate3d(0,3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.bounceInUp{-webkit-animation-name:bounceInUp;animation-name:bounceInUp}@-webkit-keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}100%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}@keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}100%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}.bounceOut{-webkit-animation-name:bounceOut;animation-name:bounceOut}@-webkit-keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.bounceOutDown{-webkit-animation-name:bounceOutDown;animation-name:bounceOutDown}@-webkit-keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.bounceOutLeft{-webkit-animation-name:bounceOutLeft;animation-name:bounceOutLeft}@-webkit-keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0);transform:translate3d(-20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0);transform:translate3d(-20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.bounceOutRight{-webkit-animation-name:bounceOutRight;animation-name:bounceOutRight}@-webkit-keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0);transform:translate3d(0,20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0);transform:translate3d(0,20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.bounceOutUp{-webkit-animation-name:bounceOutUp;animation-name:bounceOutUp}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInDown{-webkit-animation-name:fadeInDown;animation-name:fadeInDown}@-webkit-keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInDownBig{-webkit-animation-name:fadeInDownBig;animation-name:fadeInDownBig}@-webkit-keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInLeft{-webkit-animation-name:fadeInLeft;animation-name:fadeInLeft}@-webkit-keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInLeftBig{-webkit-animation-name:fadeInLeftBig;animation-name:fadeInLeftBig}@-webkit-keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInRight{-webkit-animation-name:fadeInRight;animation-name:fadeInRight}@-webkit-keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInRightBig{-webkit-animation-name:fadeInRightBig;animation-name:fadeInRightBig}@-webkit-keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInUp{-webkit-animation-name:fadeInUp;animation-name:fadeInUp}@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInUpBig{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeOutDown{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes fadeOutDown{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.fadeOutDown{-webkit-animation-name:fadeOutDown;animation-name:fadeOutDown}@-webkit-keyframes fadeOutDownBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes fadeOutDownBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.fadeOutDownBig{-webkit-animation-name:fadeOutDownBig;animation-name:fadeOutDownBig}@-webkit-keyframes fadeOutLeft{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@keyframes fadeOutLeft{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.fadeOutLeft{-webkit-animation-name:fadeOutLeft;animation-name:fadeOutLeft}@-webkit-keyframes fadeOutLeftBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes fadeOutLeftBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.fadeOutLeftBig{-webkit-animation-name:fadeOutLeftBig;animation-name:fadeOutLeftBig}@-webkit-keyframes fadeOutRight{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}@keyframes fadeOutRight{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.fadeOutRight{-webkit-animation-name:fadeOutRight;animation-name:fadeOutRight}@-webkit-keyframes fadeOutRightBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes fadeOutRightBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.fadeOutRightBig{-webkit-animation-name:fadeOutRightBig;animation-name:fadeOutRightBig}@-webkit-keyframes fadeOutUp{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes fadeOutUp{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp}@-webkit-keyframes fadeOutUpBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes fadeOutUpBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.fadeOutUpBig{-webkit-animation-name:fadeOutUpBig;animation-name:fadeOutUpBig}@-webkit-keyframes flip{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-360deg);transform:perspective(400px) rotate3d(0,1,0,-360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95);transform:perspective(400px) scale3d(.95,.95,.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}@keyframes flip{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-360deg);transform:perspective(400px) rotate3d(0,1,0,-360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95);transform:perspective(400px) scale3d(.95,.95,.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}.animated.flip{-webkit-backface-visibility:visible;backface-visibility:visible;-webkit-animation-name:flip;animation-name:flip}@-webkit-keyframes flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInX{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInX;animation-name:flipInX}@-webkit-keyframes flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInY{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInY;animation-name:flipInY}@-webkit-keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}@keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}.flipOutX{-webkit-animation-name:flipOutX;animation-name:flipOutX;-webkit-backface-visibility:visible!important;backface-visibility:visible!important}@-webkit-keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}@keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}.flipOutY{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipOutY;animation-name:flipOutY}@-webkit-keyframes lightSpeedIn{0%{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}100%{-webkit-transform:none;transform:none;opacity:1}}@keyframes lightSpeedIn{0%{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}100%{-webkit-transform:none;transform:none;opacity:1}}.lightSpeedIn{-webkit-animation-name:lightSpeedIn;animation-name:lightSpeedIn;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}@-webkit-keyframes lightSpeedOut{0%{opacity:1}100%{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}@keyframes lightSpeedOut{0%{opacity:1}100%{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}.lightSpeedOut{-webkit-animation-name:lightSpeedOut;animation-name:lightSpeedOut;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}@-webkit-keyframes rotateIn{0%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,-200deg);transform:rotate3d(0,0,1,-200deg);opacity:0}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateIn{0%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,-200deg);transform:rotate3d(0,0,1,-200deg);opacity:0}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}.rotateIn{-webkit-animation-name:rotateIn;animation-name:rotateIn}@-webkit-keyframes rotateInDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInDownLeft{-webkit-animation-name:rotateInDownLeft;animation-name:rotateInDownLeft}@-webkit-keyframes rotateInDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInDownRight{-webkit-animation-name:rotateInDownRight;animation-name:rotateInDownRight}@-webkit-keyframes rotateInUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInUpLeft{-webkit-animation-name:rotateInUpLeft;animation-name:rotateInUpLeft}@-webkit-keyframes rotateInUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-90deg);transform:rotate3d(0,0,1,-90deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-90deg);transform:rotate3d(0,0,1,-90deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInUpRight{-webkit-animation-name:rotateInUpRight;animation-name:rotateInUpRight}@-webkit-keyframes rotateOut{0%{-webkit-transform-origin:center;transform-origin:center;opacity:1}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,200deg);transform:rotate3d(0,0,1,200deg);opacity:0}}@keyframes rotateOut{0%{-webkit-transform-origin:center;transform-origin:center;opacity:1}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,200deg);transform:rotate3d(0,0,1,200deg);opacity:0}}.rotateOut{-webkit-animation-name:rotateOut;animation-name:rotateOut}@-webkit-keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}}@keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}}.rotateOutDownLeft{-webkit-animation-name:rotateOutDownLeft;animation-name:rotateOutDownLeft}@-webkit-keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}@keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}.rotateOutDownRight{-webkit-animation-name:rotateOutDownRight;animation-name:rotateOutDownRight}@-webkit-keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}@keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}.rotateOutUpLeft{-webkit-animation-name:rotateOutUpLeft;animation-name:rotateOutUpLeft}@-webkit-keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,90deg);transform:rotate3d(0,0,1,90deg);opacity:0}}@keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,90deg);transform:rotate3d(0,0,1,90deg);opacity:0}}.rotateOutUpRight{-webkit-animation-name:rotateOutUpRight;animation-name:rotateOutUpRight}@-webkit-keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0,0,1,80deg);transform:rotate3d(0,0,1,80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0,0,1,60deg);transform:rotate3d(0,0,1,60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}100%{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}@keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0,0,1,80deg);transform:rotate3d(0,0,1,80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0,0,1,60deg);transform:rotate3d(0,0,1,60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}100%{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}.hinge{-webkit-animation-name:hinge;animation-name:hinge}@-webkit-keyframes rollIn{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes rollIn{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg)}100%{opacity:1;-webkit-transform:none;transform:none}}.rollIn{-webkit-animation-name:rollIn;animation-name:rollIn}@-webkit-keyframes rollOut{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg)}}@keyframes rollOut{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg)}}.rollOut{-webkit-animation-name:rollOut;animation-name:rollOut}@-webkit-keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}@keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}.zoomIn{-webkit-animation-name:zoomIn;animation-name:zoomIn}@-webkit-keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomInDown{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomInLeft{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes zoomInRight{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomInRight{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomInRight{-webkit-animation-name:zoomInRight;animation-name:zoomInRight}@-webkit-keyframes zoomInUp{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomInUp{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomInUp{-webkit-animation-name:zoomInUp;animation-name:zoomInUp}@-webkit-keyframes zoomOut{0%{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}100%{opacity:0}}@keyframes zoomOut{0%{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}100%{opacity:0}}.zoomOut{-webkit-animation-name:zoomOut;animation-name:zoomOut}@-webkit-keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomOutDown{-webkit-animation-name:zoomOutDown;animation-name:zoomOutDown}@-webkit-keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;transform-origin:left center}}@keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;transform-origin:left center}}.zoomOutLeft{-webkit-animation-name:zoomOutLeft;animation-name:zoomOutLeft}@-webkit-keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;transform-origin:right center}}@keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;transform-origin:right center}}.zoomOutRight{-webkit-animation-name:zoomOutRight;animation-name:zoomOutRight}@-webkit-keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}@keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(0.55,.055,.675,.19);animation-timing-function:cubic-bezier(0.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(0.175,.885,.32,1);animation-timing-function:cubic-bezier(0.175,.885,.32,1)}}.zoomOutUp{-webkit-animation-name:zoomOutUp;animation-name:zoomOutUp}@-webkit-keyframes slideInDown{0%{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0)}}@keyframes slideInDown{0%{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInDown{-webkit-animation-name:slideInDown;animation-name:slideInDown}@-webkit-keyframes slideInLeft{0%{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0)}}@keyframes slideInLeft{0%{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInLeft{-webkit-animation-name:slideInLeft;animation-name:slideInLeft}@-webkit-keyframes slideInRight{0%{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0)}}@keyframes slideInRight{0%{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInRight{-webkit-animation-name:slideInRight;animation-name:slideInRight}@-webkit-keyframes slideInUp{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0)}}@keyframes slideInUp{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInUp{-webkit-animation-name:slideInUp;animation-name:slideInUp}@-webkit-keyframes slideOutDown{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%)}}@keyframes slideOutDown{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.slideOutDown{-webkit-animation-name:slideOutDown;animation-name:slideOutDown}@-webkit-keyframes slideOutLeft{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%)}}@keyframes slideOutLeft{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.slideOutLeft{-webkit-animation-name:slideOutLeft;animation-name:slideOutLeft}@-webkit-keyframes slideOutRight{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%)}}@keyframes slideOutRight{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.slideOutRight{-webkit-animation-name:slideOutRight;animation-name:slideOutRight}@-webkit-keyframes slideOutUp{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%)}}@keyframes slideOutUp{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.slideOutUp{-webkit-animation-name:slideOutUp;animation-name:slideOutUp} \ No newline at end of file diff --git a/dashboardv3/public/css/bootstrap-sidebar.css b/dashboardv3/public/css/bootstrap-sidebar.css deleted file mode 100644 index c66e4e1b0b1..00000000000 --- a/dashboardv3/public/css/bootstrap-sidebar.css +++ /dev/null @@ -1,150 +0,0 @@ -/*! - * Start Bootstrap - Simple Sidebar (http://startbootstrap.com/) - * Copyright 2013-2016 Start Bootstrap - * Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap/blob/gh-pages/LICENSE) - */ - - -/* Toggle Styles */ - -#wrapper { - padding-left: 0; - -webkit-transition: all 0.3s ease; - -moz-transition: all 0.3s ease; - -o-transition: all 0.3s ease; - transition: all 0.3s ease; -} - -#wrapper.toggled { - padding-left: 300px; -} - -#sidebar-wrapper { - z-index: 2; - position: fixed; - /*left: 350px;*/ - /*width: 0;*/ - height: 100%; - /*margin-left: -350px;*/ - /*overflow-y: auto;*/ - background: #fff; - -moz-transition: left 0.3s; - -o-transition: left 0.3s; - -webkit-transition: left 0.3s; - transition: left 0.3s; -} - -#wrapper.toggled #sidebar-wrapper { - /*width: 350px;*/ -} - -#page-content-wrapper { - width: 100%; - position: absolute; -} - -#wrapper.toggled #page-content-wrapper { - position: absolute; - margin-right: -350px; -} - - -/* Sidebar Styles */ - -.sidebar-nav { - margin: 0; - padding: 0; - list-style: none; -} - -.sidebar-nav>li { - line-height: 50px; - padding: 5px 20px; - border-bottom: 1px #1c1e2a solid; -} - -.sidebar-nav>li a { - display: block; - text-decoration: none; - color: #fff; -} - -.sidebar-nav>li a:hover { - text-decoration: none; - color: #fff; -} - -.sidebar-nav>li a:active, -.sidebar-nav>li a:focus { - text-decoration: none; -} - -.sidebar-nav>.sidebar-brand { - font-size: 18px; - line-height: 50px; -} - -.sidebar-nav>.sidebar-brand a { - color: #ddd; - letter-spacing: 1px; -} - -.sidebar-nav>.sidebar-brand a:hover { - color: #fff; - background: none; -} - - -/* Extended Elements */ - -.sidebar-input .input-group { - margin: 10px 0px; -} - -.sidebar-input .form-control, -.sidebar-input .input-group-addon { - background-color: transparent; - border-radius: 0px; -} - -.sidebar-input .form-control { - border-right: none; - color: #eee; -} - -.sidebar-input .input-group-addon { - border-left: none; - color: #ccc; -} - -.sidebar-input .form-control:focus+.input-group-addon { - border-color: #66afe9; -} - -@media(min-width:768px) { - #wrapper { - padding-left: 350px; - } - - #wrapper.toggled { - padding-left: 0; - } - - #sidebar-wrapper { - /*width: 350px;*/ - } - - #wrapper.toggled #sidebar-wrapper { - width: 0; - padding: 0; - } - - #page-content-wrapper { - position: relative; - } - - #wrapper.toggled #page-content-wrapper { - position: relative; - margin-right: 0; - } -} \ No newline at end of file diff --git a/dashboardv3/public/css/googlefonts.css b/dashboardv3/public/css/googlefonts.css deleted file mode 100644 index 53ffba87497..00000000000 --- a/dashboardv3/public/css/googlefonts.css +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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. - */ - - -/* source-sans-pro-regular - latin */ - -@font-face { - font-family: 'Source Sans Pro'; - font-style: normal; - font-weight: 400; - src: url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.eot'); - /* IE9 Compat Modes */ - src: local('Source Sans Pro Regular'), local('SourceSansPro-Regular'), - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff') format('woff'), /* Modern Browsers */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.svg#SourceSansPro') format('svg'); - /* Legacy iOS */ -} - - -/* source-sans-pro-600 - latin */ - -@font-face { - font-family: 'Source Sans Pro'; - font-style: normal; - font-weight: 600; - src: url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.eot'); - /* IE9 Compat Modes */ - src: local('Source Sans Pro SemiBold'), local('SourceSansPro-SemiBold'), - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff2') format('woff2'), /* Super Modern Browsers */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff') format('woff'), /* Modern Browsers */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.ttf') format('truetype'), /* Safari, Android, iOS */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.svg#SourceSansPro') format('svg'); - /* Legacy iOS */ -} - - -/* source-sans-pro-700 - latin */ - -@font-face { - font-family: 'Source Sans Pro'; - font-style: normal; - font-weight: 700; - src: url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.eot'); - /* IE9 Compat Modes */ - src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff2') format('woff2'), /* Super Modern Browsers */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff') format('woff'), /* Modern Browsers */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.ttf') format('truetype'), /* Safari, Android, iOS */ - url('../js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.svg#SourceSansPro') format('svg'); - /* Legacy iOS */ -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/__mixin.scss b/dashboardv3/public/css/scss/__mixin.scss deleted file mode 100644 index f3ce565cb58..00000000000 --- a/dashboardv3/public/css/scss/__mixin.scss +++ /dev/null @@ -1,72 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -@mixin clearfix() { - - &:before, - &:after { - content: " "; // 1 - display: table; // 2 - } - - &:after { - clear: both; - } -} - -@mixin ellipsis() { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; -} - -@mixin transition($transition...) { - -webkit-transition: $transition; - -moz-transition: $transition; - -o-transition: $transition; - transition: $transition; -} - -@mixin transition-property($properties...) { - -webkit-transition-property: $properties; - -moz-transition-property: $properties; - -o-transition-property: $properties; - transition-property: $properties; -} - -@mixin btn-action-effect($color) { - @if $color=='default' { - border: 1px $color_keppel_approx solid; - color: $color_keppel_approx; - } - - @else if $color=='blue' { - border: 1px $color_havelock_blue_approx solid; - color: $color_havelock_blue_approx; - } -} - -@mixin btn-action-hover-effect($color1) { - @if $color1=='default' { - background-color: $color_keppel_approx; - color: $white; - } - - @else if $color1=='blue' { - color: $white; - background-color: $tag_color; - } -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/__variable.scss b/dashboardv3/public/css/scss/__variable.scss deleted file mode 100644 index 1d1cbb4503b..00000000000 --- a/dashboardv3/public/css/scss/__variable.scss +++ /dev/null @@ -1,100 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -//fonts -$font_0: Source Sans Pro; -$font_1: sans-serif; -$font_2: FontAwesome; -$font_3: Helvetica; -$font_4: Arial; -$font_5: sans-serf; -//Colors -$white: #fff; -$black: #000; -$red: #f00; -$gray: #808080; -$dark_gray: #666; -$action_gray: #999999; -$color_keppel_approx: #37bb9b; -$color_gallery_approx: #eee; -$color_tuna_approx: #323544; -$color_celeste_approx: #ccc; -$color_cornflower_blue_approx: #66afe9; -$color_mystic_approx: #e8e9ee; -$color_jungle_green_approx: #38bb9b; -$color_jungle_green_light: #7ed3be; -$color_froly_approx: #ee6e73; -$color_manatee_approx: #9398a0; -$color_havelock_blue_approx: #4a90e2; -$color_ironside_gray_approx: #686868; -$color_mercury_approx: #e6e6e6; -$color_whisper_approx: #f6f7fa; -$color_bombay_approx: #b5b9bc; -$color_white_lilac_approx: #f6f7fb; -$color_puerto_rico_approx: #3dd4af; -$color_star_dust_approx: #9a9a9a; -$color_mirage_approx: #1c1e2a; -$concrete: #f2f2f2; -$lightGrey: #e1e2e4; -$color_form_control: #e8e8e8; -$attribute-dash-box: #cbcbcb; -//old - style color -$color_bali_hai_approx: #8fa5b1; -$transparent: transparent; -$black_7_5: rgba(0, 0, 0, 0.075); -$color_hoki_approx: #698797; -$color_curious_blue_approx: #1ba9e2; -$color_blue_bayoux_approx: #44697d; -$color_pickled_bluewood_approx: #334f5e; -$color_picton_blue_approx: #3cb5e6; -$color_yellow_sea_approx: #f5a700; -$color_gamboge_approx: #de9800; -$color_trinidad_approx: #e14f00; -$color_grenadier_approx: #c74600; -$color_athens_gray_approx: #e9ecf2; -$color_green_house_approx: #26530c; -$color_dark_grey_approx: #333; -$black_10: rgba(0, 0, 0, 0.1); -$color_cararra_approx: #ececec; -$black_30: rgba(0, 0, 0, 0.3); -$color_pizazz_approx: #ff8e00; -$black_25: rgba(0, 0, 0, 0.25); -$color_cape_cod_approx: #414141; -$color_apple_blossom_approx: #a94442; -$color_mine_shaft_approx: #333; -$white_80: rgba(255, 255, 255, 0.8); -$color_alto_approx: #dadada; -$color_fuscous_gray_approx: #545454; -$black_65: rgba(0, 0, 0, 0.65); -$white_25: rgba(255, 255, 255, 0.25); -$color_fern_approx: #65bd63; -$color_opal_approx: #a7cec6; -$white_50: rgba(255, 255, 255, 0.5); -$black_20: rgba(0, 0, 0, 0.2); -$color_pelorous_approx: #3aa2d0; -$color_laser_approx: #c4bb61; -$color_zombie_approx: #e0dd94; -$steel_blue: steelblue; -$black_80: rgba(0, 0, 0, 0.8); -$color_bright_turquoise_approx: #00ffd0; -$color_mountain_mist_approx: #999; -$color_suva_gray_approx: #868686; -$tag_color: #4a90e2; -$delete_link: #bb5838; -//urls -$url_0: url(../img/loading.gif); - -$switchTransition: 0.4s ease-out; \ No newline at end of file diff --git a/dashboardv3/public/css/scss/business-metadata.scss b/dashboardv3/public/css/scss/business-metadata.scss deleted file mode 100644 index efed616e1f4..00000000000 --- a/dashboardv3/public/css/scss/business-metadata.scss +++ /dev/null @@ -1,243 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* business-metadata */ -.business-metadata-tree-parent { - padding: 0px; - - >li:first-child { - font-weight: 600; - word-break: break-all; - } - - .business-metadata-tree-child { - &.entity-detail-table table { - td { - &:nth-child(1) { - width: 35%; - } - - word-break: break-word; - } - } - - padding-left: 5px; - margin-top: 10px; - font-weight: 100; - } - - .custom-table { - &:not(.bm-create) { - .custom-tr { - - .custom-col-1 { - width: calc(50% - 55px); - - .select2-selection--multiple .select2-selection__rendered { - overflow: scroll; - } - } - - .custom-col-2 { - width: 45px; - } - } - } - } - -} - -.business-metadata-options.dropdown { - .dropdown-menu { - min-width: 100px; - - .dropdown-item { - display: block; - width: 100%; - padding: .25rem 1.5rem; - clear: both; - font-weight: 400; - color: $color_jungle_green_approx; - text-align: inherit; - white-space: nowrap; - background-color: transparent; - border: 0; - } - } -} - -.business-metadata-options.dropdown.open { - .btn-action { - background-color: $color_jungle_green_approx; - border: 1px solid $color_jungle_green_approx; - color: #fff !important; - } -} - -.business-metadata-details, -.admin-details { - .tableOverlay { - background-color: transparent; - } - - .expandable .attr-details { - max-height: 300px; - overflow: auto; - margin-left: 30px; - width: calc(100% - 30px); - } - - .expandable .admin-audit-details { - display: flex; - flex-wrap: wrap; - margin-left: 20px; - - .attr-type-container { - border: 1px solid #ddd; - border-radius: 4px; - padding: 5px 10px; - margin: 5px; - width: 32%; - } - } - - .expandable .admin-attr-details { - max-height: 100px; - margin-left: 20px; - width: calc(100% - 27px); - } - - .import-export .admin-audit-details { - display: table; - border: 1px solid #ddd; - border-radius: 4px; - - tr>td:nth-child(2) { - text-align: right; - } - } -} - -.admin-details .expandable .admin-audit-details .attr-type-container { - max-height: 200px; - overflow: auto; -} - -.admin-details .attributeResultContainer { - float: left; -} - -.tab-pane { - .business-metadata-attr-page { - position: absolute; - top: 0px; - left: 0px; - padding: 20px; - background-color: $white; - width: 100%; - height: inherit; - } -} - -.business-metadata-attr-page { - .form-horizontal { - padding: 10px 22px; - // border: 1px solid #DEDEDE; - - .control-label-sm { - padding-top: 3px; - } - - .control-label-sm-pl { - @extend .control-label-sm; - padding-left: 10px; - } - - .control-label-sm-pr { - @extend .control-label-sm; - padding-right: 10px; - } - - .business-metadata-attr { - border: 1px solid #DEDEDE; - padding: 10px 20px - } - } -} - -.business-metadata-attr-fontLoader { - position: absolute; - top: 50%; - left: 50%; - display: none; -} - -.business-metadata-attr-tableOverlay { - position: absolute; - width: calc(100% - 40px); - height: 100%; - background: #808080; - z-index: 99; - display: none; - opacity: 0.2; -} - -.business-metadata-attr-page { - .modal-footer { - text-align: center; - } -} - -.remove-from-list { - .select2-results__option[aria-selected=true] { - display: none; - } -} - -.business-metadata-detail-attr { - margin-bottom: 0px; - box-shadow: none; - - .panel-heading { - color: #686868 !important; - font-size: 13px; - padding: 0; - - .panel-title { - font-size: 14px; - word-break: break-all; - width: inherit; - - a:hover { - color: #686868 !important; - opacity: 1 !important; - } - } - } - - .btn-group>button { - color: #686868 !important; - } - - td { - word-break: break-word; - } - - .business-metadata-detail-attr-key { - width: 30%; - } -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/common.scss b/dashboardv3/public/css/scss/common.scss deleted file mode 100644 index 9310e20cb48..00000000000 --- a/dashboardv3/public/css/scss/common.scss +++ /dev/null @@ -1,346 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -/* common.scss */ -.readOnly { - - span, - button, - a { - i { - &.fa-trash[data-guid] { - display: none; - } - - &.fa-trash[data-id="delete"] { - display: none; - } - } - - &.btn[data-id="addTag"] { - display: none; - } - - &.btn[data-id="addTerm"] { - display: none; - } - - &.btn[data-id="editButton"] { - display: none; - } - - &.editbutton[data-id="editButton"] { - display: none !important; - } - - &[data-id="delete"], - &[data-id="edit"] { - display: none; - } - - &.btn[data-id="tagClick"] { - span { - display: block; - padding: 3px 5px 3px 5px; - } - - i.fa-close[data-id="deleteTag"], - i.fa-times[data-id="deleteTag"], - i.fa-times[data-id="delete"] { - display: none; - } - } - } -} - -.details-backbutton { - display: none !important; -} - -.full-screen { - #sidebar-wrapper { - left: 0; - } - - #wrapper { - padding-left: 0px; - } -} - -.detail-page { - .details-backbutton { - display: table-cell !important; - } - - .searched-term-highlight { - background-color: #eeee31; - transition: background-color 4s, font-weight 2s; - - &.bold { - background-color: transparent; - font-weight: bold; - } - } -} - -pre { - background-color: ghostwhite; - border: 1px solid silver; - padding: 10px; - white-space: -moz-pre-wrap; - /* Mozilla, supported since 1999 */ - white-space: -pre-wrap; - /* Opera */ - white-space: -o-pre-wrap; - /* Opera */ - white-space: pre-wrap; - /* CSS3 - Text module (Candidate Recommendation) http://www.w3.org/TR/css3-text/#white-space */ - word-wrap: break-word; - - /* IE 5.5+ */ - &.code-block { - code { - position: relative; - max-height: 400px; - display: block; - overflow: auto; - text-align: left; - } - - position: relative; - overflow: hidden; - - &.shrink { - height: 112px; - white-space: -moz-pre-wrap; - /* Mozilla, supported since 1999 */ - white-space: -pre-wrap; - /* Opera */ - white-space: -o-pre-wrap; - /* Opera */ - white-space: pre-wrap; - /* CSS3 - Text module (Candidate Recommendation) http://www.w3.org/TR/css3-text/#white-space */ - word-wrap: break-word; - - /* IE 5.5+ */ - code { - height: 100px; - } - - &.fixed-height { - height: 75px; - - code { - height: 54px; - } - } - - &.medium-height { - height: 100px; - } - - .expand-collapse-button { - i:before { - content: "\f107"; - } - } - } - - .expand-collapse-button { - position: absolute; - right: 3px; - top: 4px; - z-index: 1; - - i:before { - content: "\f106"; - } - } - - .json-key { - color: brown; - } - - .json-value { - color: navy; - } - - .json-string { - color: olive; - - &.cursor { - cursor: pointer; - text-decoration: underline; - } - } - } - - code { - font-family: monospace; - } -} - -.panel-body .memory-details { - pre { - &.code-block { - &.fixed-height { - max-height: 112px; - overflow: auto; - } - - &.shrink { - height: 144px; - - code { - height: 130px; - } - } - } - } -} - -#accordion { - .panel-default>.panel-heading { - cursor: pointer; - width: 100%; - } -} - -.footer-content { - position: fixed; - right: 0px; - padding: 2px; - bottom: 0; - background: white; -} - -.custom-table { - width: 100%; - display: flex; - - tbody { - display: flex; - flex-flow: column; - width: 100%; - } - - .custom-tr { - margin-left: 15px; - display: flex; - width: calc(100% - 15px); - - .custom-col-0, - .custom-col-1, - .custom-col-2 { - vertical-align: top; - - textarea { - resize: vertical; - height: 34px; - min-height: 34px; - max-height: 70px; - } - } - - - .custom-col-0 { - line-height: 31px; - width: 9px; - padding: 0px 2px; - } - - .custom-col-1 { - width: calc(50% - 90px); - flex-grow: 2; - - &:first-child { - width: 30% !important; - flex-grow: 1; - } - } - - .custom-col-2 { - text-align: center; - width: 80px; - padding-left: 10px; - - &>button { - padding: 7px 10px; - margin-bottom: 10px; - } - } - } -} - -.errorMsg { - color: $red; -} - -.badge-default { - background-color: $color_havelock_blue_approx; - color: $white; - font-size: 12px; - font-weight: normal; - margin-bottom: 5px; - margin-left: 5px; - float: left; -} - -.errorValidate { - border-color: red !important; -} - -.errorValidate+span .select2-selection { - border-color: red !important; - -} - -.button-loader { - position: relative; - padding-left: 22px !important; - - &:after { - content: "\f021"; - position: absolute; - display: flex; - justify-content: center; - align-items: center; - left: 0px; - top: 0px; - font-family: FontAwesome; - background: transparent; - height: 100%; - width: 26px; - font-size: 11px; - animation: spin 1000ms infinite linear; - } -} - -.attr-details { - ul { - list-style: disc; - - li { - cursor: pointer; - } - } -} - -.long-description { - width: 85%; - cursor: default !important; - background-color: transparent !important; -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/form.scss b/dashboardv3/public/css/scss/form.scss deleted file mode 100644 index d1ccafcbea6..00000000000 --- a/dashboardv3/public/css/scss/form.scss +++ /dev/null @@ -1,625 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -/* form.scss */ - -.form-horizontal { - .control-label-sm { - padding-top: 3px; - } - - .control-label-sm-pl { - @extend .control-label-sm; - padding-left: 10px; - } - - .control-label-sm-pr { - @extend .control-label-sm; - padding-right: 10px; - } - -} - -.form-group { - .required:after { - content: "*"; - padding-left: 1%; - color: $red; - } - - .control-label { - &.text-left { - text-align: left; - } - - &.text-right { - text-align: right; - } - } - - .form-control { - //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - background-color: $color_white_lilac_approx; - border: 1px $color_mystic_approx solid; - - &[disabled] { - background-color: $color_gallery_approx; - } - - &:focus { - border-color: $color_bali_hai_approx; - outline: 0; //Instead of the line below you could use @include box-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - box-shadow: inset 0 1px 1px $black_7_5, 0 0 2px $color_bali_hai_approx; - } - } -} - -.form-color { - - .form-group span[class^="select2-selection select2-selection--"], - .form-control { - background-color: $color_form_control !important; - } -} - -.sidebar-wrapper { - z-index: 9 !important; - - .form-control { - background-color: $white; - border: 1px $white solid; - } -} - -.well { - background-color: $white; - border: 1px solid $color_mystic_approx; - - &.no-left-right-border { - border-left: 0px; - border-right: 0px; - padding: 16px 0px; - } -} - -textarea { - resize: none; - - &:focus { - outline: none !important; - } -} - -label { - font-weight: 600; -} - -button { - &:focus { - outline: none !important; - } - - &[disabled] { - .fa { - opacity: .65; - } - } -} - -.btn { - //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 4px; - - &:hover { - text-decoration: none; - } -} - -.btn.btn-only-icon { - border: none; - background: none; - - &.btn-atlas { - color: $color_jungle_green_approx; - } -} - -[class^="col-md-"], -[class^="col-sm-"] { - - .btn.checkbox-inline, - .btn.radio-inline { - padding-left: 19px; - } -} - -.btn-primary { - color: $white; - background-color: $color_blue_bayoux_approx; - border-color: $color_blue_bayoux_approx; - - &:hover { - color: $white; - background-color: $color_pickled_bluewood_approx; - border-color: $color_pickled_bluewood_approx; - } -} - -.btn-success { - color: $white; - background-color: $color_jungle_green_approx; - border-color: $color_jungle_green_approx; - - &:hover { - color: $white; - background-color: $color_jungle_green_approx; - border-color: $color_jungle_green_approx; - } - - &:focus { - color: $white; - background-color: $color_jungle_green_approx; - border-color: $color_jungle_green_approx; - } -} - -.btn-info { - color: $white; - background-color: $color_picton_blue_approx; - border-color: $color_picton_blue_approx; - - &:hover { - color: $white; - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - } - - &:focus { - color: $white; - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - } -} - -.btn-warning { - color: $white; - background-color: $color_yellow_sea_approx; - border-color: $color_yellow_sea_approx; - - &:hover { - color: $white; - background-color: $color_gamboge_approx; - border-color: $color_gamboge_approx; - } - - &:focus { - color: $white; - background-color: $color_gamboge_approx; - border-color: $color_gamboge_approx; - } -} - -.btn-danger { - color: $white; - background-color: $color_trinidad_approx; - border-color: $color_trinidad_approx; - - &:hover { - color: $white; - background-color: $color_grenadier_approx; - border-color: $color_grenadier_approx; - } - - &:focus { - color: $white; - background-color: $color_grenadier_approx; - border-color: $color_grenadier_approx; - } -} - -.btn-atlas { - padding: 10px 20px; - background-color: $color_keppel_approx; - color: $white; - margin-bottom: 10px; - border: 1px $color_keppel_approx solid; //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 4px; //Instead of the line below you could use @include transition($transition-1, $transition-2, $transition-3, $transition-4, $transition-5, $transition-6, $transition-7, $transition-8, $transition-9, $transition-10) - transition: all 0.3s ease; - margin: 2px; - - &:hover { - @include btn-action-effect('default'); - background-color: $transparent; - } - - &:focus { - @include btn-action-effect('default'); - background-color: $transparent; - } - - &.btn-sm { - padding: 2px 6px; - } - - &.btn-xs { - padding: 0px 5px; - } - - &.btn-md { - padding: 6px 10px; - } -} - -.btn-inline { - .btn-action { - margin: 0px 3px 3px 0px; - display: inline-block; - } -} - -.btn-fixed-width { - .btn-icon { - min-width: 100px; - - &.propagte-classification { - >span { - width: 98px; - } - } - - >span { - @include ellipsis(); - float: left; - width: 76px; - padding: 2px 5px !important; - } - - >i { - float: right; - line-height: 15px; - } - } -} - -.btn-action { - @extend .btn-atlas; - @include btn-action-effect('default'); - border-radius: 4px; - font-size: 14px; - background-color: $transparent; - - &.active { - @include btn-action-hover-effect('default'); - } - - &:hover { - @include btn-action-hover-effect('default'); - color: $white !important; - } - - &:focus { - @include btn-action-effect('default'); - } - - &.btn-sm { - padding: 2px 6px; - } - - &.btn-xs { - padding: 0px 5px; - } - - &.btn-md { - padding: 5px 10px; - } - - &.btn-blue { - @include btn-action-effect('blue'); - - &.active { - @include btn-action-hover-effect('blue'); - } - - &:hover { - @include btn-action-hover-effect('blue'); - } - - &:focus { - @include btn-action-effect('blue'); - } - - &.btn-icon { - @include btn-action-effect('blue'); - color: $tag_color !important; - - &:hover { - color: $color_havelock_blue_approx; - background-color: $transparent; - } - - >span { - &:hover { - @include btn-action-hover-effect('blue'); - } - } - - i.fa { - &:hover { - @include btn-action-hover-effect('blue'); - } - } - } - } - - &.btn-disabled { - border: 1px $action_gray solid; - color: $action_gray; - cursor: default; - - i.fa { - position: relative; - right: -5px; - } - - &:hover { - color: $white; - background-color: $action_gray; - } - } - - &.btn-icon { - padding: 0px; - overflow: hidden; - background-color: $transparent; - - &:hover { - color: $color_keppel_approx; - background-color: $transparent; - } - - >span { - padding: 5px; - - &.active { - color: $white; - background-color: $tag_color; - } - - &:hover { - @include btn-action-hover-effect('default'); - } - } - - i.fa { - position: relative; - padding: 5px; - cursor: pointer; - - &:hover { - @include btn-action-hover-effect('default'); - } - } - } - - &.btn-icon-pd { - i.fa { - padding: 5px; - cursor: pointer; - } - } -} - -.btn-group { - - .btn-atlas, - .btn-action { - margin: 0px; - } - - &.no-border-button { - .btn { - font-size: 15px; - line-height: 15px; - padding: 8px 20px; - - &:not(:last-child) { - border: 0px; - border-right: 1px solid; - } - } - - } -} - - -.pagination>.active { - >a { - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - - &:focus { - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - } - - &:hover { - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - } - } - - >span { - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - - &:focus { - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - } - - &:hover { - background-color: $color_curious_blue_approx; - border-color: $color_curious_blue_approx; - } - } -} - -.deleteBtn { - border-color: $color_mountain_mist_approx; - color: $color_mountain_mist_approx; - cursor: default; - margin: 0px 10px; - - &:hover { - border-color: $color_mountain_mist_approx; - color: $color_mountain_mist_approx !important; - background-color: $transparent; - } - - &:focus { - border-color: $color_mountain_mist_approx; - color: $color_mountain_mist_approx; - background-color: $transparent; - } -} - -.block { - display: block !important; -} - -.list-style-disc { - list-style: disc; -} - -.has-feedback.align-left { - .form-control { - padding-left: 32.5px; - padding-right: 12px; - } - - .form-control-feedback { - top: 10px; - left: 0px; - height: 14px - } -} - -.has-feedback.align-left-right-icon { - position: relative; - - .form-control.icon-input { - padding-left: 32.5px; - padding-right: 61px; - } - - .icon-group { - right: 0px; - //overflow: hidden; - position: absolute; - top: 50%; - width: 56px; - } - - .form-control-feedback { - top: calc(50% - 7px); - height: 14px; - width: 28px; - - &:first-child { - left: 0; - } - - &.clearable { - overflow: hidden; - padding-left: 35px; - transition: padding 0.4s; - pointer-events: all; - cursor: pointer; - - &.in { - padding-left: 0; - } - - } - } -} - -.create-entity-form { - &.all { - .attribute-dash-box { - &.alloptional { - display: block; - } - } - } - - .attribute-dash-box { - border-style: dashed; - border-width: 2px; - border-spacing: 8px; - border-radius: 12px; - border-color: $attribute-dash-box; - position: relative; - padding: 18px 10px 0px 10px; - margin-top: 25px; - - span.required:after { - content: "*"; - padding-left: 1%; - color: $red; - } - - &.alloptional { - display: none; - } - - .attribute-type-label { - background: $white; - padding: 5px 10px; - position: absolute; - top: -16px; - } - } -} - -.parent-node .tagActions { - display: none; - position: absolute; - right: 0px; - - .listTerm { - display: inline-block; - margin: 5px; - } - - .listTerm a { - - color: #686868; - } -} - -/* clears the 'X' from Internet Explorer */ -input[type=text]::-ms-clear { - display: none; - width: 0; - height: 0; -} - -input[type=text]::-ms-reveal { - display: none; - width: 0; - height: 0; -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/glossary.scss b/dashboardv3/public/css/scss/glossary.scss deleted file mode 100644 index 9f044e96dc8..00000000000 --- a/dashboardv3/public/css/scss/glossary.scss +++ /dev/null @@ -1,72 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -.jstree-contextmenu { - z-index: 99; -} - -.jstree-default-dark { - background: transparent !important; - - .jstree-anchor { - width: calc(100% - 50px); - overflow: hidden; - text-overflow: ellipsis; - } - - .jstree-children.jstree-children>li>a { - max-width: 500px; - } - - .jstree-clicked, - .jstree-wholerow-clicked { - background: $color_jungle_green_approx !important; - } - - .jstree-custom-filter { - background: #beebff !important; - } - - .jstree-hovered { - background: $color_star_dust_approx; - } - - .jstree-anchor { - color: #dbdbdb; - } - - .jstree-search { - color: #fbfece !important - } - - li[role="treeitem"] { - .jstree-wholerow-clicked { - .tools { - display: inline-block; - } - } - - .tools { - display: none; - position: absolute; - width: 30px; - text-align: center; - cursor: pointer; - top: 0; - right: 0; - } - } -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/graph.scss b/dashboardv3/public/css/scss/graph.scss deleted file mode 100644 index 519dc6d201e..00000000000 --- a/dashboardv3/public/css/scss/graph.scss +++ /dev/null @@ -1,358 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* graph.scss */ -.invisible { - .node circle { - transition: all 0s; - } -} - -.graph-toolbar { - background-color: $white; - margin-bottom: 10px; - padding: 10px; -} - -.legends { - >i { - >span { - font-family: "Source Sans Pro"; - } - } -} - -.lineage-box { - position: absolute; - height: 100%; - width: 100%; - overflow: hidden; -} - -.graph-button-group { - &>div { - display: inline-block; - } - - .zoom-button-group {} -} - -.box-panel { - position: absolute; - top: 37px; - border: 1px solid #ccc; - width: 250px; - max-height: 99%; - overflow: auto; - transition: all 0.3s ease; - right: -273px; - background-color: $white; - z-index: 999; - box-shadow: 1px 19px 22px -17px; - border-radius: 10px; - max-height: 88%; - - &.slide-from-left { - left: -273px; - right: 0px; - - &.size-lg { - left: -373px; - } - } - - &.size-lg { - width: 350px; - } - - &.show-box-panel { - right: 0px !important; - - &.slide-from-left { - left: 0; - } - } - - .entity-list { - overflow: auto; - list-style-type: decimal; - list-style-position: outside; - padding-left: 15px; - } - - ul>li { - word-wrap: break-word; - margin-bottom: 5px; - text-align: left; - - &.deleted-relation { - - .deleteBtn { - padding: 2px 8px !important; - margin: 5px 5px !important; - } - } - } - - - .header { - background: $color_havelock_blue_approx; - color: white; - position: relative; - text-align: center; - width: 100%; - position: sticky; - height: 37px; - top: 0; - z-index: 999; - - >h4 { - padding: 0px 36px 0px 10px; - word-break: break-all; - } - - .btn-close { - position: absolute; - right: 0px; - top: 0px; - font-size: 18px; - - &:hover { - color: $white; - } - } - } - - .body { - padding: 10px; - width: 100%; - position: relative; - height: calc(100% - 37px); - overflow: hidden; - } -} - -.btn-gray { - border: 1px solid #686868; - color: $dark_gray; - background: white; - - &[disabled] { - opacity: .3; - } - - &:hover { - border: 1px solid #686868; - color: $dark_gray !important; - background-color: white !important; - } -} - -span#zoom_in { - border-bottom: 1px solid #625555; -} - -.depth-container { - - //display: inline-block; - //margin-top: 3px; - .inline { - display: inline-block; - } -} - -.resizeGraph { - position: relative; - width: 100%; - height: 64vh; - overflow: hidden !important; - - &.auto-height { - height: auto !important; - } -} - -.active.fullscreen-mode { - position: fixed !important; - height: 100% !important; - top: 0; - bottom: 0; - left: 0; - width: 100%; - right: 0; - padding: 0 !important; - z-index: 99; - overflow: hidden !important; - background: white; - - .systemTypeTree { - height: 100vh !important; - padding: 10px; - } - - .resizeGraph { - position: fixed; - height: 100% !important; - - .ui-resizable-handle { - display: none; - } - } - - .lineage-box { - padding: 10px !important; - } - - .box-panel { - margin: 10px !important; - } -} - -.lineage-node-detail { - .table-quickMenu { - td:nth-child(1n) { - width: 150px; - } - - word-break: break-all; - } -} - -.hidden-svg { - visibility: hidden; -} - -#tab-relationship { - - .entity-status { - &.active { - color: $color_jungle_green_approx; - } - - &.deleted { - color: $delete_link; - } - - } - - .entity-list { - list-style-position: inside; - - } -} - -@-webkit-keyframes blink { - from { - opacity: 0.2; - } - - to { - opacity: 0.5; - } -} - -.mini-map-type-system { - background: white; - width: 200px; - position: absolute; - bottom: 5px; - right: 5px; - - &>svg { - box-shadow: 0px 0px 3px 1px #80808080; - } - -} - - -.box-panel.fix-box { - position: absolute; - top: 37px; - right: 0; - bottom: 0; - height: auto; - max-height: initial; - z-index: 999; - bottom: 0; - width: 400px; - overflow: hidden; - border-radius: 10px; - margin: 0 !important; - - &.slide-from-right.size-lg { - right: -413px; - - &.show-box-panel { - right: 0px; - } - } - - .body { - - position: relative; - - table{ - position: relative; - height: 100%; - } - tbody { - overflow: auto; - height: auto; - display: block; - position: absolute; - padding-bottom: 15px; - } - } -} - -.profile-bar { - fill: #38bb9b; - stroke: #38bb9b; - fill-opacity: 0.75; -} - -.axislabel { - text-anchor: middle; - fill: #999; - font: 400 12px Arial, sans-serif; -} - -.grid { - - path, - line { - stroke: lightgrey; - stroke-opacity: 0.7; - shape-rendering: crispEdges; - } -} - -.d3-tip { - table td { - padding: 2px 9px 2px 0; - vertical-align: middle; - - &.value { - text-align: right; - font-weight: 700; - } - - &.key { - font-weight: 400; - } - } -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/leftsidebar.scss b/dashboardv3/public/css/scss/leftsidebar.scss deleted file mode 100644 index 68a6f79a132..00000000000 --- a/dashboardv3/public/css/scss/leftsidebar.scss +++ /dev/null @@ -1,452 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -.filter-tree-box { - padding-left: 2px; - - .panel { - border: none; - box-shadow: none; - - &.panel-default>.panel-heading { - border-color: $color_mystic_approx; - border-width: 2px; - min-width: 222px; - - button { - height: inherit; - } - } - - .menu-items { - height: 30px; - } - - &.expand_collapse_panel-icon { - .panel-heading { - i.ec-icon:before { - content: "\f054"; - } - - &[aria-expanded="true"] { - i.ec-icon:before { - content: "\f078"; - } - } - } - } - - .dropdown-toggle { - width: 15px; - } - } - - // .remove-drop-down { - // .drop-down-menu-view { - // display: inline-block; - // } - - // .show-in-drop-down { - // display: none; - // } - // } - - // .add-drop-down { - // .drop-down-menu-view { - // display: none; - // } - - // .show-in-drop-down { - // display: block; - // } - // } - - .filter-tree-content { - overflow: auto; - height: calc(100vh - 188px); - - .panel-collapse { - padding-top: 7px; - } - - .jstree-anchor { - line-height: 26px; - height: 26px; - font-size: 16px; - // max-width: 96%; - width: calc(100% - 50px); - overflow: hidden; - text-overflow: ellipsis; - } - - .jstree-default .jstree-node { - position: relative; - max-width: 100%; - } - - .tag-tree>li.parent-node>div:hover { - background-color: $color_havelock_blue_approx; - color: #fff !important; - } - - .jstree-with-action { - .jstree-default { - .tools { - display: none; - position: absolute; - text-align: center; - cursor: pointer; - right: 0; - top: 0; - color: $white; - background: $color_havelock_blue_approx; - - i { - width: 30px; - } - } - - li[aria-selected="true"] { - &>.jstree-wholerow { - width: calc(100% - 30px); - } - - &>.tools { - display: inline-block; - top: 0px; - } - } - } - } - - .jstree-default { - .jstree-search { - font-style: unset; - color: inherit; - font-weight: 700; - } - - .jstree-anchor { - line-height: 26px; - height: 26px; - font-size: 16px; - - &.jstree-clicked { - color: $white; - - i { - -webkit-text-stroke-color: $white; - } - } - } - - &>.jstree-no-dots .jstree-open>.jstree-ocl { - transform: rotate(45deg); - } - - .jstree-wholerow-clicked { - background: $color_havelock_blue_approx; - color: $white; - } - } - - .panel-heading { - cursor: pointer; - } - - .basicSaveSearch { - .clearfix { - .btn { - display: none; - } - } - } - - .fa.fa-tag { - color: transparent; - -webkit-text-stroke-width: 1px; - -webkit-text-stroke-color: #686868; - } - - .tree-menu { - padding: 5px; - cursor: pointer; - color: #686868; - } - - .dropdown-menu { - min-width: 182px; - left: -170px; - - &>li { - padding: 3px 15px; - - &:focus, - &:hover { - background-color: $color_havelock_blue_approx; - color: #fff !important; - - a { - background-color: $color_havelock_blue_approx; - color: #fff !important; - } - - span { - color: #fff !important; - } - - .clear-icon { - color: $color_ironside_gray_approx !important; - } - - .wildcard-btn { - color: $color_jungle_green_approx !important; - } - } - - .wildcard-btn { - margin: 0px; - color: $color_jungle_green_approx !important; - } - - .wildcard-btn:hover { - margin: 0px; - color: $white !important; - } - - input { - color: $color_ironside_gray_approx !important; - width: 130px; - display: inline-block; - } - - input:hover { - background-color: #fff; - } - - - .clear-icon { - color: $color_ironside_gray_approx !important; - } - - a { - display: inline-block; - padding: 0px 3px; - } - - span { - color: #686868; - margin-left: 10px; - } - } - - .disable-list-option { - - &, - &:focus, - &:hover * { - background-color: transparent !important; - color: $gray !important; - cursor: not-allowed; - } - } - - .clear-icon { - color: $color_ironside_gray_approx !important; - position: absolute; - z-index: 3; - top: 29%; - right: 48px; - } - - .has-feedback input { - padding: 6px 25px 6px 6px; - - } - - .has-feedback input:focus { - border-color: $color_havelock_blue_approx !important; - - } - - .wildcard-search:hover { - background-color: $white; - } - } - - .hide-icon { - display: none; - } - - .custom-filter { - .fa-circle-thin:after { - font-family: Source Sans Pro, sans-serif; - position: absolute; - left: 0px; - margin-left: 9px; - font-size: 11px; - font-weight: bold; - } - - .advance-tree:after { - content: "A"; - } - - .basic-tree:after { - content: "B"; - } - } - - .switch-button { - transform: rotate(180deg); - } - - .group-tree-deactivate { - color: $action_gray; - } - } -} - -.sidebar-content { - &:hover { - .slider-bar button { - display: block; - opacity: 1; - } - } -} - -.slide-in { - #sidebar-wrapper { - width: 40px; - background: $white; - - .sidebar-content { - .search-browse-box { - border-left: none; - - &>div { - visibility: hidden; - } - - .slider-bar { - visibility: visible; - - button { - display: block; - opacity: 1; - - i:before { - content: "\f0c9"; - } - } - } - } - } - } - - #page-wrapper { - width: calc(100% - 45px); - margin-left: 45px; - } -} - -.search-browse-box { - overflow: hidden; - padding: 0; - border-left: 1px solid $color_mystic_approx; - - .slider-bar { - position: absolute; - right: 0px; - height: 100%; - width: 13px; - cursor: col-resize; - z-index: 999; - background: $white; - - .line { - position: absolute; - height: 100%; - background: $color_mystic_approx; - left: -2px; - width: 2px; - } - - &:hover { - .line { - background-color: $color_havelock_blue_approx; - } - - button { - display: block; - - &:hover { - background-color: $color_havelock_blue_approx; - color: $white; - } - } - } - - button { - background-color: $white; - position: absolute; - color: $color_havelock_blue_approx; - right: 0px; - border-radius: 16px; - display: none; - top: 9px; - border-color: $color_havelock_blue_approx; - background: white; - padding: 2px 7px; - opacity: 0; - transition: 0.3s linear; - border: 2px solid $color_havelock_blue_approx; - } - } -} - -span.tree-tooltip { - position: fixed; - display: none; - top: calc(346px - 39px); - left: 138px; - z-index: 1004; - background: #f9f9f9; - color: #2c2c2c; - padding: 5px; - height: 36px; - box-shadow: 0px 0px 3px 0px #8080806b; - border: 1px solid #80808057; - border-radius: 9px; - - &.show { - display: block; - } -} - -.tree-droupdown { - left: -190px !important; - width: 218px; - - span a { - padding: 0px !important; - - span { - margin-left: 0px !important; - } - } -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/loader.scss b/dashboardv3/public/css/scss/loader.scss deleted file mode 100644 index 1773324247c..00000000000 --- a/dashboardv3/public/css/scss/loader.scss +++ /dev/null @@ -1,205 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -/* loader.scss */ - -.fa-spin-custom { - animation: spin 1000ms infinite linear; -} - -@-webkit-keyframes spin { - 0% { - //Instead of the line below you could use @include transform($scale, $rotate, $transx, $transy, $skewx, $skewy, $originx, $originy) - transform: rotate(0deg); - } - - 100% { - //Instead of the line below you could use @include transform($scale, $rotate, $transx, $transy, $skewx, $skewy, $originx, $originy) - transform: rotate(359deg); - } -} - -@keyframes spin { - 0% { - //Instead of the line below you could use @include transform($scale, $rotate, $transx, $transy, $skewx, $skewy, $originx, $originy) - transform: rotate(0deg); - } - - 100% { - //Instead of the line below you could use @include transform($scale, $rotate, $transx, $transy, $skewx, $skewy, $originx, $originy) - transform: rotate(359deg); - } -} - -.contentLoading { - position: absolute; - background: rgba(247, 247, 247, 0.24); - top: 0; - right: 0; - left: 0; - z-index: 99; - bottom: 0; - display: none; -} - -.fontLoader { - top: 50%; - left: 50%; - position: absolute; - display: none; -} - -.fontLoader-relative { - @extend .fontLoader; - position: relative; - left: 0%; - text-align: center; -} - -.initialLoading { - position: fixed; - top: 0; - right: 0; - left: 0; - bottom: 0; - background: url("../img/ring.gif") no-repeat; - background-position: 50% 50%; - background-size: 60px; -} - -.tableOverlay { - position: absolute; - width: 100%; - height: 100%; - background: $gray; - z-index: 99; - display: none; - opacity: 0.2; -} - -.value-loader { - height: 4px; - width: 50%; - position: relative; - overflow: hidden; - background-color: #ddd; -} - -.value-loader:before { - display: block; - position: absolute; - content: ""; - left: -200px; - width: 200px; - height: 4px; - background-color: #2980b9; - animation: value-loader 2s linear infinite; -} - -@keyframes value-loader { - from { - left: -200px; - width: 30%; - } - - 50% { - width: 30%; - } - - 70% { - width: 70%; - } - - 80% { - left: 50%; - } - - 95% { - left: 120%; - } - - to { - left: 100%; - } -} - -.searchTableLogoLoader { - width: 20px; - -webkit-animation-duration: 1.5s; - animation-duration: 1.5s; - -webkit-animation-fill-mode: forwards; - animation-fill-mode: forwards; - -webkit-animation-iteration-count: infinite; - animation-iteration-count: infinite; - -webkit-animation-timing-function: linear; - animation-timing-function: linear; - -webkit-animation-name: placeHolderLoader; - animation-name: placeHolderLoader; - background: #f6f7f8; - background: linear-gradient(to right, #eeeeee 8%, #dddddd 18%, #eeeeee 33%); - background-size: 700px 10px; - border-radius: 8px; - outline: 1px #fff solid; - outline-offset: -1px; -} - -@keyframes placeHolderLoader { - 0% { - background-position: -468px 0; - } - - 100% { - background-position: 468px 0; - } -} - -.loader-row .fontLoader-relative { - margin-top: 43px; -} - -.module-loader { - position: fixed; - top: 0; - height: 2px; - z-index: 9999; - background: repeating-linear-gradient(to right, $color_jungle_green_approx 0%, $color_havelock_blue_approx 50%, #38bb4e 100%); - width: 100%; - background-size: 200% auto; - background-position: 0 100%; - animation: moduleLoader 2s infinite; - animation-fill-mode: forwards; - animation-timing-function: linear; - transition: all 2s linear; - visibility: hidden; - opacity: 0; - transition: visibility 0s linear 0.33s, opacity 0.33s linear; - - &.show-loader { - opacity: 1; - transition-delay: 0s; - visibility: visible; - } -} - -@keyframes moduleLoader { - 0% { - background-position: 0 0; - } - - 100% { - background-position: -200% 0; - } -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/login.scss b/dashboardv3/public/css/scss/login.scss deleted file mode 100644 index d4dba17f1c9..00000000000 --- a/dashboardv3/public/css/scss/login.scss +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -@import "__variable.scss"; - -body { - font-family: $font_0, $font_1; - background-color: $color_white_lilac_approx; - color: $color_dark_grey_approx; - font-size: 14px; - line-height: 1.42857143; -} - -.login-body { - height: 100vh; - padding-top: calc(50vh - 206px); - - .login-form { - padding: 60px; - width: 500px; - margin: 0 auto; - background: $white; - box-shadow: 0px 0px 3px 0px rgba(128, 128, 128, 0.2); - - h4 { - font-size: 16px; - margin-bottom: 24px; - } - - img { - height: 65px; - padding: 6px; - margin-bottom: 28px; - } - - .icon-group { - position: relative; - margin-bottom: 24px; - - &.user:after { - content: "\f007"; - } - - &.password:after { - content: "\f023"; - } - - .show-password, - &:after { - position: absolute; - left: 4px; - bottom: 4px; - font-family: FontAwesome; - font-size: 16px; - background: transparent; - height: 34px; - width: 38px; - line-height: 34px; - text-align: center; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; - border-right: 1px solid #ccc; - } - - &.text { - .show-password { - color: $color_jungle_green_approx; - } - } - - .show-password { - right: 4px; - border: none; - left: auto; - cursor: pointer; - } - - input { - height: auto; - padding: 10px 12px 10px 52px; - background: transparent; - border-radius: 0px; - border-width: 1px; - - &#password { - padding-right: 37px - } - - &:focus { - border-image-source: #38bb9b; - border-width: 2px; - border-image-slice: 5; - border-image-source: -moz-linear-gradient(-45deg, #38bb9b 0%, #4a90e2 100%); - border-image-source: -webkit-linear-gradient(-45deg, #38bb9b 0%, #4a90e2 100%); - border-image-source: linear-gradient(135deg, #38bb9b 0%, #4a90e2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#38bb9b', endColorstr='#4a90e2', GradientType=1); - box-shadow: none; - -webkit-box-shadow: none; - } - } - } - - button.btn-login { - padding: 10px 12px; - background: #38bb9b; - background: -moz-linear-gradient(-45deg, #38bb9b 0%, #4a90e2 100%); - background: -webkit-linear-gradient(-45deg, #38bb9b 0%, #4a90e2 100%); - background: linear-gradient(135deg, #38bb9b 0%, #4a90e2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#38bb9b', endColorstr='#4a90e2', GradientType=1); - color: #fff; - margin-top: 32px; - border: none; - - &:focus, - &:hover, - &:active, - &:active:focus, - &:active:hover { - background: #38bb9b; - background: -moz-linear-gradient(-45deg, #38bb9b 0%, #4a90e2 100%); - background: -webkit-linear-gradient(-45deg, #38bb9b 0%, #4a90e2 100%); - background: linear-gradient(135deg, #38bb9b 0%, #4a90e2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#38bb9b', endColorstr='#4a90e2', GradientType=1); - color: #fff; - } - } - } -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/nav.scss b/dashboardv3/public/css/scss/nav.scss deleted file mode 100644 index 6cb81a42db6..00000000000 --- a/dashboardv3/public/css/scss/nav.scss +++ /dev/null @@ -1,73 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -/* nav.scss */ - -.navbar-atlas { - background-color: $color_tuna_approx; //Instead of the line below you could use @include box-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - box-shadow: inset 0 0 0 $black_10, 0 1px 10px $black_10; - - .navbar-brand { - color: $white; - } - - .nav>li>a { - color: $white; - padding-top: 18px; - padding-bottom: 18px; - font-size: 100%; - - &:focus { - background-color: transparent; - } - - &:hover { - background-color: transparent; - } - } -} - -.navbar-toggle .icon-bar { - background-color: $white; -} - -.navbar-fixed-top+.wrapper { - margin-top: 90px; - padding-bottom: 90px; -} - -.navbar-brand { - font-size: 30px; - height: auto; -} - -.navbar-form { - width: 30%; - padding: 0; - - .form-control { - width: 100%; - padding: 6px 0; - background-color: transparent; - color: $white; - border: none; //Instead of the line below you could use @include box-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - box-shadow: 0 2px $white; - } -} - -.navbar-nav>li>a { - padding: 15px 10px; -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/old-style.scss b/dashboardv3/public/css/scss/old-style.scss deleted file mode 100644 index c37b86ae6ea..00000000000 --- a/dashboardv3/public/css/scss/old-style.scss +++ /dev/null @@ -1,102 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* old-style.scss */ - -//@extend-elements -//original selectors -//.inputs button.addAttr, .inputs button.saveAttr -%extend_1 { - height: 40px; //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 4px; - border: 1px solid $white; - color: $white; //Instead of the line below you could use @include text-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - text-shadow: 0 -1px 0 $black_25; - font-weight: bold; -} - -.row-margin-bottom { - margin-bottom: 15px; -} - -.list-group-item { - &:first-child { - //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 0; - } - - &:last-child { - //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 0; - } -} - -.h160 { - height: 160px !important; -} - -.subContent { - width: 500px; - margin: 30px; -} - -.headerDroupDown { - border-left: 1px solid $white; - font-size: 11px; - padding-left: 15px; - margin-left: 15px; -} - -.scrollTagList { - height: 330px; - overflow-y: auto; - margin-bottom: 0; - - i.fa { - margin-right: 5px; - } -} - -.menuItem { - padding: 10px; - color: $color_havelock_blue_approx; - cursor: pointer; -} - -.tagging { - display: inline-block; -} - -.crossClearText { - line-height: 20px !important; -} - -text { - font-weight: 300; - font-family: $font_2, $font_3, $font_4, $font_5; - font-size: 14px; -} - -.switch-blue .switch-selection { - background: $color_pelorous_approx; - background-image: linear-gradient(to bottom, $color_picton_blue_approx, $color_pelorous_approx); -} - -.switch-yellow .switch-selection { - background: $color_laser_approx; - background-image: linear-gradient(to bottom, $color_zombie_approx, $color_laser_approx); -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/override.scss b/dashboardv3/public/css/scss/override.scss deleted file mode 100644 index fb3604d9224..00000000000 --- a/dashboardv3/public/css/scss/override.scss +++ /dev/null @@ -1,606 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* override.scss */ -.container-fluid { - padding-left: 0px; - padding-right: 4px; -} - -.tabs li.tab.active { - border-bottom: 2px solid $color_keppel_approx; - - a { - color: $color_keppel_approx; - } -} - -.modal-header { - padding: 15px; - border-bottom: 1px solid #DEDEDE; - - .header-button { - float: right; - opacity: .2; - color: $black; - margin-top: -2px; - - &:hover { - color: $black; - text-decoration: none; - cursor: pointer; - filter: alpha(opacity=50); - opacity: .5; - } - } -} - -.modal-title { - font-weight: 600; - -webkit-font-smoothing: antialiased; -} - -.modal-footer { - padding: 15px; - text-align: right; - border-top: 1px solid #DEDEDE; - - .btn+.btn { - margin-bottom: 0; - } -} - -.modal-body { - position: relative; - padding: 15px; - max-height: calc(100vh - 215px); - min-height: 70px; - overflow: auto; - - .btn+.btn { - margin-bottom: 2px; - } - - .admin-audit-details { - border: 1px solid #ddd; - border-radius: 4px; - - tr>td:nth-child(2) { - text-align: right; - } - } - - .tree-container { - max-height: 140px; - overflow-y: auto !important; - } -} - -.modal-full-screen { - width: 80%; - height: 80vh; - - .modal-content { - width: 100%; - } - -} - -.switch.pull-left { - margin-right: 8px; -} - -.modal-content { - border-radius: 10px; -} - - -.select2-container { - width: 100% !important; -} - -.select2-mini { - - .select2-container .select2-selection--single, - .select2-container .select2-selection--multiple { - min-height: 28px; - } - - .select2-container--default .select2-selection--single { - .select2-selection__rendered { - line-height: 28px; - font-size: 13px; - } - - .select2-selection__arrow { - height: 28px; - } - - } -} - -.select2-container--default { - &.select2-container--disabled { - .select2-selection--multiple { - background-color: $color_gallery_approx !important; - cursor: not-allowed; - - input.select2-search__field { - cursor: not-allowed; - } - } - } - - .select2-selection--multiple { - - background-color: $color_white_lilac_approx !important; - border: 1px $color_mystic_approx solid !important; - - &.errorClass { - border: 1px solid red !important; - } - } - - .select2-selection--single { - .select2-selection__arrow { - height: 34px; - } - - .select2-selection__rendered { - line-height: 32px; - font-size: 14px; - } - } - - &.select2-container--focus .select2-selection--multiple { - border-color: $color_bali_hai_approx !important; - } -} - -.select2-container { - - .select2-selection--single, - .select2-selection--multiple { - min-height: 34px; - - .select2-selection__rendered { - padding-left: 12px; - } - } -} - -.select2-container--default .select2-selection--multiple .select2-selection__choice { - background-color: $white; - color: $color_mountain_mist_approx; - border: 1px solid $tag_color; -} - -.select2-container--default .select2-search--inline .select2-search__field { - color: #555; - // width: 300px !important; -} - -.typeLOV { - .select2-container--default { - .select2-selection--multiple { - .select2-selection__rendered { - padding-right: 13px; - - .select2-selection__choice { - font-size: 14px; - color: $color_mountain_mist_approx; - border: 1px solid $color_mountain_mist_approx; - } - - .select2-search__field { - font-size: 14px; - } - } - - .select2-selection__clear { - position: absolute; - float: none; - margin: 0px; - right: 4px; - top: 5px; - color: $color_mountain_mist_approx; - } - } - } -} - -.fixed-popover { - position: fixed; -} - -.popover.fade { - -webkit-transition: ease-in .1s ease-out; - -o-transition: ease-in .1s ease-out; - transition: ease-in .1s ease-out; -} - -.pager { - margin: 0px; -} - -.popover { - z-index: 1000; -} - -.popover-content { - max-height: 150px; - overflow: auto; - - ul { - color: $dark_gray; - padding: 0px 5px; - margin-bottom: 0px; - cursor: pointer; - - a { - color: $dark_gray; - padding: 5px; - } - } -} - -.tab-content>.tab-pane.active { - overflow-x: hidden; - overflow: initial; -} - -.advancedInfo { - margin-left: 5px; - cursor: pointer; -} - -.query-builder { - .rule-container { - margin: 6px 0; - display: flex; - flex-wrap: wrap; - - .values-box { - display: flex; - flex-grow: 1; - width: 100%; - padding-right: 26px; - } - - .action-box { - position: absolute; - right: 4px; - top: calc(50% - 18px); - } - - .rule-header { - .rule-actions { - padding: 7px 0px; - } - } - - .error-container { - color: $color_trinidad_approx; - } - - .rule-value-container { - display: inline-block !important; - border-left: none; - width: calc(65% - 105px); - - .form-control { - width: 100% !important; - padding: 6px 12px !important; - } - } - - .rule-filter-container { - width: 35%; - - .form-control { - width: 100% !important; - } - } - - .rule-operator-container { - width: 150px; - - .form-control { - width: 100% !important; - } - } - } - - .rules-list>:first-child::before { - top: -8px; - } - - .rules-group-container { - border-color: transparent; - background: none; - - .rules-group-header { - .group-actions { - .btn-success { - color: #38BB9B !important; - background-color: transparent !important; - border-color: #38BB9B !important; - } - - .btn-danger { - color: #e14f00; - background-color: transparent; - border-color: #e14f00; - } - } - - .group-conditions { - .btn-primary { - color: #333 !important; - background-color: $white !important; - border-color: #ccc !important; - } - - .active { - color: $white !important; - background-color: #5bc0de !important; - border-color: #46b8da !important; - } - } - } - } - - - .rules-group-header .btn-group.pull-right.group-actions { - float: right !important; - } -} - -div.columnmanager-visibilitycontrol { - width: auto; - margin-bottom: 5px; - - &.open .btn-action { - background-color: $color_keppel_approx; - color: $white; - } -} - -div.columnmanager-dropdown-container { - .columnmanager-dropdown-item { - padding: 2px 13px; - } - - &.open { - overflow: auto; - width: auto; - } - - >li>span.column-label { - width: auto; - } -} - -.stack-modal[aria-role="alertdialog"] { - &.width-600 { - width: 600px !important; - left: calc(50% - 250px) !important; - margin-left: 0 !important; - } - - &.width-500 { - width: 500px !important; - left: calc(50% - 216px) !important; - margin-left: 0 !important; - } - - &.width-400 { - width: 400px !important; - left: calc(50% - 183px); - margin-left: 0 !important; - } - - .alert.ui-pnotify-container { - color: $color_ironside_gray_approx; - background-color: $white; - border: 1px solid rgba(0, 0, 0, .2); - padding: 0px; - outline: 0; - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - - .ui-pnotify-icon, - .ui-pnotify-title { - padding: 15px; - } - - .ui-pnotify-text { - position: relative; - padding: 15px; - max-height: 400px; - min-height: 70px; - overflow: auto; - border-top: 1px solid #DEDEDE; - word-break: break-word; - } - - .ui-pnotify-action-bar { - padding: 15px; - text-align: right; - border-top: 1px solid #DEDEDE; - } - } -} - -.ui-pnotify-icon, -.ui-pnotify-icon span { - padding: 2px 0px; -} - -.btn-round-xs { - border-radius: 11px; - padding-left: 10px; - padding-right: 10px; - background-color: transparent !important; - color: #626467; - border: 1px solid black; -} - -.text-center { - text-align: center !important; -} - -.margin-15 { - margin: 15px 0px; -} - -.padding-left-0 { - padding-left: 0px !important; -} - -.fa-color { - color: $color_keppel_approx -} - -.w30 { - width: 30% !important; -} - -.query-builder .error-container { - cursor: pointer; -} - -.renderable { - .glyphicon { - color: $color_jungle_green_approx; - font-size: large; - font-weight: bold; - } - - .noToggle { - color: $gray; - } -} - -.backgrid-internal-table { - - th, - td { - display: table-cell; - } -} - -.table-hover>tbody>tr:hover { - background-color: #fafafa; -} - -.input-group { - .form-control { - z-index: 1; - } -} - -.ui-pnotify-container { - .ui-pnotify-text { - word-break: break-word; - } -} - -.jstree-wholerow-ul { - width: 100%; - - .jstree-anchor { - width: calc(100% - 50px); - overflow: hidden; - text-overflow: ellipsis; - } -} - -.modal { - position: absolute; -} - -.modal-open { - overflow-y: auto; -} - -.daterangepicker { - - .ranges { - max-height: 328px; - overflow: auto; - } - - .ranges li.active, - td.active { - background-color: $color_havelock_blue_approx; - } - - .drp-buttons { - .applyBtn { - background-color: $color_havelock_blue_approx; - border-color: $color_havelock_blue_approx; - } - } -} - -.dropzone .dz-preview .dz-details .dz-filename { - padding-top: 20px; -} - -.select2-container--default .select2-search--inline .select2-search__field { - width: 100% !important; -} - -.tooltip-inner>div { - max-width: 250px; - text-align: left; - - ul { - list-style: disc; - } -} - -.ideal-timeout { - .modal-content { - border-radius: 0px !important; - } -} - -.typeFilter-container { - width: 100%; - - .typeFilter { - width: calc(100% - 45px); - display: inline-block; - } -} - -.refreshBtn-container { - display: inline-block; - position: absolute; - padding-left: 8px; - - .btn-action { - margin: 0px !important; - font-size: 15px; - } -} - -.user-circle { - display: inline; -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/panel.scss b/dashboardv3/public/css/scss/panel.scss deleted file mode 100644 index 66adc2689a8..00000000000 --- a/dashboardv3/public/css/scss/panel.scss +++ /dev/null @@ -1,175 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* panel.scss */ - -.panel-default { - >.panel-heading { - color: $color_jungle_green_approx; - background: $white; - border-color: $color_jungle_green_approx; - - &.dash-button-icon { - button:not(:last-child) { - border-right: 1px solid $color_jungle_green_approx; - } - } - - button { - color: $color_jungle_green_approx; - background: $white; - border: none; - } - - .panel-title { - font-weight: bold; - padding-top: 6px; - } - } - - .nav-tabs { - >li { - &.active { - >a { - color: $color_jungle_green_approx; - } - } - - >a { - color: $black; - } - } - } -} - -.panel-fullscreen { - .panel-body { - //overflow: hidden; - height: calc(100% - 46px) !important; - } - - .ui-resizable-handle { - display: none !important; - } -} - -.nav-tabs { - >li { - &:first-child { - margin-left: 25px; - } - } -} - -.with-nav-tabs { - .tab-content { - >.tab-pane { - &>div { - position: relative; - } - - &.active { - padding: 20px 10px 0px 10px; - min-height: 50px; - } - } - } -} - -.panel-fullscreen { - position: fixed; - height: 100%; - top: 0px; - bottom: 0; - left: 0; - width: 100%; - right: 0; - z-index: 999; -} - - - -.panel { - &.right-icons { - .panel-heading { - padding: 5px 0px; - } - } - - &.expand_collapse_panel-icon { - .panel-heading { - .panel-title { - display: inline-block; - } - - i.ec-icon:before { - content: "\f054" - } - - &.collapsed, - &[aria-expanded="false"] { - i.ec-icon:before { - content: "\f054" - } - } - - &[aria-expanded="true"] { - i.ec-icon:before { - content: "\f078" - } - } - } - } -} - -.panel-default.custom-panel>.panel-heading { - color: $color_jungle_green_approx; - cursor: pointer; - border-bottom: none; - display: inline-block; - - .panel-title { - font-weight: normal; - - a:hover { - color: $color_jungle_green_approx; - opacity: 0.7; - } - } - - .btn-group { - margin-top: 4px; - } -} - -.panel-default.custom-panel>.panel-actions { - float: right; - margin-top: 15px; - margin-right: 10px; - - button { - margin-top: -4px; - } -} - -.panel-default.custom-panel>.panel-collapse>.panel-body { - border-top: none; -} - -.panel-default.custom-panel>.panel-heading>.btn-group>button { - color: $color_jungle_green_approx; -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/profile-table.scss b/dashboardv3/public/css/scss/profile-table.scss deleted file mode 100644 index 598af2ed360..00000000000 --- a/dashboardv3/public/css/scss/profile-table.scss +++ /dev/null @@ -1,72 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* Profile Tab css */ - -.graphkey { - font-size: 12px; - color: $action_gray; -} - -.graphval { - font-size: 15px; - - .value-loader { - top: 10px; - } -} - -.nv-axislabel { - fill: $action_gray; -} - -.profileGraphDetail hr { - margin: 3px; -} - -svg.dateType .nv-bar { - cursor: pointer; -} - -.jqstooltip { - height: auto !important; - width: auto !important; -} - -.progress.cstm_progress { - margin-bottom: 0px; - - .progress-bar-success.cstm_success-bar { - background-color: $color_jungle_green_approx; - } - - .progress-bar-success.cstm_success-bar:hover { - background-color: $color_puerto_rico_approx; - } -} - -th.renderable.nonNullData { - a { - text-align: center; - } -} - -.profileGraphDetail>div div { - text-align: right; - white-space: nowrap; - @include ellipsis(); -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/relationship.scss b/dashboardv3/public/css/scss/relationship.scss deleted file mode 100644 index 7bf2560725c..00000000000 --- a/dashboardv3/public/css/scss/relationship.scss +++ /dev/null @@ -1,35 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -.relationship-box, -.lineage-box { - position: absolute; - height: 100%; - width: 100%; - overflow: hidden; - z-index: 1; - - .relatioship-link { - fill: none; - stroke-width: 1.5px; - } -} - -.relationship-node-details { - &.box-panel { - top: 0; - } -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/search.scss b/dashboardv3/public/css/scss/search.scss deleted file mode 100644 index b43848664ad..00000000000 --- a/dashboardv3/public/css/scss/search.scss +++ /dev/null @@ -1,529 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -//colors -$color_celeste_approx: #1D1F2B; - -.switch { - position: relative; - width: 50px; - height: 22px; - margin-left: 8px; - padding: 3px; - vertical-align: top; - border: 1px solid $gray; - border-radius: 18px; - cursor: pointer; -} - -.switch-input { - position: absolute; - top: 0; - left: 0; - opacity: 0; -} - -.switch-slider { - position: absolute; - top: 0px; - left: 3px; - width: 16px; - height: 16px; - border-radius: 10px; - @include transition(left #{$switchTransition}); - - &:before { - content: ''; - position: absolute; - top: 50%; - left: 50%; - margin: -6px 0 0 -8px; - width: 16px; - height: 16px; - background-color: $color_jungle_green_approx; - border-radius: 10px; - @include transition(inherit); - } - - .switch-input:checked~& { - left: 30px; - } -} - -.labelShowRecord { - line-height: 40px; -} - -.srchType { - margin: 5px 0px; - - .srchTitle { - font-size: 14px; - color: $gray; - } -} - -body.ui-autocomplete-small-height { - .ui-menu.ui-widget-content.ui-autocomplete { - max-height: 40%; - } -} - -.default-global-search { - .has-feedback.align-left-right-icon { - .form-control.global-search { - padding-left: 43px; - } - - .form-control-feedback:first-child { - left: 11px; - } - - .icon-group { - right: 11px; - } - } - - .global-search-container { - //width: 50%; - - .searchLayoutView { - top: 50px; - margin: 0 auto; - } - - .global-search { - height: 50px; - } - } -} - -.global-search-active { - overflow: hidden; - - header.atlas-header>table { - td { - &.global-search-container { - z-index: 221; - } - } - } -} - -.global-search-container { - .searchLayoutView { - position: absolute; - z-index: 999; - left: 0; - right: 0; - background: $white; - box-shadow: 0px 1px 5px 0px rgba(128, 128, 128, 0.5); - top: 37px; - padding: 0px 20px; - display: none; - transition: all ease 0.3s; - - &.open { - display: block; - } - } -} - -.search-container { - &.center { - width: 80%; - margin: 30vh auto; - } - - &.top { - animation-fill-mode: backwards; - animation: bottom-top 0.4s ease-in; - } - - .create-entity { - position: absolute; - top: 0px; - right: 0px; - } -} - -// @-webkit-keyframes bottom-top { -// from {top: 0px;} -// to {top: 200px; background-color: blue;} -// } - -@keyframes bottom-top { - from { - margin-top: 20%; - width: 100%; - } - - to { - margin: 0px; - } -} - -.filterQuery { - width: 94%; - display: block; - - &>span { - margin-bottom: 15px !important; - } - - span { - font-size: 15px; - font-weight: bold; - margin: 0px 2px; - float: left; - } - - .key { - color: $color_jungle_green_approx; - } - - .operator { - color: $action_gray; - } - - .value { - color: $tag_color; - } - - .sub-group { - float: left; - - &.show:hover { - background: yellow; - border-radius: 15px; - } - } - - .group { - float: left; - - &.show:hover { - background: rgba(55, 187, 156, 0.2); - border-radius: 15px; - } - } - - .queryContainer { - float: left; - } - - .capsuleView { - padding: 1px 2px; - border: 1px solid; - border-radius: 15px; - display: inline-block; - color: $color_havelock_blue_approx; - margin: 0px 3px; - position: relative; - float: left; - font-size: 6px; - - span { - font-size: 13px; - } - - &:hover { - cursor: pointer; - } - - .clear-attr { - background: $gray; - padding: 2px; - border-radius: 50%; - color: white; - margin: 3px 2px; - font-size: 8px; - } - } -} - -.popup-tag-term { - display: none; -} - -.popover-tag-term { - .btn { - display: block; - } -} - -.gu-mirror { - .table-quickMenu { - border: none; - - td { - height: 54px; - } - } -} - -.table-responsive { - position: relative; - overflow: auto; -} - -.sindu_dragger { - @extend .gu-mirror; - - &.sindu_column { - li { - float: none !important; - display: table-cell !important; - } - } - - .gu-transit { - //box-shadow: 0px 1px 15px inset; - } - - table { - background: rgb(242, 242, 242) !important; - } -} - -.filter-box { - .inline-content-fr { - .inline { - margin: 0px; - } - } -} - -.typeFilter { - .dropdown { - span.type-clear-btn { - position: absolute; - color: #444444; - font-size: 8px; - right: 23px; - top: 12px; - cursor: pointer; - } - } - - button.dropdown-toggle { - width: 99.5%; - text-align: left; - background-color: white; - color: $color_star_dust_approx; - border: $color_star_dust_approx; - - &:hover { - color: $color_star_dust_approx !important; - border: $color_star_dust_approx !important; - } - } -} - -ul.type-filter-ul { - color: black; - padding: 10px; - max-height: 415px; - overflow: auto; - width: 100%; - padding-top: 0px; - margin-bottom: 0px; - - li { - padding: 2px; - } - - .typeLi li { - padding: 3px; - background-color: #f7fbff; - margin: 3px; - border: 1px solid #dbd6d6; - border-radius: 4px; - - &:hover { - color: $white; - background-color: $color_star_dust_approx; - cursor: pointer; - } - - &.active { - background-color: #37bb9b; - color: white; - } - } - - .filterLi li { - padding: 2px; - margin: 4px; - } -} - -.dark-text { - color: black; -} - -hr.hr-filter { - margin-top: 7px; - margin-bottom: 7px; - border: 0; -} - -.searchTable { - &.noData { - - .labelShowRecord, - .inline[data-id="colManager"], - .row.searach-result-pagination, - table thead { - display: none !important; - } - } -} - -.attr-filter-overlay { - position: absolute; - height: 100%; - width: 100%; - opacity: 0.5; - z-index: 2; - background: white; -} - -.searchResultContainer { - z-index: 1; -} - -.attributeResultContainer { - &.overlay { - z-index: 3; - } - - .attribute-filter-container { - position: absolute; - z-index: 3; - left: 21px; - width: 75%; - right: 0; - // display: none; - background: $white; - box-shadow: 0px 13px 34px -13px grey; - padding: 15px; - transition: all ease 0.3s; - - &.no-attr { - .filter-box { - display: inline-block; - padding: 0px 15px; - } - - // .attribute-result-footer, - // .attribute-edit-footer { - // display: inline-block; - // } - } - - .filter-box { - padding: 5px; - } - - .entity-detail-table-toggle { - display: inline-block; - } - - .pretty.p-switch.p-fill input:checked~.state.p-primary:before { - background-color: #38bb9b !important; - } - - .pretty.p-switch input:checked~.state.p-primary:before { - border-color: #38bb9b; - } - - .panel { - border: none; - } - - .attribute-result-footer, - .attribute-edit-footer { - text-align: right; - } - } - -} - -.ellipsis { - @include ellipsis(); -} - -.ellipsis-with-margin { - .searchResult { - p { - margin: 10px 0px; - } - } -} - -.popover { - max-width: 800px; - - .attributePopOver { - min-height: 190px; - } -} - -.query-builder { - .rule-container { - &.user-define { - .values-box { - display: flex; - flex-wrap: wrap; - - .rule-filter-container { - width: 200px; - } - - .rule-value-container { - width: 100%; - padding: 7px 0px 0px 0px; - } - } - } - - .rule-value-container { - &>table.custom-table { - tr { - display: none; - - &.custom-tr { - display: table-row; - - td.custom-col-1 { - width: 48%; - - .errorMsg { - display: none; - } - } - } - } - - input, - textarea { - width: 100% !important; - } - } - } - } -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/stats.scss b/dashboardv3/public/css/scss/stats.scss deleted file mode 100644 index 896d5bb6b13..00000000000 --- a/dashboardv3/public/css/scss/stats.scss +++ /dev/null @@ -1,122 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -/* stats */ -.server-stats-container { - - .connection-status { - height: 10px; - width: 10px; - border-radius: 50%; - display: inline-block; - - &.connected { - background-color: #4CAF50; - } - - &.not-connected { - background-color: #f44336; - } - } - - .notification-card { - padding-top: 5px; - } - - .card-container { - &.panel { - &.panel-primary { - border: 1px solid #ddd; - padding: 5px; - } - } - - &.panel-primary>.panel-heading { - color: #686868; - background-color: $white; - font-size: 14px; - font-weight: bold; - } - } - - - .panel-group { - .panel { - padding: 5px; - } - } - - .panel { - &.panel-default { - padding: 5px; - margin: 5px; - } - - .panel-body { - - .col-sm-6, - .col-sm-12 { - padding: 5px; - - .panel-heading { - padding: 5px 0 0 15px; - } - } - - } - - } - - .table { - &.stat-table { - width: 100%; - - td { - display: table-cell; - } - - &.notification-table { - &.table-striped>tbody>tr:nth-of-type(odd) { - background-color: $color_white_lilac_approx; - } - - tr { - - th:not(:first-child), - td:not(:first-child) { - text-align: right; - } - } - } - - - } - } - - .entityTable { - &.table { - tr { - - th:not(:first-child), - td:not(:first-child) { - width: 33%; - text-align: right; - } - } - - } - } -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/style.scss b/dashboardv3/public/css/scss/style.scss deleted file mode 100644 index 37d5458bc60..00000000000 --- a/dashboardv3/public/css/scss/style.scss +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -@import "__mixin.scss"; -@import "__variable.scss"; -@import "common.scss"; -@import "table.scss"; -@import "tab.scss"; -@import "form.scss"; -@import "nav.scss"; -@import "panel.scss"; -@import "loader.scss"; -@import "graph.scss"; -@import "relationship.scss"; -@import "old-style.scss"; -@import "theme.scss"; -@import "tag.scss"; -@import "search.scss"; -@import "profile-table.scss"; -@import "glossary.scss"; -@import "wizard.scss"; -@import "business-metadata.scss"; -@import "stats.scss"; -@import "override.scss"; -@import "leftsidebar.scss"; \ No newline at end of file diff --git a/dashboardv3/public/css/scss/tab.scss b/dashboardv3/public/css/scss/tab.scss deleted file mode 100644 index c164b47440d..00000000000 --- a/dashboardv3/public/css/scss/tab.scss +++ /dev/null @@ -1,208 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - - -/* tab.scss */ - -.atlast-tabbable { - margin: 25px 0; - - .nav-tabs { - border-bottom: 1px solid $color_mystic_approx; - - >li { - >a { - padding: 15px 30px; - text-transform: uppercase; - letter-spacing: 1px; //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 2px 2px 0 0; - } - - &.active>a { - border: 1px solid $color_mystic_approx; - border-bottom-color: transparent; - - &:focus { - border: 1px solid $color_mystic_approx; - border-bottom-color: transparent; - } - - &:hover { - border: 1px solid $color_mystic_approx; - border-bottom-color: transparent; - } - } - } - } - - .tab-content { - background-color: $white; - padding: 35px; - border: 1px solid $color_mystic_approx; - border-top: none; - } -} - -ul.tabs li.tab { - padding: 0; -} - -.tab-content>.tab-pane { - display: block; - opacity: 0; - height: 0; - padding: 0px; - overflow: hidden; - - &.active { - padding: 15px 20px; - opacity: 1; - height: auto; - overflow: auto; - } -} - -.tagsList .atlast-tabbable { - margin: 0; - - .tab-content { - padding: 10px 22px; - } - - .nav-tabs>li>a { - padding: 10px 20px; - } -} - -// NEW theme style -.tabs { - position: relative; - height: 42px; - width: 100%; - white-space: nowrap; - padding: 0; - transition: color 0.28s ease; - - .indicator { - position: absolute; - bottom: 0; - height: 2px; - background-color: $color_keppel_approx; - will-change: left, right; - } - - li.tab { - display: block; - float: left; - text-align: center; - line-height: 42px; - height: 42px; - padding: 0 20px; - margin: 0; - text-transform: uppercase; - letter-spacing: 0.8px; - border-bottom: 1px solid $color_mirage_approx; - - a { - font-size: 14px; - font-weight: 600; - color: $white; - display: block; - text-decoration: none; - width: 100%; - height: 100%; //Instead of the line below you could use @include transition($transition-1, $transition-2, $transition-3, $transition-4, $transition-5, $transition-6, $transition-7, $transition-8, $transition-9, $transition-10) - transition: color 0.28s ease; - /* color: $color_manatee_approx; */ - /* &:hover { - color: $color_keppel_approx; - } - &.active { - color: $color_keppel_approx; - } */ - } - } -} - -.atlast-tabbable { - margin: 25px 0; - - .nav-tabs { - border-bottom: 1px solid $color_mystic_approx; - - >li { - >a { - padding: 15px 30px; - text-transform: uppercase; - letter-spacing: 1px; //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 2px 2px 0 0; - } - - &.active>a { - border: 1px solid $color_mystic_approx; - border-bottom-color: transparent; - - &:focus { - border: 1px solid $color_mystic_approx; - border-bottom-color: transparent; - } - - &:hover { - border: 1px solid $color_mystic_approx; - border-bottom-color: transparent; - } - } - } - } - - .tab-content { - background-color: $white; - padding: 35px; - border: 1px solid $color_mystic_approx; - border-top: none; - } -} - -.default-tab { - .nav-tabs { - >li { - &.active { - >a { - color: $color_jungle_green_approx; - // background: $color_white_lilac_approx; - } - } - - >a { - color: $black; - } - } - } -} - -.pending-task { - - .pending-refresh-btn { - margin-bottom: 15px; - } - - table tr th { - padding: 6px 8px !important; - } - - .panel-heading { - font-size: 16px; - } -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/table.scss b/dashboardv3/public/css/scss/table.scss deleted file mode 100644 index 121769b18c5..00000000000 --- a/dashboardv3/public/css/scss/table.scss +++ /dev/null @@ -1,335 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -.table.bold-key>tbody>tr>td:first-child { - font-weight: 600; -} - -tr.empty { - td { - display: table-cell; - text-align: center; - } -} - - -.stat-table { - - tbody, - thead { - >tr { - - td:nth-child(2), - th:nth-child(2) { - text-align: right; - } - } - } -} - -.entity-detail-table, -.type-node-details, -.relationship-detail-table { - position: relative; - - .hide-empty-value { - .hide-row { - display: none; - } - } - - .entity-relationship-table-toggle, - .entity-detail-table-toggle { - position: absolute; - right: 0; - top: 7px; - } - - table { - - th:nth-child(1), - td:nth-child(1) { - width: 20%; - } - } -} - -.type-node-details { - .header { - .pretty.p-switch .state:before { - border: 1px solid white; - } - - .pretty.p-switch .state label:after { - background-color: white !important; - } - - .pretty.p-switch.p-fill input:checked~.state label:after { - background-color: #4a90e2 !important; - } - - .pretty.p-switch.p-fill input:checked~.state.p-primary:before { - background-color: white !important; - } - } -} - -.backgrid { - td { - white-space: normal; - } - - .select-all-header-cell, - .select-row-cell { - width: 42px; - text-overflow: clip; - } - - thead { - th { - button { - padding-right: 11px; - } - } - } - - .sortable:not(.descending):not(.ascending) { - .sort-caret { - font: normal normal normal 14px/1 FontAwesome; - font-size: inherit; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - font-size: 11px; - - &:before { - content: "\f0dc"; - } - } - } - - .debuggging-table-header { - padding-right: 0px !important; - - button { - float: right; - } - } -} - -.backgrid-paginator ul { - display: inline-block; - padding-left: 0; - margin: 20px 0; - border: 1px $color_keppel_approx solid; - margin: 0px; - float: right; - border-radius: 4px; - overflow: hidden; - - >.active>span, - >.active>a, - >.active>a:hover { - background: none; - color: $color_keppel_approx; - background: none; - color: #37bb9b; - font-weight: 600; - font-family: sans-serif; - } - - >li>a, - >li>span, - >li>button { - width: 30px; - height: 30px; - padding: 0; - line-height: 30px; - text-decoration: none; - border: none; - float: left; - background: $transparent; - color: $color_keppel_approx; - @include ellipsis(); - - i { - font-weight: bold; - } - - &:hover { - color: $white; - background: $color_keppel_approx - } - } - - >.disabled>span, - >.disabled>a, - >li>button[disabled] { - color: $color_mountain_mist_approx; - - &:hover { - cursor: not-allowed; - color: $white; - background: $color_jungle_green_light !important; - } - } -} - -.toggleList.semi-collapsed div:nth-child(n+2) { - display: none; - -} - -.table-quickMenu { - border: thin $lightGrey solid; - border-collapse: separate; - border-radius: 6px; - box-shadow: 0px 0px 4px #d8d8d8; - overflow: scroll !important; - max-height: 500px; - width: 100%; - - .resizeHandler { - &.grid-draggable { - background-color: $color_jungle_green_approx !important; - } - - &:hover { - border-left: 1px solid #d2d2d2; - } - } - - >thead>tr { - background: #eeeeee; - - &>th { - border-width: thin; - // border-color: $color_jungle_green_approx; - border-bottom-style: solid; - box-shadow: none; - padding: 6px 15px !important; - background-color: transparent; - text-align: left; - font-weight: 800; - border-top: 0; - font-size: 14px; - letter-spacing: 0.25px; - color: #6a6a6a; - - &.no-capitalize { - text-transform: none !important; - } - } - - >td { - border-color: $color_gallery_approx; - color: #333333; - font-weight: 100; - padding: 9px 15px; - } - } - - >tbody>tr>td { - &.select-row-cell { - text-align: center; - } - } - - .expandable { - .expandable-content { - max-width: none; - background: #f8f8f8; - - div { - - table { - width: 100%; - - td { - - display: table-cell; - } - - tr:last-child>td { - border-bottom: none; - } - } - } - } - } -} - -td { - - div.scroll-y, - pre.scroll-y { - max-height: 200px; - overflow-y: auto; - word-break: break-all; - } - - &.searchTableName { - min-width: 150px; - - &:hover { - img { - transform: scale(1.5); - transform-origin: 100% 50%; - transition: transform 0.2s; - outline-color: #f5f5f5; - } - } - - a { - max-width: calc(100% - 36px); - overflow: hidden; - float: left; - text-overflow: ellipsis; - } - - img { - height: 20px; - margin: 0px 5px; - float: left; - } - } -} - -.auditStatusContainer { - display: flex; - flex-wrap: wrap; - justify-content: center; - - &>div { - flex-grow: 1; - } -} - -.debug-metrics-table table { - - tr th:not(:first-child), - tr td:not(:first-child) { - text-align: center !important; - - button { - margin: 0 auto; - } - } -} - -.debug-btn-wrapper { - margin-bottom: 5px; - z-index: 2; -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/tag.scss b/dashboardv3/public/css/scss/tag.scss deleted file mode 100644 index 5a023e6f52c..00000000000 --- a/dashboardv3/public/css/scss/tag.scss +++ /dev/null @@ -1,212 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -//tag.scss -.tag-tree { - padding: 0; // overflow: auto; - - &.saveSearchList { - height: 150px; - overflow-y: auto; - } - - .child>li, - >li { - list-style: none; - cursor: pointer; - - &.parent-node { - position: relative; - - &.active { - &>div { - background-color: $color_havelock_blue_approx; - border: none; - - .tools { - display: block - } - - &>a, - &>i { - color: $white !important; - } - - &:hover { - background-color: $color_havelock_blue_approx; - } - } - - ul.child { - &:after { - height: 4px; - top: -5px; - } - } - } - - &>div { - position: relative; - margin-top: 5px; - /* margin-bottom: 5px; */ - border-radius: 4px; - - &:hover { - background-color: $color_star_dust_approx; - color: $white !important; - - &>a { - color: $white !important; - } - } - - >.fa.toggleArrow { - position: absolute; - left: 0; - padding: 8px; - cursor: pointer; - } - - .tools { - display: none; - position: absolute; - right: 0; - color: $white; - padding: 5px 10px; - } - - >a, - >div>a { - display: block; - color: $color_ironside_gray_approx !important; - white-space: nowrap; - padding: 5px 10px; - max-width: 91%; - @include ellipsis(); - font-size: 14px; - - &:hover { - text-decoration: none !important; - } - } - - >i+a { - padding: 5px 25px; - } - } - - >ul.child { - margin-left: 11px; - padding-left: 10px; - border-left: 1px dotted gray; - position: relative; - - &:after { - position: absolute; - content: ""; - height: 13px; - width: 11px; - top: -14px; - left: -1px; - border-left: 1px dotted gray; - } - - li { - &.parent-node { - &:after { - position: absolute; - content: ""; - height: 2px; - width: 14px; - top: 16px; - left: -9px; - border-top: 1px dotted gray; - } - - &.active:after { - width: 9px; - } - } - } - } - } - } -} - -.input-group.attributes .form-control { - height: 40px; - box-shadow: none; - border-right: none; -} - -.input-group.attributes .input-group-addon { - background-color: $color_white_lilac_approx; - border: 1px $color_mystic_approx solid; - border-radius: 0px; - border-left: none; -} - -.input-group.attributes .input-group-addon i.fa { - cursor: pointer; -} - -.input-group.attributes .form-control:focus+.input-group-addon { - border-color: $color_bali_hai_approx; -} - -.entityLink { - font-size: 16px; -} - -.mainAttrTable { - max-height: 180px; - overflow: auto; - - table.attriTable { - width: 100%; - - td { - // &[data-type="int"], - // &[data-type="long"], - // &[data-type="float"], - // &[data-type="byte"], - // &[data-type="double"], - // &[data-type="short"] { - // text-align: right; - // } - } - - th, - td { - border: 1px solid #ddd; - padding: 5px 7px; - width: 50%; - - &.renderable.html-cell { - min-width: 150px; - } - } - } -} - -.addtag-propagte-box { - border: 1px solid #ddd; - border-radius: 7px; -} - -.entityTypeSelector { - margin: 10px 0px; -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/theme.scss b/dashboardv3/public/css/scss/theme.scss deleted file mode 100644 index af9c23d9c82..00000000000 --- a/dashboardv3/public/css/scss/theme.scss +++ /dev/null @@ -1,767 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -/* theme.scss */ -$sidebar-color: #f4f4f4; -$sidebar-gray-color: #797979; - -body { - font-family: $font_0, $font_1; - color: $color_ironside_gray_approx; - overflow-x: hidden; - - .view-container { - padding-top: 68px; - } - - #sidebar-wrapper.animate-me, - #page-wrapper.animate-me { - transition: width ease 0.3s; - } - - #page-wrapper { - height: calc(100vh - 90px); - overflow: auto; - padding-top: 15px !important; - padding-bottom: 10px !important; - } -} - -.back-button { - display: inline-block; - float: left; - position: absolute; - left: 4px; - top: 9px; - font-size: 38px; - color: #bfbfbf; - cursor: pointer; - - &:hover { - color: $gray; - } -} - -.detail-page { - .back-button { - top: 15px; - font-size: 45px; - } -} - -.modal-header { - .back-button { - margin-left: 10px; - top: 9px; - font-size: 38px; - } - - .modal-name { - font-size: 22px; - margin-top: 5px; - margin-left: 20px; - } -} - - -.atlas-page-header { - height: 70px; - background-color: #d3e0eb; - display: block; - position: fixed; - left: 0px; - right: 0px; - padding: 10px; - - .atlas-page-header-title { - display: inline-block; - margin: 0px 20px; - line-height: 50px; - overflow: hidden; - } - - .atlas-page-header-content { - display: inline-block; - overflow: hidden; - } -} - -.atlas-page-content {} - -.popover-menu { - li>a { - color: $color_ironside_gray_approx; - - &:hover { - color: $color_jungle_green_approx; - } - - i { - padding-right: 3px; - } - } - - .listTerm { - padding: 3px 0px; - } - - .divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; - } -} - -header.atlas-header { - background-color: $white; - border-bottom: 1px $color_mystic_approx solid; - position: fixed; - width: 100%; - z-index: 4; - box-shadow: 0px 2px 6px 0px rgba(0, 0, 0, 0.05); - - .navbar-nav { - display: table; - - li { - float: none; - display: table-cell; - padding: 0px 5px; - } - - .logo { - // width: 172px; - height: 46px; - padding: 6px 6px 6px 0px; - margin-left: 10px; - } - } - - &>table { - width: 100%; - - td { - padding: 3px 2px; - position: relative; - transition: width 0.3s !important; - - .admin-icon { - background-color: $color_ironside_gray_approx; - width: 24px; - height: 20px; - -webkit-mask: url(../img/support.svg) no-repeat center; - mask: url(../img/support.svg) no-repeat center; - } - - .search-box { - width: 50%; - margin: 0 auto; - } - } - } - - .header-menu { - .dropdown-menu { - &.right-align { - right: 0; - left: auto; - } - - &>li>a, - { - color: $color_ironside_gray_approx; - - &:hover { - color: $color_jungle_green_approx; - } - - i { - padding-right: 3px; - } - } - } - - td { - >a { - display: inline-block; - color: $color_ironside_gray_approx !important; - padding: 13px 14px; - border-bottom: 2px solid transparent; - } - - >a, - >table { - padding: 14px 14px; - - &:hover { - border-bottom: 2px solid $color_jungle_green_approx; - padding: 14px 14px; - color: $color_jungle_green_approx !important; - - .admin-icon { - background-color: $color_jungle_green_approx; - } - - a { - color: $color_jungle_green_approx; - - &:hover { - border: none; - } - } - } - - td { - padding: 0px 15px; - - a { - border-bottom: 0px; - } - } - - span { - padding: 5px; - } - - i { - font-size: 18px; - } - } - } - } -} - -.main-search { - .form-control { - border: none; - border-left: 1px $color_mystic_approx solid; //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 0; //Instead of the line below you could use @include box-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - box-shadow: none; - height: 60px; - font-size: 18px; - font-style: italic; - } - - .input-group-addon { - font-size: 20px; - color: $color_bombay_approx; - background: none; - border: none; - } -} - -.close { - font-size: 2em; -} - -.fix-filter { - position: fixed; - bottom: 0; - - .header { - height: 10px; - background: blue; - } - - .body {} -} - -.page-title { - padding: 0px 15px 0px 15px; - - .title { - padding-top: 0; - margin-top: 0; - } - - h1 { - &.title { - word-break: break-all; - } - - // margin-top: 50px; - margin-bottom: 10px; - font-weight: 600; - @include ellipsis(); - max-width: 91%; - display: inline-block; - - small { - position: relative; - bottom: 5px; - margin-left: 15px; - padding-left: 15px; - border-left: 1px $color_mystic_approx solid; - color: $color_bombay_approx; - font-size: 40%; - font-weight: 600; - text-transform: uppercase; - } - } - - .sub-title { - margin-bottom: 40px; - } -} - -.sm-title { - line-height: 30px; -} - -.md-title { - line-height: 34px; -} - -.lg-title { - line-height: 40px; -} - -.group-box { - margin-bottom: 15px; -} - -.ui-resizable-w { - border-left: 1px solid gray; -} - -a { - color: $color_jungle_green_approx; - cursor: pointer; - - &:focus { - color: $color_puerto_rico_approx; - text-decoration: none; - outline: none; - cursor: pointer; - } - - &:hover { - color: $color_puerto_rico_approx; - text-decoration: none; - cursor: pointer; - } -} - -.cursor-default, -.cursor-default a { - cursor: default; -} - -.blue-link { - color: $color_havelock_blue_approx; - - &:focus { - color: $color_havelock_blue_approx; - text-decoration: none; - outline: none; - } - - &:hover { - color: $color_havelock_blue_approx; - text-decoration: underline; - } -} - -a[href^="#!/"]:not(.btn, .not-blue-link) { - @extend .blue-link; -} - -th { - text-transform: capitalize; -} - -ul { - list-style: none; -} - -hr[size="10"] { - margin: 10px 0px; -} - -.table { - margin-bottom: 2px; - background-color: $white; - max-width: none; - - .table { - width: auto; - } -} - -.card { - background: $white none repeat scroll 0 0; //Instead of the line below you could use @include box-shadow($shadow-1, $shadow-2, $shadow-3, $shadow-4, $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9, $shadow-10) - box-shadow: 0 1px 3px $black_30; - margin-bottom: 30px; -} - -// Colors Class -.white-bg { - background-color: $white; - padding: 30px 0; -} - -.gray-text { - color: $color_star_dust_approx; -} - -.gray-bg { - background-color: $color_white_lilac_approx; -} - -.comment-input { - background-color: $color_white_lilac_approx; - padding: 20px; - font-size: 16px; - margin-bottom: 20px; -} - -.comment-box { - padding: 25px 0; - margin-top: 25px; - border-top: 1px $color_mystic_approx solid; - - .comment { - margin-bottom: 25px; - } - - .author { - color: $color_keppel_approx; - margin-bottom: 0; - } - - .date { - color: $color_star_dust_approx; - } -} - -.col-sm-custom { - margin: 15px 25px 0px; - position: relative; -} - -.no-padding { - padding: 0px !important; -} - -.no-padding-bottom { - padding-bottom: 0px !important; -} - -.no-padding-top { - padding-top: 0px !important; -} - -.no-padding-left { - padding-left: 0px !important; -} - -.no-padding-right { - padding-right: 0px !important; -} - -.no-margin { - margin: 0px !important; -} - -.no-margin-bottom { - margin-bottom: 0px !important; -} - -.no-margin-top { - margin-top: 0px !important; -} - -.no-margin-left { - margin-left: 0px !important; -} - -.no-margin-right { - margin-right: 0px !important; -} - -.no-border { - border: none !important; -} - -.no-pointer { - pointer-events: none; -} - -.position-relative { - position: relative; -} - -.pagination-box { - margin-top: 15px; -} - -.ellipsis-with-margin { - @include ellipsis(); - margin-bottom: 10px; -} - -.ellipsis { - @include ellipsis(); -} - -.readOnlyLink { - @include ellipsis(); - - .deleteBtn { - padding: 0px 5px; - } - - a { - color: $delete_link !important; - } -} - -.add-seperator { - margin-bottom: 10px; - border-bottom: 1px solid #eeeaea; - padding-bottom: 10px; -} - -.legend-sm { - font-size: 17px; -} - -.errorClass { - border: 1px solid red !important; - box-shadow: none !important; -} - -.inline-content { - >.inline { - display: inline-block; - - &+.inline { - margin-left: 5px; - } - } -} - -.inline-content-fl { - @extend .inline-content; - - >.inline { - display: block; - float: left; - } -} - -.inline-content-fr { - @extend .inline-content-fl; - - >.inline { - float: right; - - &+.inline { - margin-right: 5px; - } - } -} - -.has-error { - - .select2-selection--single, - .select2-selection--multiple { - border-color: $color_apple_blossom_approx; - } -} - -.search-entity-icon-box { - padding: 10px; - border-radius: 50%; - width: 25px; - height: 25px; - - img { - width: 25px; - height: 25px; - cursor: default; - } -} - -.entity-icon-box { - display: inline-block; - background: #cee0fa; - padding: 10px; - border-radius: 50%; - min-width: 76.25px; - min-height: 70px; - - &.disabled { - background: #e3e3e3; - } - - img { - height: 50px; - } -} - -.ui-menu.ui-widget-content.ui-autocomplete { - box-shadow: 0px 11px 30px -8px grey; - max-width: 100%; - max-height: 70vh; - overflow-y: auto; - /* prevent horizontal scrollbar */ - overflow-x: hidden; - - .ui-autocomplete-category { - padding: 5px 15px; - color: #acacac; - text-transform: capitalize; - } - - li.empty { - padding: 5px 2px; - line-height: 45px; - - span.empty-message { - padding: 10px; - } - } - - .ui-menu-item { - padding: 2px 2px; - color: $color_ironside_gray_approx; - - &.with-icon { - img { - height: 25px; - width: 30px; - margin-right: 10px; - background: none; - } - } - - span.searched-term { - display: inline-block; - padding: 0; - font-weight: bold; - color: $black !important; - } - - .ui-state-active { - margin: 0px; - border: none; - background: #cee0fa; - color: $black !important; - } - - a, - span { - padding: 6px 10px; - display: block; - color: inherit !important; - } - } -} - -.tooltip-inner { - max-width: none; - color: #2c2c2c; - background-color: #f9f9f9; - box-shadow: 0px 0px 3px 0px #8080806b; -} - -.tooltip.bottom .tooltip-arrow { - border-bottom-color: #000; -} - -.dropdown-menu.multi-level { - .dropdown-submenu { - position: relative; - - &>a:after { - display: none; - content: " "; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - border-width: 5px 5px 5px 0px; - border-right-color: #ccc; - position: absolute; - left: 8px; - top: calc(50% - 5px); - } - - &>a:hover:after { - display: block; - } - - &>.dropdown-menu { - top: 0; - left: -100%; - width: 100%; - margin-top: -6px; - margin-left: -1px; - -webkit-border-radius: 0 6px 6px 6px; - -moz-border-radius: 0 6px 6px; - border-radius: 0 6px 6px 6px; - } - - &:hover>.dropdown-menu { - display: table; - } - - } -} - -.select2-results__option { - &.select2-results__option--highlighted { - .option-title-light { - color: #eaeaea; - } - } - - .option-title-light { - font-size: 12px; - color: #a4a4a4; - } - - -} - -.dropzone { - border-radius: 10px; - border: 2px dashed $color_havelock_blue_approx; - - .dz-default.dz-message { - font-weight: 500; - font-size: 20px; - } - - &.single-file-center { - .dz-file-preview { - margin-left: calc(50% - 68px); - } - } -} - -.dropzone-modal { - .modal-body { - background: $color_white_lilac_approx; - } -} - -.help-btn { - cursor: pointer; - font-size: 20px; -} \ No newline at end of file diff --git a/dashboardv3/public/css/scss/wizard.scss b/dashboardv3/public/css/scss/wizard.scss deleted file mode 100644 index 85efe73555c..00000000000 --- a/dashboardv3/public/css/scss/wizard.scss +++ /dev/null @@ -1,392 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -$color_scarlet_approx: #ff3111; -$color_pippin_approx: #fbe3e4; -$color_your_pink_approx: #fbc2c4; -$color_falu_red_approx: #8a1f11; - -%wizard_tabcontrol { - display: block; - width: 100%; -} - -%extend_2 { - list-style: none !important; - padding: 0; - margin: 0; -} - -%extend_3 { - display: block; - width: auto; - margin: 0 .5em .5em; - padding: 1em; - text-decoration: none; - position: relative; - border-radius: 5px; -} - -%extend_4 { - background: #f5f5f5; - color: #bbb; - cursor: default; -} - -%extend_5 { - background: $color_keppel_approx; - color: $white; - cursor: default; -} - -%extend_befor_after { - content: " "; - display: block; - width: 0; - height: 0; - border-top: 50px solid transparent; - border-bottom: 50px solid transparent; - position: absolute; - top: 50%; - margin-top: -50px; - left: 100%; -} - -.wizard { - @extend %wizard_tabcontrol; - - a { - outline: 0; - } - - ul { - @extend %extend_2; - - >li { - display: block; - padding: 0; - } - } - - > { - .steps { - position: relative; - display: block; - width: 100%; - - .current-info { - position: absolute; - left: -999em; - } - - .number { - font-size: 1.429em; - } - - &>ul { - position: relative; - border: 0; - padding: 0px; - background: #f5f5f5; - border-radius: 0; - list-style: none; - overflow: hidden; - margin-bottom: 10px; - - >li { - width: 25%; - float: left; - - &:first-child>a { - padding-left: 15px; - } - - a { - @extend %extend_3; - - &:hover { - cursor: pointer; - } - - margin: 0; - border: none; - border-radius: 0; - padding: 10px 0 10px 45px; - - &:before { - @extend %extend_befor_after; - border-left: 30px solid #ddd; - margin-left: 1px; - z-index: 1; - } - - &:after { - @extend %extend_befor_after; - border-left: 30px solid #f5f5f5; - z-index: 2; - } - } - - &.disabled a { - @extend %extend_4; - } - - &.current a { - @extend %extend_5; - - &:after { - border-left: 30px solid $color_keppel_approx; - } - } - - &.done a { - background: #b4e5d9; - color: $white; - - &:after { - border-left: 30px solid #b4e5d9; - } - } - - &.error a { - background: $color_scarlet_approx; - color: $white; - - &:after { - border-left: 30px solid $color_scarlet_approx; - } - } - } - } - } - - .content { - background: #f5f5f5; - display: block; - margin: .5em; - position: relative; - width: 100%; //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 5px; - - > { - .title { - display: none; - } - - .body { - float: left; - width: 100%; - height: 95%; - padding: 2.5%; - - >ul { - list-style: disc !important; - - >li { - display: list-item; - } - } - } - } - } - - .actions { - position: relative; - display: block; - text-align: right; - width: 100%; - - ul[role="menu"] { - li+li { - margin-left: 5px; - } - - li.disabled { - a { - opacity: .65; - } - } - - a { - padding: 10px 20px; - background-color: $color_keppel_approx; - color: $white; - margin-bottom: 10px; - border: 1px $color_keppel_approx solid; - border-radius: 4px; - transition: all .3s ease; - margin: 2px; - } - - a[href="#cancel"] { - padding: 10px 20px; - background-color: transparent; - color: $color_keppel_approx; - margin-bottom: 10px; - border: 1px $color_keppel_approx solid; - border-radius: 4px; - transition: all .3s ease; - margin: 2px; - } - } - - >ul { - display: inline-block; - text-align: right; - - >li { - float: left; - margin: 0 .5em; - } - } - } - - .loading .spinner {} - } - - &.vertical> { - .steps { - display: inline; - float: left; - width: 30%; - - >ul>li { - float: none; - width: 100%; - } - } - - .content { - display: inline; - float: left; - margin: 0 2.5% .5em 2.5%; - width: 65%; - } - - .actions { - display: inline; - float: right; - margin: 0 2.5%; - width: 95%; - - >ul>li { - margin: 0 0 0 1em; - } - } - } -} - -.tabcontrol { - @extend %wizard_tabcontrol; - - a { - outline: 0; - } - - ul { - @extend %extend_2; - - >li { - display: block; - padding: 0; - } - } - - > { - .steps .current-info { - position: absolute; - left: -999em; - } - - .content>.title { - display: none; - } - } -} - -@media(max-width: 600px) { - .wizard { - >.steps { - a { - margin-top: .5em; - - &:hover { - margin-top: .5em; - } - - &:active { - margin-top: .5em; - } - } - - >ul>li { - width: 50%; - } - } - - &.vertical> { - .steps { - display: block; - float: none; - width: 100%; - } - - .actions { - display: block; - float: none; - width: 100%; - } - - .content { - display: block; - float: none; - margin: 0 .5em .5em; - width: auto; - } - } - } -} - -@media(max-width: 480px) { - .wizard>.steps>ul>li { - width: 100%; - } -} - -.wizard-modal { - .modal-body { - overflow: hidden; - max-height: none; - } - - .wizard { - position: relative; - width: 100%; - height: 100%; - - .content { - max-height: 400px; - overflow: auto; - margin: 0px 0px 15px 0px; - } - - .actions { - >ul>li { - margin: 0px; - } - } - } -} \ No newline at end of file diff --git a/dashboardv3/public/ieerror.html b/dashboardv3/public/ieerror.html deleted file mode 100644 index 7b67bcfacb7..00000000000 --- a/dashboardv3/public/ieerror.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - Atlas - - - - - - - - -
        - - - - -
        -
        - -
        -
        -

        Please note that Atlas does not supports old version of Internet Explorer.

        -

        We recommend upgrading to the latest Internet Explorer, Google Chrome, or Firefox.

        -
        -
        - -
        - - - \ No newline at end of file diff --git a/dashboardv3/public/img/atlas_logo.png b/dashboardv3/public/img/atlas_logo.png deleted file mode 100644 index f0203f6f0d9..00000000000 Binary files a/dashboardv3/public/img/atlas_logo.png and /dev/null differ diff --git a/dashboardv3/public/img/atlas_logo.svg b/dashboardv3/public/img/atlas_logo.svg deleted file mode 100644 index 3314cb039e7..00000000000 --- a/dashboardv3/public/img/atlas_logo.svg +++ /dev/null @@ -1,17 +0,0 @@ - -Asset 6 \ No newline at end of file diff --git a/dashboardv3/public/img/atlas_logo_beta.png b/dashboardv3/public/img/atlas_logo_beta.png deleted file mode 100644 index fcd54d4da0d..00000000000 Binary files a/dashboardv3/public/img/atlas_logo_beta.png and /dev/null differ diff --git a/dashboardv3/public/img/atlas_logo_beta.svg b/dashboardv3/public/img/atlas_logo_beta.svg deleted file mode 100644 index 18fe3e9eb67..00000000000 --- a/dashboardv3/public/img/atlas_logo_beta.svg +++ /dev/null @@ -1,17 +0,0 @@ - -Atlas_Logo_Beta \ No newline at end of file diff --git a/dashboardv3/public/img/atlas_monogram.svg b/dashboardv3/public/img/atlas_monogram.svg deleted file mode 100644 index 1bea91b3ddc..00000000000 --- a/dashboardv3/public/img/atlas_monogram.svg +++ /dev/null @@ -1,17 +0,0 @@ - -Atlas_Logo_monogram \ No newline at end of file diff --git a/dashboardv3/public/img/entity-icon/AtlasServer.png b/dashboardv3/public/img/entity-icon/AtlasServer.png deleted file mode 100644 index f24c01794b1..00000000000 Binary files a/dashboardv3/public/img/entity-icon/AtlasServer.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/DataSet.png b/dashboardv3/public/img/entity-icon/DataSet.png deleted file mode 100644 index 5fb37673603..00000000000 Binary files a/dashboardv3/public/img/entity-icon/DataSet.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/avro.png b/dashboardv3/public/img/entity-icon/avro.png deleted file mode 100644 index f1de7f8b82c..00000000000 Binary files a/dashboardv3/public/img/entity-icon/avro.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/aws.png b/dashboardv3/public/img/entity-icon/aws.png deleted file mode 100644 index 8c8f7c504a7..00000000000 Binary files a/dashboardv3/public/img/entity-icon/aws.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/azure.png b/dashboardv3/public/img/entity-icon/azure.png deleted file mode 100644 index 82e1caa49f2..00000000000 Binary files a/dashboardv3/public/img/entity-icon/azure.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/db.png b/dashboardv3/public/img/entity-icon/db.png deleted file mode 100644 index 577d5805fbe..00000000000 Binary files a/dashboardv3/public/img/entity-icon/db.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/AtlasServer.png b/dashboardv3/public/img/entity-icon/disabled/AtlasServer.png deleted file mode 100644 index ab3a1247950..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/AtlasServer.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/DataSet.png b/dashboardv3/public/img/entity-icon/disabled/DataSet.png deleted file mode 100644 index 5ed51de7592..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/DataSet.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/avro.png b/dashboardv3/public/img/entity-icon/disabled/avro.png deleted file mode 100644 index c9a6172cf65..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/avro.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/aws.png b/dashboardv3/public/img/entity-icon/disabled/aws.png deleted file mode 100644 index d9be6f3ea0a..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/aws.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/azure.png b/dashboardv3/public/img/entity-icon/disabled/azure.png deleted file mode 100644 index 720f3ac5915..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/azure.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/db.png b/dashboardv3/public/img/entity-icon/disabled/db.png deleted file mode 100644 index 982c6867a29..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/db.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/falcon.png b/dashboardv3/public/img/entity-icon/disabled/falcon.png deleted file mode 100644 index ef8cd242eb6..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/falcon.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/falcon_feed_creation.png b/dashboardv3/public/img/entity-icon/disabled/falcon_feed_creation.png deleted file mode 100644 index f7404678833..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/falcon_feed_creation.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/falcon_feed_replication.png b/dashboardv3/public/img/entity-icon/disabled/falcon_feed_replication.png deleted file mode 100644 index af492dabe66..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/falcon_feed_replication.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/falcon_process.png b/dashboardv3/public/img/entity-icon/disabled/falcon_process.png deleted file mode 100644 index 075628c5898..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/falcon_process.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/file_system.png b/dashboardv3/public/img/entity-icon/disabled/file_system.png deleted file mode 100644 index 8b4e50416c3..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/file_system.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/flink.png b/dashboardv3/public/img/entity-icon/disabled/flink.png deleted file mode 100644 index af78144be18..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/flink.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/flink_application.png b/dashboardv3/public/img/entity-icon/disabled/flink_application.png deleted file mode 100644 index af78144be18..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/flink_application.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/flink_application_processes.png b/dashboardv3/public/img/entity-icon/disabled/flink_application_processes.png deleted file mode 100644 index 28d4ed91683..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/flink_application_processes.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/flink_process.png b/dashboardv3/public/img/entity-icon/disabled/flink_process.png deleted file mode 100644 index af78144be18..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/flink_process.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/gcp.png b/dashboardv3/public/img/entity-icon/disabled/gcp.png deleted file mode 100644 index e7d83fe36b8..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/gcp.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/hadoop.png b/dashboardv3/public/img/entity-icon/disabled/hadoop.png deleted file mode 100644 index 0334fc7d78e..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/hadoop.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/hbase.png b/dashboardv3/public/img/entity-icon/disabled/hbase.png deleted file mode 100644 index fa6e21427dd..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/hbase.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/hbase_column.png b/dashboardv3/public/img/entity-icon/disabled/hbase_column.png deleted file mode 100644 index ef454267bf4..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/hbase_column.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/hbase_column_family.png b/dashboardv3/public/img/entity-icon/disabled/hbase_column_family.png deleted file mode 100644 index 0182ec3e0f2..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/hbase_column_family.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/hbase_table.png b/dashboardv3/public/img/entity-icon/disabled/hbase_table.png deleted file mode 100644 index 556a10a14d7..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/hbase_table.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/hdfs_path.png b/dashboardv3/public/img/entity-icon/disabled/hdfs_path.png deleted file mode 100644 index 8b4e50416c3..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/hdfs_path.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/hive.png b/dashboardv3/public/img/entity-icon/disabled/hive.png deleted file mode 100644 index 227f5b3a31b..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/hive.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/hive_column.png b/dashboardv3/public/img/entity-icon/disabled/hive_column.png deleted file mode 100644 index 35fbe482343..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/hive_column.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/hive_column_lineage.png b/dashboardv3/public/img/entity-icon/disabled/hive_column_lineage.png deleted file mode 100644 index c08f4b4200c..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/hive_column_lineage.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/hive_db.png b/dashboardv3/public/img/entity-icon/disabled/hive_db.png deleted file mode 100644 index 76b5c3f8c5f..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/hive_db.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/hive_process.png b/dashboardv3/public/img/entity-icon/disabled/hive_process.png deleted file mode 100644 index 5cc6d78c6d7..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/hive_process.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/hive_process_execution.png b/dashboardv3/public/img/entity-icon/disabled/hive_process_execution.png deleted file mode 100644 index ec1be806184..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/hive_process_execution.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/hive_storagedesc.png b/dashboardv3/public/img/entity-icon/disabled/hive_storagedesc.png deleted file mode 100644 index c3930a43f46..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/hive_storagedesc.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/hive_table.png b/dashboardv3/public/img/entity-icon/disabled/hive_table.png deleted file mode 100644 index b22e194d83f..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/hive_table.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/impala.png b/dashboardv3/public/img/entity-icon/disabled/impala.png deleted file mode 100644 index c94be973b71..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/impala.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/impala_column_lineage.png b/dashboardv3/public/img/entity-icon/disabled/impala_column_lineage.png deleted file mode 100755 index 7ef403bc4d2..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/impala_column_lineage.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/impala_process.png b/dashboardv3/public/img/entity-icon/disabled/impala_process.png deleted file mode 100755 index 7ef403bc4d2..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/impala_process.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/jms_topic.png b/dashboardv3/public/img/entity-icon/disabled/jms_topic.png deleted file mode 100644 index 54a02c8f447..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/jms_topic.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/kafka.png b/dashboardv3/public/img/entity-icon/disabled/kafka.png deleted file mode 100644 index ef941d3445f..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/kafka.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/kafka_consumer.png b/dashboardv3/public/img/entity-icon/disabled/kafka_consumer.png deleted file mode 100644 index d7e564f0fa9..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/kafka_consumer.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/kafka_consumer_group.png b/dashboardv3/public/img/entity-icon/disabled/kafka_consumer_group.png deleted file mode 100644 index 1bc9dadfc27..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/kafka_consumer_group.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/kafka_consumer_lineage.png b/dashboardv3/public/img/entity-icon/disabled/kafka_consumer_lineage.png deleted file mode 100644 index 80248e9f078..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/kafka_consumer_lineage.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/kafka_producer.png b/dashboardv3/public/img/entity-icon/disabled/kafka_producer.png deleted file mode 100644 index 372cff48f1d..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/kafka_producer.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/kafka_producer_lineage.png b/dashboardv3/public/img/entity-icon/disabled/kafka_producer_lineage.png deleted file mode 100644 index c312b548077..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/kafka_producer_lineage.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/kafka_topic.png b/dashboardv3/public/img/entity-icon/disabled/kafka_topic.png deleted file mode 100644 index 84cb234161d..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/kafka_topic.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/ozone.png b/dashboardv3/public/img/entity-icon/disabled/ozone.png deleted file mode 100644 index f498c2d149a..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/ozone.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/ozone_bucket.png b/dashboardv3/public/img/entity-icon/disabled/ozone_bucket.png deleted file mode 100644 index 5b0d5d159ef..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/ozone_bucket.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/ozone_key.png b/dashboardv3/public/img/entity-icon/disabled/ozone_key.png deleted file mode 100644 index 4dba49172df..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/ozone_key.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/ozone_volume.png b/dashboardv3/public/img/entity-icon/disabled/ozone_volume.png deleted file mode 100644 index 1e4326b22a3..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/ozone_volume.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/process.png b/dashboardv3/public/img/entity-icon/disabled/process.png deleted file mode 100644 index 88bc1ae7588..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/process.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/rdbms.png b/dashboardv3/public/img/entity-icon/disabled/rdbms.png deleted file mode 100644 index 84f20bae4fa..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/rdbms.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/rdbms_column.png b/dashboardv3/public/img/entity-icon/disabled/rdbms_column.png deleted file mode 100644 index 200a2882161..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/rdbms_column.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/rdbms_db.png b/dashboardv3/public/img/entity-icon/disabled/rdbms_db.png deleted file mode 100644 index 6f1d1690f8d..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/rdbms_db.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/rdbms_table.png b/dashboardv3/public/img/entity-icon/disabled/rdbms_table.png deleted file mode 100644 index e49fc68f848..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/rdbms_table.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/spark.png b/dashboardv3/public/img/entity-icon/disabled/spark.png deleted file mode 100644 index 93f8a4d8608..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/spark.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/spark_process.png b/dashboardv3/public/img/entity-icon/disabled/spark_process.png deleted file mode 100644 index bf191217c19..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/spark_process.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/spark_table.png b/dashboardv3/public/img/entity-icon/disabled/spark_table.png deleted file mode 100644 index 1404026ae4d..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/spark_table.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/sqoop.png b/dashboardv3/public/img/entity-icon/disabled/sqoop.png deleted file mode 100644 index 359b77edf99..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/sqoop.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/sqoop_db.png b/dashboardv3/public/img/entity-icon/disabled/sqoop_db.png deleted file mode 100644 index 970ab9a6bea..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/sqoop_db.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/sqoop_process.png b/dashboardv3/public/img/entity-icon/disabled/sqoop_process.png deleted file mode 100644 index aae4d56092d..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/sqoop_process.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/storm.png b/dashboardv3/public/img/entity-icon/disabled/storm.png deleted file mode 100644 index cab3f7f021a..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/storm.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/storm_bolt.png b/dashboardv3/public/img/entity-icon/disabled/storm_bolt.png deleted file mode 100644 index f35add3ac5e..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/storm_bolt.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/storm_spout.png b/dashboardv3/public/img/entity-icon/disabled/storm_spout.png deleted file mode 100644 index 841375170a3..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/storm_spout.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/storm_topology.png b/dashboardv3/public/img/entity-icon/disabled/storm_topology.png deleted file mode 100644 index 224a2876fb8..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/storm_topology.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/disabled/table.png b/dashboardv3/public/img/entity-icon/disabled/table.png deleted file mode 100644 index de1e5cdff0f..00000000000 Binary files a/dashboardv3/public/img/entity-icon/disabled/table.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/falcon.png b/dashboardv3/public/img/entity-icon/falcon.png deleted file mode 100644 index 14e8234d4f9..00000000000 Binary files a/dashboardv3/public/img/entity-icon/falcon.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/falcon_feed_creation.png b/dashboardv3/public/img/entity-icon/falcon_feed_creation.png deleted file mode 100644 index 955404cdf32..00000000000 Binary files a/dashboardv3/public/img/entity-icon/falcon_feed_creation.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/falcon_feed_replication.png b/dashboardv3/public/img/entity-icon/falcon_feed_replication.png deleted file mode 100644 index 7cbf15ddc8b..00000000000 Binary files a/dashboardv3/public/img/entity-icon/falcon_feed_replication.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/falcon_process.png b/dashboardv3/public/img/entity-icon/falcon_process.png deleted file mode 100644 index baee877a9fb..00000000000 Binary files a/dashboardv3/public/img/entity-icon/falcon_process.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/file_system.png b/dashboardv3/public/img/entity-icon/file_system.png deleted file mode 100644 index 778578690f8..00000000000 Binary files a/dashboardv3/public/img/entity-icon/file_system.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/flink.png b/dashboardv3/public/img/entity-icon/flink.png deleted file mode 100644 index 9a94d12c3c0..00000000000 Binary files a/dashboardv3/public/img/entity-icon/flink.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/flink_application.png b/dashboardv3/public/img/entity-icon/flink_application.png deleted file mode 100644 index 9a94d12c3c0..00000000000 Binary files a/dashboardv3/public/img/entity-icon/flink_application.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/flink_application_processes.png b/dashboardv3/public/img/entity-icon/flink_application_processes.png deleted file mode 100644 index 53237abdac5..00000000000 Binary files a/dashboardv3/public/img/entity-icon/flink_application_processes.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/flink_process.png b/dashboardv3/public/img/entity-icon/flink_process.png deleted file mode 100644 index 9a94d12c3c0..00000000000 Binary files a/dashboardv3/public/img/entity-icon/flink_process.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/gcp.png b/dashboardv3/public/img/entity-icon/gcp.png deleted file mode 100644 index 4740e8dbf24..00000000000 Binary files a/dashboardv3/public/img/entity-icon/gcp.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hadoop.png b/dashboardv3/public/img/entity-icon/hadoop.png deleted file mode 100644 index cceb1f411a1..00000000000 Binary files a/dashboardv3/public/img/entity-icon/hadoop.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hbase.png b/dashboardv3/public/img/entity-icon/hbase.png deleted file mode 100644 index fd657dd169d..00000000000 Binary files a/dashboardv3/public/img/entity-icon/hbase.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hbase_column.png b/dashboardv3/public/img/entity-icon/hbase_column.png deleted file mode 100644 index 9cf9a38872e..00000000000 Binary files a/dashboardv3/public/img/entity-icon/hbase_column.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hbase_column_family.png b/dashboardv3/public/img/entity-icon/hbase_column_family.png deleted file mode 100644 index d89aaae0674..00000000000 Binary files a/dashboardv3/public/img/entity-icon/hbase_column_family.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hbase_table.png b/dashboardv3/public/img/entity-icon/hbase_table.png deleted file mode 100644 index d937443f9d6..00000000000 Binary files a/dashboardv3/public/img/entity-icon/hbase_table.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hdfs_path.png b/dashboardv3/public/img/entity-icon/hdfs_path.png deleted file mode 100644 index 778578690f8..00000000000 Binary files a/dashboardv3/public/img/entity-icon/hdfs_path.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hive.png b/dashboardv3/public/img/entity-icon/hive.png deleted file mode 100644 index 531837d58f0..00000000000 Binary files a/dashboardv3/public/img/entity-icon/hive.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hive_column.png b/dashboardv3/public/img/entity-icon/hive_column.png deleted file mode 100644 index 74753fa9470..00000000000 Binary files a/dashboardv3/public/img/entity-icon/hive_column.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hive_column_lineage.png b/dashboardv3/public/img/entity-icon/hive_column_lineage.png deleted file mode 100644 index 3a85f786b71..00000000000 Binary files a/dashboardv3/public/img/entity-icon/hive_column_lineage.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hive_db.png b/dashboardv3/public/img/entity-icon/hive_db.png deleted file mode 100644 index 216eaeb9dfa..00000000000 Binary files a/dashboardv3/public/img/entity-icon/hive_db.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hive_process.png b/dashboardv3/public/img/entity-icon/hive_process.png deleted file mode 100644 index 4083bcacd85..00000000000 Binary files a/dashboardv3/public/img/entity-icon/hive_process.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hive_process_execution.png b/dashboardv3/public/img/entity-icon/hive_process_execution.png deleted file mode 100644 index 4499724ac77..00000000000 Binary files a/dashboardv3/public/img/entity-icon/hive_process_execution.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hive_storagedesc.png b/dashboardv3/public/img/entity-icon/hive_storagedesc.png deleted file mode 100644 index ef9fd4801ef..00000000000 Binary files a/dashboardv3/public/img/entity-icon/hive_storagedesc.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hive_table.png b/dashboardv3/public/img/entity-icon/hive_table.png deleted file mode 100644 index d2209e8d40d..00000000000 Binary files a/dashboardv3/public/img/entity-icon/hive_table.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/hourglass.svg b/dashboardv3/public/img/entity-icon/hourglass.svg deleted file mode 100644 index aad49788c08..00000000000 --- a/dashboardv3/public/img/entity-icon/hourglass.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/dashboardv3/public/img/entity-icon/impala.png b/dashboardv3/public/img/entity-icon/impala.png deleted file mode 100644 index bd6b29990a6..00000000000 Binary files a/dashboardv3/public/img/entity-icon/impala.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/impala_column_lineage.png b/dashboardv3/public/img/entity-icon/impala_column_lineage.png deleted file mode 100755 index 3980326a1c7..00000000000 Binary files a/dashboardv3/public/img/entity-icon/impala_column_lineage.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/impala_process.png b/dashboardv3/public/img/entity-icon/impala_process.png deleted file mode 100755 index 3980326a1c7..00000000000 Binary files a/dashboardv3/public/img/entity-icon/impala_process.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/jms_topic.png b/dashboardv3/public/img/entity-icon/jms_topic.png deleted file mode 100644 index 4d08bc319e5..00000000000 Binary files a/dashboardv3/public/img/entity-icon/jms_topic.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/kafka.png b/dashboardv3/public/img/entity-icon/kafka.png deleted file mode 100644 index 4985375a9ae..00000000000 Binary files a/dashboardv3/public/img/entity-icon/kafka.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/kafka_consumer.png b/dashboardv3/public/img/entity-icon/kafka_consumer.png deleted file mode 100644 index 5951283ab04..00000000000 Binary files a/dashboardv3/public/img/entity-icon/kafka_consumer.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/kafka_consumer_group.png b/dashboardv3/public/img/entity-icon/kafka_consumer_group.png deleted file mode 100644 index 9b8e9561077..00000000000 Binary files a/dashboardv3/public/img/entity-icon/kafka_consumer_group.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/kafka_consumer_lineage.png b/dashboardv3/public/img/entity-icon/kafka_consumer_lineage.png deleted file mode 100644 index ab103f43bd2..00000000000 Binary files a/dashboardv3/public/img/entity-icon/kafka_consumer_lineage.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/kafka_producer.png b/dashboardv3/public/img/entity-icon/kafka_producer.png deleted file mode 100644 index be4d96b8084..00000000000 Binary files a/dashboardv3/public/img/entity-icon/kafka_producer.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/kafka_producer_lineage.png b/dashboardv3/public/img/entity-icon/kafka_producer_lineage.png deleted file mode 100644 index 48dd90d18b9..00000000000 Binary files a/dashboardv3/public/img/entity-icon/kafka_producer_lineage.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/kafka_topic.png b/dashboardv3/public/img/entity-icon/kafka_topic.png deleted file mode 100644 index 3eae9abf1b1..00000000000 Binary files a/dashboardv3/public/img/entity-icon/kafka_topic.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/ozone.png b/dashboardv3/public/img/entity-icon/ozone.png deleted file mode 100644 index 1b0a9284a2e..00000000000 Binary files a/dashboardv3/public/img/entity-icon/ozone.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/ozone_bucket.png b/dashboardv3/public/img/entity-icon/ozone_bucket.png deleted file mode 100644 index d7a39726b24..00000000000 Binary files a/dashboardv3/public/img/entity-icon/ozone_bucket.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/ozone_key.png b/dashboardv3/public/img/entity-icon/ozone_key.png deleted file mode 100644 index 2e64f837e0b..00000000000 Binary files a/dashboardv3/public/img/entity-icon/ozone_key.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/ozone_volume.png b/dashboardv3/public/img/entity-icon/ozone_volume.png deleted file mode 100644 index b00a41bf441..00000000000 Binary files a/dashboardv3/public/img/entity-icon/ozone_volume.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/process.png b/dashboardv3/public/img/entity-icon/process.png deleted file mode 100644 index 0b01d1b0939..00000000000 Binary files a/dashboardv3/public/img/entity-icon/process.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/rdbms.png b/dashboardv3/public/img/entity-icon/rdbms.png deleted file mode 100644 index f9dfa989554..00000000000 Binary files a/dashboardv3/public/img/entity-icon/rdbms.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/rdbms_column.png b/dashboardv3/public/img/entity-icon/rdbms_column.png deleted file mode 100644 index 8b05f352b7d..00000000000 Binary files a/dashboardv3/public/img/entity-icon/rdbms_column.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/rdbms_db.png b/dashboardv3/public/img/entity-icon/rdbms_db.png deleted file mode 100644 index b9200be8e56..00000000000 Binary files a/dashboardv3/public/img/entity-icon/rdbms_db.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/rdbms_table.png b/dashboardv3/public/img/entity-icon/rdbms_table.png deleted file mode 100644 index 3f6630ffd4d..00000000000 Binary files a/dashboardv3/public/img/entity-icon/rdbms_table.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/spark.png b/dashboardv3/public/img/entity-icon/spark.png deleted file mode 100644 index 27bf2f746d6..00000000000 Binary files a/dashboardv3/public/img/entity-icon/spark.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/spark_process.png b/dashboardv3/public/img/entity-icon/spark_process.png deleted file mode 100644 index 077b0351b31..00000000000 Binary files a/dashboardv3/public/img/entity-icon/spark_process.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/spark_table.png b/dashboardv3/public/img/entity-icon/spark_table.png deleted file mode 100644 index af90c24e694..00000000000 Binary files a/dashboardv3/public/img/entity-icon/spark_table.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/sqoop.png b/dashboardv3/public/img/entity-icon/sqoop.png deleted file mode 100644 index 3cd6345ef79..00000000000 Binary files a/dashboardv3/public/img/entity-icon/sqoop.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/sqoop_db.png b/dashboardv3/public/img/entity-icon/sqoop_db.png deleted file mode 100644 index fe46bc9423a..00000000000 Binary files a/dashboardv3/public/img/entity-icon/sqoop_db.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/sqoop_process.png b/dashboardv3/public/img/entity-icon/sqoop_process.png deleted file mode 100644 index e4757305e43..00000000000 Binary files a/dashboardv3/public/img/entity-icon/sqoop_process.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/storm.png b/dashboardv3/public/img/entity-icon/storm.png deleted file mode 100644 index 4549aa5d8e7..00000000000 Binary files a/dashboardv3/public/img/entity-icon/storm.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/storm_bolt.png b/dashboardv3/public/img/entity-icon/storm_bolt.png deleted file mode 100644 index 86d2f795932..00000000000 Binary files a/dashboardv3/public/img/entity-icon/storm_bolt.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/storm_spout.png b/dashboardv3/public/img/entity-icon/storm_spout.png deleted file mode 100644 index 0d1e1bead14..00000000000 Binary files a/dashboardv3/public/img/entity-icon/storm_spout.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/storm_topology.png b/dashboardv3/public/img/entity-icon/storm_topology.png deleted file mode 100644 index 6f705e0083e..00000000000 Binary files a/dashboardv3/public/img/entity-icon/storm_topology.png and /dev/null differ diff --git a/dashboardv3/public/img/entity-icon/table.png b/dashboardv3/public/img/entity-icon/table.png deleted file mode 100644 index b07049bc1e3..00000000000 Binary files a/dashboardv3/public/img/entity-icon/table.png and /dev/null differ diff --git a/dashboardv3/public/img/favicon.ico b/dashboardv3/public/img/favicon.ico deleted file mode 100644 index 5cd060fd19b..00000000000 Binary files a/dashboardv3/public/img/favicon.ico and /dev/null differ diff --git a/dashboardv3/public/img/loading.gif b/dashboardv3/public/img/loading.gif deleted file mode 100644 index 5b33f7e54f4..00000000000 Binary files a/dashboardv3/public/img/loading.gif and /dev/null differ diff --git a/dashboardv3/public/img/ring.gif b/dashboardv3/public/img/ring.gif deleted file mode 100644 index f18f441785c..00000000000 Binary files a/dashboardv3/public/img/ring.gif and /dev/null differ diff --git a/dashboardv3/public/index.html.tpl b/dashboardv3/public/index.html.tpl deleted file mode 100644 index f849e4d13a9..00000000000 --- a/dashboardv3/public/index.html.tpl +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - Atlas - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        - -
        - -
        -
        -
        -
        -
        -
        -
        -
        - - - - - - - \ No newline at end of file diff --git a/dashboardv3/public/js/App.js b/dashboardv3/public/js/App.js deleted file mode 100644 index 5593a776945..00000000000 --- a/dashboardv3/public/js/App.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['marionette'], function(Marionette) { - - var App = new Marionette.Application(); - - App.addRegions({ - rHeader: '#header', - rSideNav: '#sidebar-wrapper', - rContent: '#page-wrapper' - }); - - App.addInitializer(function() { - Backbone.history.start(); - }); - - return App; -}); \ No newline at end of file diff --git a/dashboardv3/public/js/collection/BaseCollection.js b/dashboardv3/public/js/collection/BaseCollection.js deleted file mode 100644 index 30f5b76d07e..00000000000 --- a/dashboardv3/public/js/collection/BaseCollection.js +++ /dev/null @@ -1,143 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'utils/Utils', - 'utils/CommonViewFunction', - 'backbone.paginator' -], function(require, Globals, Utils, CommonViewFunction) { - 'use strict'; - - var BaseCollection = Backbone.PageableCollection.extend( - /** @lends BaseCollection.prototype */ - { - /** - * BaseCollection's initialize function - * @augments Backbone.PageableCollection - * @constructs - */ - - initialize: function() { - this.sort_key = 'id'; - }, - comparator: function(key, value) { - key = key.get(this.sort_key); - value = value.get(this.sort_key); - return key > value ? 1 : key < value ? -1 : 0; - }, - sortByKey: function(sortKey) { - this.sort_key = sortKey; - this.sort(); - }, - /** - * state required for the PageableCollection - */ - state: { - firstPage: 0, - pageSize: Globals.settings.PAGE_SIZE - }, - mode: 'client', - /** - * override the parseRecords of PageableCollection for our use - */ - parseRecords: function(resp, options) { - this.responseData = { - dataType: resp.dataType, - query: resp.query, - queryType: resp.queryType, - requestId: resp.requestId - }; - try { - if (!this.modelAttrName) { - throw new Error("this.modelAttrName not defined for " + this); - } - return resp[this.modelAttrName]; - } catch (e) { - console.log(e); - } - }, - - //////////////////////////////////////////////////////////// - // Overriding backbone-pageable page handlers methods // - //////////////////////////////////////////////////////////// - getFirstPage: function(options) { - return this.getPage('first', _.extend({ - reset: true - }, options)); - }, - - getPreviousPage: function(options) { - return this.getPage("prev", _.extend({ - reset: true - }, options)); - }, - - getNextPage: function(options) { - return this.getPage("next", _.extend({ - reset: true - }, options)); - }, - - getLastPage: function(options) { - return this.getPage("last", _.extend({ - reset: true - }, options)); - }, - hasPrevious: function(options) { - return this.hasPreviousPage(); - }, - hasNext: function(options) { - return this.hasNextPage(); - } - ///////////////////////////// - // End overriding methods // - ///////////////////////////// - - }, - /** BaseCollection's Static Attributes */ - { - // Static functions - getTableCols: function(cols, collection, defaultSortDirection) { - var retCols = _.map(cols, function(v, k, l) { - var defaults = collection.constructor.tableCols[k]; - if (!defaults) { - //console.log("Error!! " + k + " not found in collection: " , collection); - defaults = {}; - } - return _.extend({ - 'name': k, - direction: defaultSortDirection ? defaultSortDirection : null, - }, defaults, v); - }); - return retCols; - }, - nonCrudOperation: function(url, requestMethod, options) { - var that = this; - options['beforeSend'] = CommonViewFunction.addRestCsrfCustomHeader; - if (options.data && typeof options.data === "object") { - options.data = JSON.stringify(options.data); - } - return Backbone.sync.call(this, null, this, _.extend({ - url: url, - type: requestMethod - }, options)); - } - }); - return BaseCollection; -}); \ No newline at end of file diff --git a/dashboardv3/public/js/collection/VCommonList.js b/dashboardv3/public/js/collection/VCommonList.js deleted file mode 100644 index d5b0a9ec965..00000000000 --- a/dashboardv3/public/js/collection/VCommonList.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VCommon', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VCommon, UrlLinks) { - 'use strict'; - var VCommonList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.baseURL + '', - - model: VCommon, - - initialize: function() { - this.modelName = 'VCommon'; - this.modelAttrName = ''; - }, - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VCommonList; -}); \ No newline at end of file diff --git a/dashboardv3/public/js/collection/VEntityList.js b/dashboardv3/public/js/collection/VEntityList.js deleted file mode 100644 index 645bc0c20b5..00000000000 --- a/dashboardv3/public/js/collection/VEntityList.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VEntity', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VEntity, UrlLinks) { - 'use strict'; - var VEntityList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.entitiesApiUrl(), - - model: VEntity, - - initialize: function() { - this.modelName = 'VEntity'; - this.modelAttrName = 'entityDefs'; - }, - parseRecords: function(resp, options) { - try { - // if (!this.modelAttrName) { - // throw new Error("this.modelAttrName not defined for " + this); - // } - if (resp.entity && resp.referredEntities) { - var obj = { - entity: resp.entity, - referredEntities: resp.referredEntities - } - return obj; - } else if (resp[this.modelAttrName]) { - return resp[this.modelAttrName]; - } else { - return resp - } - - } catch (e) { - console.log(e); - } - }, - getAdminData: function(options) { - var url = UrlLinks.adminApiUrl(); - options = _.extend({ - contentType: 'application/json', - dataType: 'json' - }, options); - return this.constructor.nonCrudOperation.call(this, url, 'POST', options); - } - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VEntityList; -}); \ No newline at end of file diff --git a/dashboardv3/public/js/collection/VGlossaryList.js b/dashboardv3/public/js/collection/VGlossaryList.js deleted file mode 100644 index 9c4918f2ff2..00000000000 --- a/dashboardv3/public/js/collection/VGlossaryList.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VGlossary', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VGlossary, UrlLinks) { - 'use strict'; - var VGlossaryList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.glossaryApiUrl(), - - model: VGlossary, - - initialize: function() { - this.modelName = 'VGlossary'; - this.modelAttrName = ''; - }, - parseRecords: function(resp, options) { - if (_.isEmpty(this.modelAttrName)) { - return resp; - } else { - return resp[this.modelAttrName] - } - }, - getCategory: function(options) { - var url = UrlLinks.categoryApiUrl({ "guid": options.guid, "related": options.related }), - apiOptions = _.extend({ - contentType: 'application/json', - dataType: 'json' - }, options.ajaxOptions); - return this.constructor.nonCrudOperation.call(this, url, 'GET', apiOptions); - }, - getTerm: function(options) { - var url = UrlLinks.termApiUrl({ "guid": options.guid, "related": options.related }), - apiOptions = _.extend({ - contentType: 'application/json', - dataType: 'json' - }, options.ajaxOptions); - return this.constructor.nonCrudOperation.call(this, url, 'GET', apiOptions); - } - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VGlossaryList; -}); \ No newline at end of file diff --git a/dashboardv3/public/js/collection/VLineageList.js b/dashboardv3/public/js/collection/VLineageList.js deleted file mode 100644 index bda649220ee..00000000000 --- a/dashboardv3/public/js/collection/VLineageList.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VLineage', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VLineage, UrlLinks) { - 'use strict'; - var VLineageList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.baseURL, - - model: VLineage, - - initialize: function() { - this.modelName = 'VLineage'; - this.modelAttrName = 'results'; - }, - getLineage: function(id, options) { - var url = UrlLinks.lineageApiUrl(id); - - options = _.extend({ - contentType: 'application/json', - dataType: 'json' - }, options); - - return this.constructor.nonCrudOperation.call(this, url, 'GET', options); - } - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VLineageList; -}); \ No newline at end of file diff --git a/dashboardv3/public/js/collection/VProfileList.js b/dashboardv3/public/js/collection/VProfileList.js deleted file mode 100644 index 06f0e110f72..00000000000 --- a/dashboardv3/public/js/collection/VProfileList.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VProfile' -], function(require, Globals, BaseCollection, VProfile) { - 'use strict'; - var VProfileList = BaseCollection.extend( - //Prototypal attributes - { - url: Globals.baseURL + '/api/atlas/entities', - - model: VProfile, - - initialize: function() { - this.modelName = 'VProfile'; - this.modelAttrName = 'definition'; - this.bindErrorEvents(); - } - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VProfileList; -}); \ No newline at end of file diff --git a/dashboardv3/public/js/collection/VRelationshipList.js b/dashboardv3/public/js/collection/VRelationshipList.js deleted file mode 100644 index 2fda826be17..00000000000 --- a/dashboardv3/public/js/collection/VRelationshipList.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VRelationship', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VRelationship, UrlLinks) { - 'use strict'; - var VRelationshipList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.baseURL, - - model: VRelationship, - - initialize: function() { - this.modelName = 'VRelationship'; - this.modelAttrName = 'results'; - }, - getRelationship: function(id, options) { - var url = UrlLinks.relationshipApiUrl(id); - - options = _.extend({ - contentType: 'application/json', - dataType: 'json' - }, options); - - return this.constructor.nonCrudOperation.call(this, url, 'GET', options); - } - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VRelationshipList; -}); \ No newline at end of file diff --git a/dashboardv3/public/js/collection/VSchemaList.js b/dashboardv3/public/js/collection/VSchemaList.js deleted file mode 100644 index fceaaa29ae0..00000000000 --- a/dashboardv3/public/js/collection/VSchemaList.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VSchema', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VSchema, UrlLinks) { - 'use strict'; - var VSchemaList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.baseURL, - model: VSchema, - initialize: function() { - this.modelName = 'VSchema'; - this.modelAttrName = 'results'; - }, - parseRecords: function(resp, options) { - try { - if (!this.modelAttrName) { - throw new Error("this.modelAttrName not defined for " + this); - } - this.keyList = resp[this.modelAttrName].dataType.attributeDefinitions; - if (resp[this.modelAttrName].dataType.superTypes) { - if (resp[this.modelAttrName].dataType.superTypes.indexOf("Asset") != -1) { - this.keyList.push({ - "name": "name", - "dataTypeName": "string", - "isComposite": false, - "isIndexable": true, - "isUnique": false, - "multiplicity": {}, - "reverseAttributeName": null - }) - } - } - var arr = []; - resp[this.modelAttrName].rows.forEach(function(d) { - arr.push(d); - }); - return arr; - } catch (e) { - console.log(e); - } - }, - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VSchemaList; -}); \ No newline at end of file diff --git a/dashboardv3/public/js/collection/VSearchList.js b/dashboardv3/public/js/collection/VSearchList.js deleted file mode 100644 index 227d3dc281f..00000000000 --- a/dashboardv3/public/js/collection/VSearchList.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VSearch', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VSearch, UrlLinks) { - 'use strict'; - var VSearchList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.searchApiUrl(), - - model: VSearch, - - initialize: function(options) { - _.extend(this, options); - this.modelName = 'VSearchList'; - this.modelAttrName = ''; - }, - parseRecords: function(resp, options) { - this.queryType = resp.queryType; - this.queryText = resp.queryText; - this.referredEntities = resp.referredEntities; - if (resp.attributes) { - this.dynamicTable = true; - var entities = []; - _.each(resp.attributes.values, function(obj) { - var temp = {}; - _.each(obj, function(val, index) { - var key = resp.attributes.name[index]; - if (key == "__guid") { - key = "guid" - } - temp[key] = val; - }); - entities.push(temp); - }); - return entities; - } else if (resp.entities) { - this.dynamicTable = false; - return resp.entities ? resp.entities : []; - } else { - return []; - } - }, - getExpimpAudit: function(params, options) { - var url = UrlLinks.expimpAudit(params); - - options = _.extend({ - contentType: 'application/json', - dataType: 'json', - }, options); - - return this.constructor.nonCrudOperation.call(this, url, 'GET', options); - }, - getBasicRearchResult: function(options) { - var url = UrlLinks.searchApiUrl('basic'); - - options = _.extend({ - contentType: 'application/json', - dataType: 'json', - }, options); - options.data = JSON.stringify(options.data); - - return this.constructor.nonCrudOperation.call(this, url, 'POST', options); - } - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VSearchList; -}); \ No newline at end of file diff --git a/dashboardv3/public/js/collection/VTagList.js b/dashboardv3/public/js/collection/VTagList.js deleted file mode 100644 index cfbf767009a..00000000000 --- a/dashboardv3/public/js/collection/VTagList.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -define(['require', - 'utils/Globals', - 'collection/BaseCollection', - 'models/VTag', - 'utils/UrlLinks' -], function(require, Globals, BaseCollection, VTag, UrlLinks) { - 'use strict'; - var VTagList = BaseCollection.extend( - //Prototypal attributes - { - url: UrlLinks.classificationDefApiUrl(), - model: VTag, - initialize: function() { - this.modelName = 'VTag'; - this.modelAttrName = 'classificationDefs'; - }, - parseRecords: function(resp, options) { - try { - if (!this.modelAttrName) { - throw new Error("this.modelAttrName not defined for " + this); - } - if (resp[this.modelAttrName]) { - return resp[this.modelAttrName]; - } else { - return resp - } - - } catch (e) { - console.log(e); - } - }, - }, - //Static Class Members - { - /** - * Table Cols to be passed to Backgrid - * UI has to use this as base and extend this. - * - */ - tableCols: {} - } - ); - return VTagList; -}); \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/LICENSE b/dashboardv3/public/js/external_lib/atlas-lineage/LICENSE deleted file mode 100644 index d6ea1531095..00000000000 --- a/dashboardv3/public/js/external_lib/atlas-lineage/LICENSE +++ /dev/null @@ -1,204 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. - - -======================================================================= \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/dist/index.js b/dashboardv3/public/js/external_lib/atlas-lineage/dist/index.js deleted file mode 100644 index b31ee491136..00000000000 --- a/dashboardv3/public/js/external_lib/atlas-lineage/dist/index.js +++ /dev/null @@ -1 +0,0 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("platform"),require("dagreD3")):"function"==typeof define&&define.amd?define(["platform","dagreD3"],e):"object"==typeof exports?exports.LineageHelper=e(require("platform"),require("dagreD3")):t.LineageHelper=e(t.platform,t.dagreD3)}(window,(function(t,e){return function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:r})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(r,i,function(e){return t[e]}.bind(null,i));return r},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=10)}([,function(e,n){e.exports=t},function(t,n){t.exports=e},,,,,,,function(t,e,n){},function(t,e,n){"use strict";n.r(e),n.d(e,"default",(function(){return Br}));var r=n(2),i=n.n(r);function o(){}var a=function(t){return null==t?o:function(){return this.querySelector(t)}};function s(){return[]}var u=function(t){return null==t?s:function(){return this.querySelectorAll(t)}},l=function(t){return function(){return this.matches(t)}},c=function(t){return new Array(t.length)};function h(t,e){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=e}h.prototype={constructor:h,appendChild:function(t){return this._parent.insertBefore(t,this._next)},insertBefore:function(t,e){return this._parent.insertBefore(t,e)},querySelector:function(t){return this._parent.querySelector(t)},querySelectorAll:function(t){return this._parent.querySelectorAll(t)}};function f(t,e,n,r,i,o){for(var a,s=0,u=e.length,l=o.length;se?1:t>=e?0:NaN}var g="http://www.w3.org/1999/xhtml",v={svg:"http://www.w3.org/2000/svg",xhtml:g,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"},y=function(t){var e=t+="",n=e.indexOf(":");return n>=0&&"xmlns"!==(e=t.slice(0,n))&&(t=t.slice(n+1)),v.hasOwnProperty(e)?{space:v[e],local:t}:t};function m(t){return function(){this.removeAttribute(t)}}function w(t){return function(){this.removeAttributeNS(t.space,t.local)}}function b(t,e){return function(){this.setAttribute(t,e)}}function x(t,e){return function(){this.setAttributeNS(t.space,t.local,e)}}function k(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttribute(t):this.setAttribute(t,n)}}function E(t,e){return function(){var n=e.apply(this,arguments);null==n?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,n)}}var T=function(t){return t.ownerDocument&&t.ownerDocument.defaultView||t.document&&t||t.defaultView};function N(t){return function(){this.style.removeProperty(t)}}function O(t,e,n){return function(){this.style.setProperty(t,e,n)}}function S(t,e,n){return function(){var r=e.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,n)}}function P(t,e){return t.style.getPropertyValue(e)||T(t).getComputedStyle(t,null).getPropertyValue(e)}function A(t){return function(){delete this[t]}}function M(t,e){return function(){this[t]=e}}function z(t,e){return function(){var n=e.apply(this,arguments);null==n?delete this[t]:this[t]=n}}function j(t){return t.trim().split(/^|\s+/)}function D(t){return t.classList||new B(t)}function B(t){this._node=t,this._names=j(t.getAttribute("class")||"")}function C(t,e){for(var n=D(t),r=-1,i=e.length;++r=0&&(this._names.splice(e,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};function q(){this.textContent=""}function U(t){return function(){this.textContent=t}}function F(t){return function(){var e=t.apply(this,arguments);this.textContent=null==e?"":e}}function H(){this.innerHTML=""}function V(t){return function(){this.innerHTML=t}}function X(t){return function(){var e=t.apply(this,arguments);this.innerHTML=null==e?"":e}}function Y(){this.nextSibling&&this.parentNode.appendChild(this)}function Z(){this.previousSibling&&this.parentNode.insertBefore(this,this.parentNode.firstChild)}function W(t){return function(){var e=this.ownerDocument,n=this.namespaceURI;return n===g&&e.documentElement.namespaceURI===g?e.createElement(t):e.createElementNS(n,t)}}function K(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}var Q=function(t){var e=y(t);return(e.local?K:W)(e)};function J(){return null}function tt(){var t=this.parentNode;t&&t.removeChild(this)}function et(){var t=this.cloneNode(!1),e=this.parentNode;return e?e.insertBefore(t,this.nextSibling):t}function nt(){var t=this.cloneNode(!0),e=this.parentNode;return e?e.insertBefore(t,this.nextSibling):t}var rt={},it=null;"undefined"!=typeof document&&("onmouseenter"in document.documentElement||(rt={mouseenter:"mouseover",mouseleave:"mouseout"}));function ot(t,e,n){return t=at(t,e,n),function(e){var n=e.relatedTarget;n&&(n===this||8&n.compareDocumentPosition(this))||t.call(this,e)}}function at(t,e,n){return function(r){var i=it;it=r;try{t.call(this,this.__data__,e,n)}finally{it=i}}}function st(t){return t.trim().split(/^|\s+/).map((function(t){var e="",n=t.indexOf(".");return n>=0&&(e=t.slice(n+1),t=t.slice(0,n)),{type:t,name:e}}))}function ut(t){return function(){var e=this.__on;if(e){for(var n,r=0,i=-1,o=e.length;r=k&&(k=x+1);!(b=_[k])&&++k=0;)(r=i[o])&&(a&&4^r.compareDocumentPosition(a)&&a.parentNode.insertBefore(r,a),a=r);return this},sort:function(t){function e(e,n){return e&&n?t(e.__data__,n.__data__):!e-!n}t||(t=d);for(var n=this._groups,r=n.length,i=new Array(r),o=0;o1?this.each((null==e?N:"function"==typeof e?S:O)(t,e,null==n?"":n)):P(this.node(),t)},property:function(t,e){return arguments.length>1?this.each((null==e?A:"function"==typeof e?z:M)(t,e)):this.node()[t]},classed:function(t,e){var n=j(t+"");if(arguments.length<2){for(var r=D(this.node()),i=-1,o=n.length;++i=0&&(n=t.slice(r+1),t=t.slice(0,r)),t&&!e.hasOwnProperty(t))throw new Error("unknown type: "+t);return{type:t,name:n}}))}function Nt(t,e){for(var n,r=0,i=t.length;r0)for(var n,r,i=new Array(n),o=0;o=0&&e._call.call(null,t),e=e._next;--Ut}()}finally{Ut=0,function(){var t,e,n=Bt,r=1/0;for(;n;)n._call?(r>n._time&&(r=n._time),t=n,n=n._next):(e=n._next,n._next=null,n=t?t._next=e:Bt=e);Ct=t,ne(r)}(),Vt=0}}function ee(){var t=Yt.now(),e=t-$t;e>1e3&&(Xt-=e,$t=t)}function ne(t){Ut||(Ft&&(Ft=clearTimeout(Ft)),t-Vt>24?(t<1/0&&(Ft=setTimeout(te,t-Yt.now()-Xt)),Ht&&(Ht=clearInterval(Ht))):(Ht||($t=Yt.now(),Ht=setInterval(ee,1e3)),Ut=1,Zt(te)))}Qt.prototype=Jt.prototype={constructor:Qt,restart:function(t,e,n){if("function"!=typeof t)throw new TypeError("callback is not a function");n=(null==n?Wt():+n)+(null==e?0:+e),this._next||Ct===this||(Ct?Ct._next=this:Bt=this,Ct=this),this._call=t,this._time=n,ne()},stop:function(){this._call&&(this._call=null,this._time=1/0,ne())}};var re=function(t,e,n){var r=new Qt;return e=null==e?0:+e,r.restart((function(n){r.stop(),t(n+e)}),e,n),r},ie=St("start","end","cancel","interrupt"),oe=[],ae=function(t,e,n,r,i,o){var a=t.__transition;if(a){if(n in a)return}else t.__transition={};!function(t,e,n){var r,i=t.__transition;function o(u){var l,c,h,f;if(1!==n.state)return s();for(l in i)if((f=i[l]).name===n.name){if(3===f.state)return re(o);4===f.state?(f.state=6,f.timer.stop(),f.on.call("interrupt",t,t.__data__,f.index,f.group),delete i[l]):+l0)throw new Error("too late; already scheduled");return n}function ue(t,e){var n=le(t,e);if(n.state>3)throw new Error("too late; already running");return n}function le(t,e){var n=t.__transition;if(!n||!(n=n[e]))throw new Error("transition not found");return n}var ce,he,fe,pe,de=function(t,e){var n,r,i,o=t.__transition,a=!0;if(o){for(i in e=null==e?null:e+"",o)(n=o[i]).name===e?(r=n.state>2&&n.state<5,n.state=6,n.timer.stop(),n.on.call(r?"interrupt":"cancel",t,t.__data__,n.index,n.group),delete o[i]):a=!1;a&&delete t.__transition}},ge=function(t,e){return t=+t,e=+e,function(n){return t*(1-n)+e*n}},ve=180/Math.PI,ye={translateX:0,translateY:0,rotate:0,skewX:0,scaleX:1,scaleY:1},me=function(t,e,n,r,i,o){var a,s,u;return(a=Math.sqrt(t*t+e*e))&&(t/=a,e/=a),(u=t*n+e*r)&&(n-=t*u,r-=e*u),(s=Math.sqrt(n*n+r*r))&&(n/=s,r/=s,u/=s),t*r180?e+=360:e-t>180&&(t+=360),o.push({i:n.push(i(n)+"rotate(",null,r)-2,x:ge(t,e)})):e&&n.push(i(n)+"rotate("+e+r)}(o.rotate,a.rotate,s,u),function(t,e,n,o){t!==e?o.push({i:n.push(i(n)+"skewX(",null,r)-2,x:ge(t,e)}):e&&n.push(i(n)+"skewX("+e+r)}(o.skewX,a.skewX,s,u),function(t,e,n,r,o,a){if(t!==n||e!==r){var s=o.push(i(o)+"scale(",null,",",null,")");a.push({i:s-4,x:ge(t,n)},{i:s-2,x:ge(e,r)})}else 1===n&&1===r||o.push(i(o)+"scale("+n+","+r+")")}(o.scaleX,o.scaleY,a.scaleX,a.scaleY,s,u),o=a=null,function(t){for(var e,n=-1,r=u.length;++n>8&15|e>>4&240,e>>4&15|240&e,(15&e)<<4|15&e,1):8===n?Fe(e>>24&255,e>>16&255,e>>8&255,(255&e)/255):4===n?Fe(e>>12&15|e>>8&240,e>>8&15|e>>4&240,e>>4&15|240&e,((15&e)<<4|15&e)/255):null):(e=ze.exec(t))?new Ve(e[1],e[2],e[3],1):(e=je.exec(t))?new Ve(255*e[1]/100,255*e[2]/100,255*e[3]/100,1):(e=De.exec(t))?Fe(e[1],e[2],e[3],e[4]):(e=Be.exec(t))?Fe(255*e[1]/100,255*e[2]/100,255*e[3]/100,e[4]):(e=Ce.exec(t))?We(e[1],e[2]/100,e[3]/100,1):(e=Ie.exec(t))?We(e[1],e[2]/100,e[3]/100,e[4]):Le.hasOwnProperty(t)?Ue(Le[t]):"transparent"===t?new Ve(NaN,NaN,NaN,0):null}function Ue(t){return new Ve(t>>16&255,t>>8&255,255&t,1)}function Fe(t,e,n,r){return r<=0&&(t=e=n=NaN),new Ve(t,e,n,r)}function He(t){return t instanceof Oe||(t=qe(t)),t?new Ve((t=t.rgb()).r,t.g,t.b,t.opacity):new Ve}function $e(t,e,n,r){return 1===arguments.length?He(t):new Ve(t,e,n,null==r?1:r)}function Ve(t,e,n,r){this.r=+t,this.g=+e,this.b=+n,this.opacity=+r}function Xe(){return"#"+Ze(this.r)+Ze(this.g)+Ze(this.b)}function Ye(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"rgb(":"rgba(")+Math.max(0,Math.min(255,Math.round(this.r)||0))+", "+Math.max(0,Math.min(255,Math.round(this.g)||0))+", "+Math.max(0,Math.min(255,Math.round(this.b)||0))+(1===t?")":", "+t+")")}function Ze(t){return((t=Math.max(0,Math.min(255,Math.round(t)||0)))<16?"0":"")+t.toString(16)}function We(t,e,n,r){return r<=0?t=e=n=NaN:n<=0||n>=1?t=e=NaN:e<=0&&(t=NaN),new Qe(t,e,n,r)}function Ke(t){if(t instanceof Qe)return new Qe(t.h,t.s,t.l,t.opacity);if(t instanceof Oe||(t=qe(t)),!t)return new Qe;if(t instanceof Qe)return t;var e=(t=t.rgb()).r/255,n=t.g/255,r=t.b/255,i=Math.min(e,n,r),o=Math.max(e,n,r),a=NaN,s=o-i,u=(o+i)/2;return s?(a=e===o?(n-r)/s+6*(n0&&u<1?0:a,new Qe(a,s,u,t.opacity)}function Qe(t,e,n,r){this.h=+t,this.s=+e,this.l=+n,this.opacity=+r}function Je(t,e,n){return 255*(t<60?e+(n-e)*t/60:t<180?n:t<240?e+(n-e)*(240-t)/60:e)}function tn(t,e,n,r,i){var o=t*t,a=o*t;return((1-3*t+3*o-a)*e+(4-6*o+3*a)*n+(1+3*t+3*o-3*a)*r+a*i)/6}Te(Oe,qe,{copy:function(t){return Object.assign(new this.constructor,this,t)},displayable:function(){return this.rgb().displayable()},hex:Re,formatHex:Re,formatHsl:function(){return Ke(this).formatHsl()},formatRgb:Ge,toString:Ge}),Te(Ve,$e,Ne(Oe,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new Ve(this.r*t,this.g*t,this.b*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new Ve(this.r*t,this.g*t,this.b*t,this.opacity)},rgb:function(){return this},displayable:function(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:Xe,formatHex:Xe,formatRgb:Ye,toString:Ye})),Te(Qe,(function(t,e,n,r){return 1===arguments.length?Ke(t):new Qe(t,e,n,null==r?1:r)}),Ne(Oe,{brighter:function(t){return t=null==t?1/.7:Math.pow(1/.7,t),new Qe(this.h,this.s,this.l*t,this.opacity)},darker:function(t){return t=null==t?.7:Math.pow(.7,t),new Qe(this.h,this.s,this.l*t,this.opacity)},rgb:function(){var t=this.h%360+360*(this.h<0),e=isNaN(t)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*e,i=2*n-r;return new Ve(Je(t>=240?t-240:t+120,i,r),Je(t,i,r),Je(t<120?t+240:t-120,i,r),this.opacity)},displayable:function(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl:function(){var t=this.opacity;return(1===(t=isNaN(t)?1:Math.max(0,Math.min(1,t)))?"hsl(":"hsla(")+(this.h||0)+", "+100*(this.s||0)+"%, "+100*(this.l||0)+"%"+(1===t?")":", "+t+")")}}));var en=function(t){return function(){return t}};function nn(t,e){return function(n){return t+n*e}}function rn(t){return 1==(t=+t)?on:function(e,n){return n-e?function(t,e,n){return t=Math.pow(t,n),e=Math.pow(e,n)-t,n=1/n,function(r){return Math.pow(t+r*e,n)}}(e,n,t):en(isNaN(e)?n:e)}}function on(t,e){var n=e-t;return n?nn(t,n):en(isNaN(t)?e:t)}var an=function t(e){var n=rn(e);function r(t,e){var r=n((t=$e(t)).r,(e=$e(e)).r),i=n(t.g,e.g),o=n(t.b,e.b),a=on(t.opacity,e.opacity);return function(e){return t.r=r(e),t.g=i(e),t.b=o(e),t.opacity=a(e),t+""}}return r.gamma=t,r}(1);function sn(t){return function(e){var n,r,i=e.length,o=new Array(i),a=new Array(i),s=new Array(i);for(n=0;n=1?(n=1,e-1):Math.floor(n*e),i=t[r],o=t[r+1],a=r>0?t[r-1]:2*i-o,s=ro&&(i=e.slice(o,i),s[a]?s[a]+=i:s[++a]=i),(n=n[0])===(r=r[0])?s[a]?s[a]+=r:s[++a]=r:(s[++a]=null,u.push({i:a,x:ge(n,r)})),o=ln.lastIndex;return o=0&&(t=t.slice(0,e)),!t||"start"===t}))}(e)?se:ue;return function(){var a=o(this,t),s=a.on;s!==r&&(i=(r=s).copy()).on(e,n),a.on=i}}var Sn=yt.prototype.constructor;function Pn(t){return function(){this.style.removeProperty(t)}}function An(t,e,n){return function(r){this.style.setProperty(t,e.call(this,r),n)}}function Mn(t,e,n){var r,i;function o(){var o=e.apply(this,arguments);return o!==i&&(r=(i=o)&&An(t,o,n)),r}return o._value=e,o}function zn(t){return function(e){this.textContent=t.call(this,e)}}function jn(t){var e,n;function r(){var r=t.apply(this,arguments);return r!==n&&(e=(n=r)&&zn(r)),e}return r._value=t,r}var Dn=0;function Bn(t,e,n,r){this._groups=t,this._parents=e,this._name=n,this._id=r}function Cn(){return++Dn}var In=yt.prototype;Bn.prototype=function(t){return yt().transition(t)}.prototype={constructor:Bn,select:function(t){var e=this._name,n=this._id;"function"!=typeof t&&(t=a(t));for(var r=this._groups,i=r.length,o=new Array(i),s=0;sr?(r+i)/2:Math.min(0,r)||Math.max(0,i),a>o?(o+a)/2:Math.min(0,o)||Math.max(0,a))}var Qn=function(t){return function(){return t}};function Jn(t,e,n,r,i,o,a,s,u,l){this.target=t,this.type=e,this.subject=n,this.identifier=r,this.active=i,this.x=o,this.y=a,this.dx=s,this.dy=u,this._=l}function tr(){return!it.ctrlKey&&!it.button}function er(){return this.parentNode}function nr(t){return null==t?{x:it.x,y:it.y}:t}function rr(){return navigator.maxTouchPoints||"ontouchstart"in this}Jn.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};var ir=function(){var t,e,n,r,i=tr,o=er,a=nr,s=rr,u={},l=St("start","drag","end"),c=0,h=0;function f(t){t.on("mousedown.drag",p).filter(s).on("touchstart.drag",v).on("touchmove.drag",y).on("touchend.drag touchcancel.drag",m).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function p(){if(!r&&i.apply(this,arguments)){var a=_("mouse",o.apply(this,arguments),Gt,this,arguments);a&&(mt(it.view).on("mousemove.drag",d,!0).on("mouseup.drag",g,!0),Mt(it.view),Pt(),n=!1,t=it.clientX,e=it.clientY,a("start"))}}function d(){if(At(),!n){var r=it.clientX-t,i=it.clientY-e;n=r*r+i*i>h}u.mouse("drag")}function g(){mt(it.view).on("mousemove.drag mouseup.drag",null),zt(it.view,n),At(),u.mouse("end")}function v(){if(i.apply(this,arguments)){var t,e,n=it.changedTouches,r=o.apply(this,arguments),a=n.length;for(t=0;t1e-6)if(Math.abs(c*s-u*l)>1e-6&&i){var f=n-o,p=r-a,d=s*s+u*u,g=f*f+p*p,v=Math.sqrt(d),y=Math.sqrt(h),m=i*Math.tan((or-Math.acos((d+h-g)/(2*v*y)))/2),_=m/y,w=m/v;Math.abs(_-1)>1e-6&&(this._+="L"+(t+_*l)+","+(e+_*c)),this._+="A"+i+","+i+",0,0,"+ +(c*f>l*p)+","+(this._x1=t+w*s)+","+(this._y1=e+w*u)}else this._+="L"+(this._x1=t)+","+(this._y1=e);else;},arc:function(t,e,n,r,i,o){t=+t,e=+e,o=!!o;var a=(n=+n)*Math.cos(r),s=n*Math.sin(r),u=t+a,l=e+s,c=1^o,h=o?r-i:i-r;if(n<0)throw new Error("negative radius: "+n);null===this._x1?this._+="M"+u+","+l:(Math.abs(this._x1-u)>1e-6||Math.abs(this._y1-l)>1e-6)&&(this._+="L"+u+","+l),n&&(h<0&&(h=h%ar+ar),h>sr?this._+="A"+n+","+n+",0,1,"+c+","+(t-a)+","+(e-s)+"A"+n+","+n+",0,1,"+c+","+(this._x1=u)+","+(this._y1=l):h>1e-6&&(this._+="A"+n+","+n+",0,"+ +(h>=or)+","+c+","+(this._x1=t+n*Math.cos(i))+","+(this._y1=e+n*Math.sin(i))))},rect:function(t,e,n,r){this._+="M"+(this._x0=this._x1=+t)+","+(this._y0=this._y1=+e)+"h"+ +n+"v"+ +r+"h"+-n+"Z"},toString:function(){return this._}};var cr=lr,hr=function(t){return function(){return t}};function fr(t){this._context=t}fr.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,e){switch(t=+t,e=+e,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,e):this._context.moveTo(t,e);break;case 1:this._point=2;default:this._context.lineTo(t,e)}}};var pr=function(t){return new fr(t)};function dr(t){return t[0]}function gr(t){return t[1]}var vr=n(1),yr=n.n(vr),mr={entityStateReadOnly:{ACTIVE:!1,DELETED:!0,STATUS_ACTIVE:!1,STATUS_DELETED:!0}},_r={nodeArrowDistance:24,refreshGraphForSafari:function(t){t.edgeEl.each((function(t){var e=this,n=$(this).find("pattern");setTimeout((function(t){$(e).find("defs").append(n)}),500)}))},refreshGraphForIE:function(t){var e=t.edgePathEl,n=0;e.each((function(t){var e=$(this).find("marker");$(this).find("marker").remove();var r=this;++n,setTimeout((function(t){$(r).find("defs").append(e),0===--n&&(this.$(".fontLoader").hide(),this.$("svg").fadeTo(1e3,1))}),1e3)}))},dragNode:function(t){var e=this,n=t.g,r=t.svg,i=t.guid,o=(t.edgePathEl,{dragmove:function(t,e){var r=this,i=mt(t),o=n.node(e),a=o.x,s=o.y;o.x+=it.dx,o.y+=it.dy,i.attr("transform","translate("+o.x+","+o.y+")");var u=o.x-a,l=o.y-s;n.edges().forEach((function(t){if(t.v==e||t.w==e){var i=n.edge(t.v,t.w);r.translateEdge(i,u,l),mt(i.elem).select("path").attr("d",r.calcPoints(t))}}))},translateEdge:function(t,e,n){t.points.forEach((function(t){t.x=t.x+e,t.y=t.y+n}))},calcPoints:function(t){var e=n.edge(t.v,t.w),r=n.node(t.v),i=n.node(t.w),o=e.points.slice(1,e.points.length-1);e.points.slice(1,e.points.length-1);return o.unshift(this.intersectRect(r,o[0])),o.push(this.intersectRect(i,o[o.length-1])),function(){var t=dr,e=gr,n=hr(!0),r=null,i=pr,o=null;function a(a){var s,u,l,c=a.length,h=!1;for(null==r&&(o=i(l=cr())),s=0;s<=c;++s)!(sMath.abs(a)*c?(s<0&&(c=-c),h=0===s?0:c*a/s,f=c):(a<0&&(l=-l),h=l,f=0===a?0:l*s/a),{x:r+h,y:o+f}}}),a=ir().on("drag",(function(t){o.dragmove.call(o,this,t)})),s=ir().on("drag",(function(t){o.translateEdge(n.edge(t.v,t.w),it.dx,it.dy);var e=n.edge(t.v,t.w);mt(e.elem).select("path").attr("d",o.calcPoints(t))}));a(r.selectAll("g.node")),s(r.selectAll("g.edgePath"))},zoomIn:function(t){var e=t.svg,n=t.scaleFactor,r=void 0===n?1.3:n;this.d3Zoom.scaleBy(e.transition().duration(750),r)},zoomOut:function(t){var e=t.svg,n=t.scaleFactor,r=void 0===n?.8:n;this.d3Zoom.scaleBy(e.transition().duration(750),r)},zoom:function(t){var e=t.svg,n=t.xa,r=t.ya,i=t.scale;e.transition().duration(750).call(this.d3Zoom.transform,Fn.translate(n,r).scale(i))},fitToScreen:function(t){var e=t.svg,n=e.node(),r=n.getBBox(),i=n.parentElement,o=i.clientWidth,a=i.clientHeight,s=r.width,u=r.height,l=r.x+s/2,c=r.y+u/2,h=(h||.95)/Math.max(s/o,u/a),f=o/2-h*l,p=a/2-h*c;this.zoom({svg:e,xa:f,ya:p,scale:h})},centerNode:function(t){var e=t.guid,n=t.g,r=t.svg,i=t.svgGroupEl,o=(t.edgePathEl,t.width),a=t.height,s=t.fitToScreen,u=t.onCenterZoomed,l=t.isSelected;this.d3Zoom=function(){var t,e,n=Vn,r=Xn,i=Kn,o=Zn,a=Wn,s=[0,1/0],u=[[-1/0,-1/0],[1/0,1/0]],l=250,c=It,h=St("start","zoom","end"),f=0;function p(t){t.property("__zoom",Yn).on("wheel.zoom",w).on("mousedown.zoom",b).on("dblclick.zoom",x).filter(a).on("touchstart.zoom",k).on("touchmove.zoom",E).on("touchend.zoom touchcancel.zoom",T).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function d(t,e){return(e=Math.max(s[0],Math.min(s[1],e)))===t.k?t:new Un(e,t.x,t.y)}function g(t,e,n){var r=e[0]-n[0]*t.k,i=e[1]-n[1]*t.k;return r===t.x&&i===t.y?t:new Un(t.k,r,i)}function v(t){return[(+t[0][0]+ +t[1][0])/2,(+t[0][1]+ +t[1][1])/2]}function y(t,e,n){t.on("start.zoom",(function(){m(this,arguments).start()})).on("interrupt.zoom end.zoom",(function(){m(this,arguments).end()})).tween("zoom",(function(){var t=this,i=arguments,o=m(t,i),a=r.apply(t,i),s=null==n?v(a):"function"==typeof n?n.apply(t,i):n,u=Math.max(a[1][0]-a[0][0],a[1][1]-a[0][1]),l=t.__zoom,h="function"==typeof e?e.apply(t,i):e,f=c(l.invert(s).concat(u/l.k),h.invert(s).concat(u/h.k));return function(t){if(1===t)t=h;else{var e=f(t),n=u/e[2];t=new Un(n,s[0]-e[0]*n,s[1]-e[1]*n)}o.zoom(null,t)}}))}function m(t,e,n){return!n&&t.__zooming||new _(t,e)}function _(t,e){this.that=t,this.args=e,this.active=0,this.extent=r.apply(t,e),this.taps=0}function w(){if(n.apply(this,arguments)){var t=m(this,arguments),e=this.__zoom,r=Math.max(s[0],Math.min(s[1],e.k*Math.pow(2,o.apply(this,arguments)))),a=Gt(this);if(t.wheel)t.mouse[0][0]===a[0]&&t.mouse[0][1]===a[1]||(t.mouse[1]=e.invert(t.mouse[0]=a)),clearTimeout(t.wheel);else{if(e.k===r)return;t.mouse=[a,e.invert(a)],de(this),t.start()}$n(),t.wheel=setTimeout(l,150),t.zoom("mouse",i(g(d(e,r),t.mouse[0],t.mouse[1]),t.extent,u))}function l(){t.wheel=null,t.end()}}function b(){if(!e&&n.apply(this,arguments)){var t=m(this,arguments,!0),r=mt(it.view).on("mousemove.zoom",l,!0).on("mouseup.zoom",c,!0),o=Gt(this),a=it.clientX,s=it.clientY;Mt(it.view),Hn(),t.mouse=[o,this.__zoom.invert(o)],de(this),t.start()}function l(){if($n(),!t.moved){var e=it.clientX-a,n=it.clientY-s;t.moved=e*e+n*n>f}t.zoom("mouse",i(g(t.that.__zoom,t.mouse[0]=Gt(t.that),t.mouse[1]),t.extent,u))}function c(){r.on("mousemove.zoom mouseup.zoom",null),zt(it.view,t.moved),$n(),t.end()}}function x(){if(n.apply(this,arguments)){var t=this.__zoom,e=Gt(this),o=t.invert(e),a=t.k*(it.shiftKey?.5:2),s=i(g(d(t,a),e,o),r.apply(this,arguments),u);$n(),l>0?mt(this).transition().duration(l).call(y,s,e):mt(this).call(p.transform,s)}}function k(){if(n.apply(this,arguments)){var e,r,i,o,a=it.touches,s=a.length,u=m(this,arguments,it.changedTouches.length===s);for(Hn(),r=0;rg[id='"+e+"']"),h=(this.d3Zoom.scaleExtent([.01,50]).on("zoom",(function(){i.attr("transform",it.transform)})),null),f=null;if(c.empty()){if(s)return void this.fitToScreen({svg:r});h=n.graph().width/2,f=n.graph().height/2}else{var p=c.attr("transform").replace(/[^0-9\-.,]/g,"").split(",");h=p[0],f=p[1]}var d=-(1.2*h-o/2),g=-(1.2*f-a/2);this.zoom({svg:r,xa:d,ya:g,scale:1.2}),l?r.transition().duration(750).call(this.d3Zoom.transform,Fn.translate(d,g).scale(1.2)):r.call(this.d3Zoom.transform,Fn.translate(d,g).scale(1.2)),u&&u({newScale:1.2,newTranslate:[d,g],d3Zoom:this.d3Zoom,selectedNodeEl:c})},getToolTipDirection:function(t){var e=t.el,n=mt("body").node().getBoundingClientRect().width,r=mt(e).node().getBoundingClientRect(),i="e";return n-r.left<330?(i=n-r.left<330&&r.top<400?"sw":"w",n-r.left<330&&r.top>600&&(i="nw")):r.top>600?(i=n-r.left<330&&r.top>600?"nw":"n",r.left<50&&(i="ne")):r.top<400&&(i=r.left<50?"se":"s"),i},onHoverFade:function(t){var e=t.svg,n=t.g,r=t.mouseenter,i=t.nodesToHighlight,o=t.hoveredNode;return function(t){var i=e.selectAll(".node"),a=e.selectAll(".edgePath");if(r){e.classed("hover",!0);var s=n.successors(o),u=n.predecessors(o);t=s.concat(u);i.classed("hover-active-node",(function(e,n,r){return!!function(t,e,n){if(t===n||e&&e.length&&-1!=e.indexOf(n))return!0}(o,t,e)})),a.classed("hover-active-path",(function(t){return!!(t.v===o||t.w===o?1:0)}))}else e.classed("hover",!1),i.classed("hover-active-node",!1),a.classed("hover-active-path",!1)}(i)},getBaseUrl:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:window.location.pathname;return t.replace(/\/[\w-]+.(jsp|html)|\/+$/gi,"")},getEntityIconPath:function(t){var e=t.entityData,n=t.errorUrl,r=t.imgBasePath,i=this.getBaseUrl()+(r||"/img/entity-icon/");if(e){var o=function(t){return i+(mr.entityStateReadOnly[l]?"disabled/"+t:t)},a=function(){return c?mr.entityStateReadOnly[l]?i+"disabled/process.png":i+"process.png":mr.entityStateReadOnly[l]?i+"disabled/table.png":i+"table.png"},s=e.typeName,u=e.serviceType,l=e.status,c=e.isProcess;if(n){if(n.indexOf("table.png")>-1||n.indexOf("process.png")>-1)return null;var h=!(!n||!n.match("entity-icon/"+s+".png|disabled/"+s+".png"));return u&&h?o(u+".png"):a()}return s?o(s+".png"):u?o(u+".png"):a()}},base64Encode:function(t,e){var n=new FileReader;n.addEventListener("load",(function(){return e(n.result)})),n.readAsDataURL(t)},imgShapeRender:function(t,e,n,r){var i=r.dagreD3,o=r.defsEl,a=r.imgBasePath,s=r.guid,u=r.isRankdirToBottom,l=this,c=s,h=this.getEntityIconPath({entityData:n,imgBasePath:a}),f=h.split("/").pop();if(void 0===this.imageObject&&(this.imageObject={}),n.isDeleted&&(f="deleted_"+f),n.id==c)var p=!0;var d=t.append("circle").attr("fill","url(#img_"+f+")").attr("r",u?"30px":"24px").attr("data-stroke",n.id).attr("stroke-width","2px").attr("class","nodeImage "+(p?"currentNode":n.isProcess?"process":"node"));if(p&&d.attr("stroke","#fb4200"),!0===n.isIncomplete){t.attr("class","node isIncomplete show"),t.insert("rect").attr("x","-5").attr("y","-23").attr("width","14").attr("height","16").attr("fill","url(#img_hourglass.svg)").attr("data-stroke",n.id).attr("stroke-width","2px");g({imgName:"hourglass.svg",imageIconPath:"/img/entity-icon/hourglass.svg",leftPosition:"0",topPosition:"0",width:"12",height:"14"})}function g(t){o.select('pattern[id="img_'+t.imgName+'"]').empty()&&o.append("pattern").attr("x","0%").attr("y","0%").attr("patternUnits","objectBoundingBox").attr("id","img_"+t.imgName).attr("width","100%").attr("height","100%").append("image").attr("href",(function(e){var r=this;if(n){!function e(i){var o=i.imagePath,a={url:o,method:"GET",cache:!0};d.attr("data-iconpath",o);var s=new XMLHttpRequest;s.onreadystatechange=function(){if(4===s.readyState)if(200===s.status)"IE"!==yr.a.name?l.base64Encode(this.response,(function(e){l.imageObject[t.imageIconPath]=e,mt(r).attr("xlink:href",e)})):l.imageObject[t.imageIconPath]=o,t.imageIconPath!==d.attr("data-iconpath")&&d.attr("data-iconpathorigin",t.imageIconPath);else if(404===s.status){var i=l.getEntityIconPath({entityData:n,errorUrl:o});if(null===i){var a=mt(r.parentElement);a.select("image").remove(),a.attr("patternContentUnits","objectBoundingBox").append("circle").attr("r","24px").attr("fill","#e8e8e8")}else e({imagePath:i})}},s.responseType="blob",s.open(a.method,a.url,!0),s.send(null)}({imagePath:t.imageIconPath})}})).attr("x",t.leftPosition).attr("y",t.topPosition).attr("width",t.width).attr("height",t.height)}return g({imgName:f,imageIconPath:h,leftPosition:u?"11":"4",topPosition:u?"20":p?"3":"4",width:"40",height:"40"}),n.intersect=function(t){return i.intersect.circle(n,p?l.nodeArrowDistance+3:l.nodeArrowDistance,t)},d},arrowPointRender:function(t,e,n,r,i){var o=i.dagreD3,a=t.node(),s=a?a.parentNode:t;mt(s).select("path.path").attr("marker-end","url(#"+e+")");var u=t.append("marker").attr("id",e).attr("viewBox","0 0 10 10").attr("refX",8).attr("refY",5).attr("markerUnits","strokeWidth").attr("markerWidth",4).attr("markerHeight",4).attr("orient","auto").append("path").attr("d","M 0 0 L 10 5 L 0 10 z").style("fill",n.styleObj.stroke);o.util.applyStyle(u,n[r+"Style"])},saveSvg:function(t){var e=t.svg,n=t.width,r=t.height,i=t.downloadFileName,o=t.onExportLineage,a=this,s=e.clone(!0).node();setTimeout((function(){"Firefox"===yr.a.name&&(s.setAttribute("width",n),s.setAttribute("height",r));var t=mt("body").append("div");t.classed("hidden-svg",!0),t.node().appendChild(s);var e=mt(".hidden-svg svg");e.select("g").attr("transform","scale(1)"),e.select("foreignObject").remove();var u=150,l=150,c=s.getBBox().width+u,h=s.getBBox().height+l,f=s.getBBox().x,p=s.getBBox().y;s.attributes.viewBox.value=f+","+p+","+c+","+h;var d=document.createElement("canvas");d.id="canvas",d.style.display="none",d.width=1*s.getBBox().width+u,d.height=1*s.getBBox().height+l,mt("body").node().appendChild(d);var g=d.getContext("2d"),v=(new XMLSerializer).serializeToString(s),y=window.URL||window.webkitURL||window;g.fillStyle="#FFFFFF",g.fillRect(0,0,d.width,d.height),g.strokeRect(0,0,d.width,d.height),g.restore();var m=new Image(d.width,d.height),_=new Blob([v],{type:"image/svg+xml;base64"});"Safari"===yr.a.name&&(_=new Blob([v],{type:"image/svg+xml"})),g.drawImage(m,50,50,d.width,d.height);var w=y.createObjectURL(_);m.onload=function(){try{var e=document.createElement("a");e.download=i,document.body.appendChild(e),g.drawImage(m,50,50,d.width,d.height),d.toBlob((function(t){t?(e.href=y.createObjectURL(t),t.size>1e7&&o({status:"failed",message:"The Image size is huge, please open the image in a browser!"}),e.click(),o({status:"Success",message:"Successful"}),"Safari"===yr.a.name&&a.refreshGraphForSafari({edgeEl:a.$("svg g.node")})):o({status:"failed",message:"There was an error in downloading Lineage!"})}),"image/png"),t.remove(),d.remove()}catch(t){o({status:"failed",message:"There was an error in downloading Lineage!"})}},m.src=w}),0)}};function wr(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(t);e&&(r=r.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,r)}return n}function br(t){for(var e=1;e0&&void 0!==arguments[0]?arguments[0]:{},i=r.entityData,o=r.errorUrl,a=this.getBaseUrl(window.location.pathname)+Globals.entityImgPath;function s(t){return a+(mr.entityStateReadOnly[e]?"disabled/"+t:t)}function u(){return i.isProcess?mr.entityStateReadOnly[e]?a+"disabled/process.png":a+"process.png":mr.entityStateReadOnly[e]?a+"disabled/table.png":a+"table.png"}if(i&&(n=i.typeName,t=i&&i.serviceType,e=i&&i.status),i){if(o){var l=!(!o||!o.match("entity-icon/"+n+".png|disabled/"+n+".png"));return t&&l?s(t+".png"):u()}return i.typeName?s(i.typeName+".png"):u()}},isProcess:function(t){var e=t.typeName,n=t.superTypes;t.entityDef;return"Process"==e||n.indexOf("Process")>-1},isDeleted:function(t){if(void 0!==t)return mr.entityStateReadOnly[t.status]},isNodeToBeUpdated:function(t,e){var n=e.isProcessHideCheck,r=e.isDeletedEntityHideCheck,i={isProcess:n&&t.isProcess,isDeleted:r&&t.isDeleted};return i.update=i.isProcess||i.isDeleted,i},getServiceType:function(t){var e=t.typeName,n=t.entityDef,r=null;return e&&n&&(r=n.serviceType||null),r},getEntityDef:function(t){var e=t.typeName,n=t.entityDefCollection,r=null;return e&&(r=n.find((function(t){return t.name==e}))),r},getNestedSuperTypes:function(t){var e=t.entityDef,n=t.entityDefCollection,r=new Set;return function t(e,n){e&&e.superTypes&&e.superTypes.length&&e.superTypes.forEach((function(e){r.add(e);var i=n.find((function(t){t.name}));i&&t(i,n)}))}(e,n),Array.from(r)},generateData:function(t){var e=this,n=t.data,r=void 0===n?{}:n,i=t.filterObj,o=t.entityDefCollection,a=t.g,s=t.guid,u=t.setGraphEdge,l=t.setGraphNode;return new Promise((function(t,n){try{var c=r.relations||{},h=r.guidEntityMap||{},f=i.isProcessHideCheck||i.isDeletedEntityHideCheck,p={fill:"none",stroke:"#ffb203",width:3},d=function(t){if(t){if(t.updatedValues)return t;var n=t.displayText?t.displayText:" ",r=Object.assign(t,{shape:"img",updatedValues:!0,label:n.trunc(18),toolTipLabel:n,id:t.guid,isLineage:!0,isIncomplete:t.isIncomplete,entityDef:e.getEntityDef({typeName:t.typeName,entityDefCollection:o})});return r.serviceType=e.getServiceType(r),r.superTypes=e.getNestedSuperTypes(br(br({},r),{},{entityDefCollection:o})),r.isProcess=e.isProcess(r),r.isDeleted=e.isDeleted(r),r}},g=function(t){return"fill:"+t.fill+";stroke:"+t.stroke+";stroke-width:"+t.width},v=function(t,n,r){var i=[];return t.forEach((function(t){if(e.isNodeToBeUpdated(d(h[t]),r).update)if(w[t])i=i.concat(w[t]);else{var n=function t(n,r){if(n&&b[n]){var i=[];return b[n].forEach((function(n){if(e.isNodeToBeUpdated(d(h[n]),r).update){var o=t(n,r);o&&(i=i.concat(o))}else i.push(n)})),i}return null}(t,r);n&&(i=i.concat(n))}else i.push(t)})),i},y=function(t){if(a._nodes[t])return a._nodes[t];var e=d(h[t]);return l(t,e),e},m=function(t,e){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};u(t,e,br({arrowhead:"arrowPoint",curve:bt,style:g(p),styleObj:p},n))},_=function(t,e){y(t),y(e),m(t,e)},w={};if(f){var b=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.relations,n={};return e.forEach((function(t){n[t.fromEntityId]?n[t.fromEntityId].push(t.toEntityId):n[t.fromEntityId]=[t.toEntityId]})),n}(r);Object.keys(b).forEach((function(t){var n=b[t],r=e.isNodeToBeUpdated(d(h[t]),i),o=v(n,0,i);r.update?w[t]?w[t]=w[t].concat(o):w[t]=o:o.forEach((function(e){_(t,e)}))}))}else c.length?c.forEach((function(t){_(t.fromEntityId,t.toEntityId)})):y(s);a._nodes[s]&&(a._nodes[s]&&(a._nodes[s].isLineage=!1),e.findImpactNodeAndUpdateData({guid:s,g:a,setEdge:m,getStyleObjStr:g})),t(a)}catch(t){n(t)}}))},findImpactNodeAndUpdateData:function(t){var e=t.guid,n=t.getStyleObjStr,r=t.g,i=t.setEdge,o={},a={fill:"none",stroke:"#fb4200",width:3};!function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},s=arguments.length>1?arguments[1]:void 0,u=Object.keys(e);u.length&&(o[s]||(o[s]=!0,u.forEach((function(e){r._nodes[e]&&(r._nodes[e].isLineage=!1),i(s,e,{style:n(a),styleObj:a}),t(r._sucs[e],e)}))))}(r._sucs[e],e)}};String.prototype.trunc=String.prototype.trunc||function(t){return this.length>t?this.substr(0,t-1)+"...":this};function Er(){}function Tr(t,e){var n=new Er;if(t instanceof Er)t.each((function(t,e){n.set(e,t)}));else if(Array.isArray(t)){var r,i=-1,o=t.length;if(null==e)for(;++i0&&void 0!==arguments[0]?arguments[0]:{};return n._createGraph(n.options,n.graphOptions,t)},clear:function(t){return n.clear(t)},refresh:function(t){return n.refresh(t)},centerAlign:function(t){return n.centerAlign(t)},exportLineage:function(t){return n.exportLineage(t)},zoomIn:function(t){return n.zoomIn(t)},zoomOut:function(t){return n.zoomOut(t)},zoom:function(t){return n.zoom(t)},fullScreen:function(t){return n.fullScreen(t)},searchNode:function(t){return n.searchNode(t)},displayFullName:function(t){return n.displayFullName(t)},removeNodeSelection:function(t){return n.removeNodeSelection(t)},getGraphOptions:function(){return n.graphOptions},getNode:function(t,e){var r=null;return(r=e?n.actualData[t]:n.g._nodes[t])&&(r=Object.assign({},r)),r},getNodes:function(t,e){var r=null;return(r=e?n.actualData:n.g._nodes)&&(r=Object.assign({},r)),r},setNode:this._setGraphNode,setEdge:this._setGraphEdge},!1===a&&this.init(),this.initReturnObj}var e,n,r;return e=t,(n=[{key:"_updateAllOptions",value:function(t){Object.assign(this.options,t);var e=this.svg.node().getBoundingClientRect();this.graphOptions.width=this.options.width||e.width,this.graphOptions.height=this.options.height||e.height;var n=this.graphOptions,r=n.svg,i=n.width,o=n.height,a=n.guid,s=this.options.fitToScreen;r.select("g").node().removeAttribute("transform"),r.attr("viewBox","0 0 "+i+" "+o).attr("enable-background","new 0 0 "+i+" "+o),this.centerAlign({fitToScreen:s,guid:a})}},{key:"_updateOptions",value:function(t){Object.assign(this.options,{filterObj:{isProcessHideCheck:!1,isDeletedEntityHideCheck:!1}},t)}},{key:"init",value:function(){var t=this.options.data,e=void 0===t?{}:t;e.baseEntityGuid&&(this.guid=e.baseEntityGuid),this._initializeGraph(),this._initGraph()}},{key:"clear",value:function(){this.options.el||(this.svg.remove(),this.svg=null),this.g=null,this.graphOptions={}}},{key:"centerAlign",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=this.svg.select("g"),n=e.selectAll("g.edgePath");_r.centerNode(zr(zr({},this.graphOptions),{},{svgGroupEl:e,edgePathEl:n},t))}},{key:"zoomIn",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};_r.zoomIn(zr(zr({},this.graphOptions),t))}},{key:"zoomOut",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};_r.zoomOut(zr(zr({},this.graphOptions),t))}},{key:"zoom",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};_r.zoom(zr(zr({},this.graphOptions),t))}},{key:"displayFullName",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=this;this.g.nodes().forEach((function(n){var r=e.svg.selectAll("g.nodes>g[id='"+n+"']"),i=e.g.node(n).toolTipLabel;1==t.bLabelFullText?r.select("tspan").text(i):r.select("tspan").text(i.trunc(18))})),this.selectedNode&&this.searchNode({guid:this.selectedNode})}},{key:"refresh",value:function(){this.clear(),this._initializeGraph(),this._initGraph({refresh:!0}),this.selectedNode=""}},{key:"removeNodeSelection",value:function(){this.svg.selectAll("g.node>circle").classed("node-detail-highlight",!1)}},{key:"searchNode",value:function(t){var e=t.guid,n=t.onSearchNode;this.svg.selectAll(".serach-rect").remove(),this.svg.selectAll(".label").attr("stroke","none"),this.selectedNode=e,this.centerAlign({guid:e,onCenterZoomed:function(t){var e=t.selectedNodeEl,r=e.node().getBBox(),i=r.width+10,o=r.x-5;e.select(".label").attr("stroke","#316132"),e.select("circle").classed("wobble",!0),e.insert("rect","circle").attr("class","serach-rect").attr("stroke","#37bb9b").attr("stroke-width","2.5px").attr("fill","none").attr("x",o).attr("y",-27.5).attr("width",i).attr("height",60),n&&"function"==typeof n&&n(t)},isSelected:!0})}},{key:"exportLineage",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.downloadFileName;if(void 0===e){var n=this.g._nodes[this.guid];e=n&&n.attributes?"".concat(n.attributes.qualifiedName||n.attributes.name||"lineage_export",".png"):"export.png"}_r.saveSvg(zr(zr({},this.graphOptions),{},{downloadFileName:e,onExportLineage:function(t){function e(e){return t.apply(this,arguments)}return e.toString=function(){return t.toString()},e}((function(e){t.onExportLineage&&onExportLineage(e)}))}))}},{key:"fullScreen",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=t.el;if(void 0===e)throw new Error("LineageHelper requires el propety to apply fullScreen class");var n=mt(e);return n.classed("fullscreen-mode")?(n.classed("fullscreen-mode",!1),!1):(n.classed("fullscreen-mode",!0),!0)}},{key:"_getValueFromUser",value:function(t){if(void 0!==t)return"function"==typeof t?t():t}},{key:"_initializeGraph",value:function(){var t=this.options,e=t.width,n=void 0===e?"100%":e,r=t.height,o=void 0===r?"100%":r,a=t.el;this.svg=mt(a),a instanceof SVGElement||(this.svg.selectAll("*").remove(),this.svg=this.svg.append("svg").attr("xmlns","http://www.w3.org/2000/svg").attr(" xmlns:xlink","http://www.w3.org/1999/xlink").attr("version","1.1").attr("width",n).attr("height",o)),this.g=(new i.a.graphlib.Graph).setGraph(Object.assign({nodesep:50,ranksep:90,rankdir:"LR",marginx:20,marginy:20,transition:function(t){return t.transition().duration(500)}},this.options.dagreOptions)).setDefaultEdgeLabel((function(){return{}}));var s=this.svg.node().getBoundingClientRect();this.actualData={},this.graphOptions={svg:this.svg,g:this.g,dagreD3:i.a,guid:this.guid,width:this.options.width||s.width,height:this.options.height||s.height}}},{key:"_initGraph",value:function(){var t=this,e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.refresh;this.svg&&this.svg.select("g").remove();var r=this.options.filterObj;if(this.options.getFilterObj){var i=this.options.getFilterObj();if(void 0!==i||null!==i){if("object"!==Ar(i))throw new Error("getFilterObj expect return type `object`,`null` or `Undefined`");r=i}}if(!0!==this.options.setDataManually)return void 0===this.options.data||this.options.data&&0===this.options.data.relations.length&&_.isEmpty(this.options.data.guidEntityMap)?(this.options.beforeRender&&this.options.beforeRender(),this.svg.append("text").attr("x","50%").attr("y","50%").attr("alignment-baseline","middle").attr("text-anchor","middle").text("No lineage data found"),void(this.options.afterRender&&this.options.afterRender())):kr.generateData(zr(zr(zr({},this.options),{},{filterObj:r},this.graphOptions),{},{setGraphNode:this._setGraphNode,setGraphEdge:this._setGraphEdge})).then((function(e){t._createGraph(t.options,t.graphOptions,{refresh:n})}))}},{key:"_createGraph",value:function(t,e,n){var r=this,o=t.data,a=void 0===o?{}:o,s=t.imgBasePath,u=t.isShowTooltip,l=t.isShowHoverPath,c=t.onLabelClick,h=t.onPathClick,f=t.onNodeClick,p=t.zoom,d=t.fitToScreen,g=t.getToolTipContent,v=t.toolTipTitle,y=n.refresh;this.options.beforeRender&&this.options.beforeRender(),this.selectedNode="";var m=this,_=e.svg,w=e.g,b=e.width,x=e.height,k=this.options.dagreOptions&&"tb"===this.options.dagreOptions.rankdir;if(_ instanceof yt==0)throw new Error("svg is not initialized or something went wrong while creatig graph instance");if(void 0!==w._nodes&&0!==w._nodes.length){w.nodes().forEach((function(t){var e=w.node(t);e&&(e.rx=e.ry=5)})),_.attr("viewBox","0 0 "+b+" "+x).attr("enable-background","new 0 0 "+b+" "+x);var E=_.append("g"),T=_.append("defs"),N=new i.a.render;N.arrows().arrowPoint=function(){return _r.arrowPointRender.apply(_r,Array.prototype.slice.call(arguments).concat([zr({},e)]))},N.shapes().img=function(){return _r.imgShapeRender.apply(_r,Array.prototype.slice.call(arguments).concat([zr(zr({},e),{},{isRankdirToBottom:k,imgBasePath:m._getValueFromUser(s),defsEl:T})]))};var O=function(){var t=function(){return"n"},e=function(){return[0,0]},n=function(){return" "},r=document.body,i=h(),o=null,a=null,s=null;function u(t){(o=function(t){var e=t.node();return e?"svg"===e.tagName.toLowerCase()?e:e.ownerSVGElement:null}(t))&&(a=o.createSVGPoint(),r.appendChild(i))}u.show=function(){var i=Array.prototype.slice.call(arguments);i[i.length-1]instanceof SVGElement&&(s=i.pop());var o,a=n.apply(this,i),h=e.apply(this,i),p=t.apply(this,i),d=f(),g=c.length,v=document.documentElement.scrollTop||r.scrollTop,y=document.documentElement.scrollLeft||r.scrollLeft;for(d.html(a).style("opacity",1).style("pointer-events","all");g--;)d.classed(c[g],!1);return o=l.get(p).apply(this),d.classed(p,!0).style("top",o.top+h[0]+v+"px").style("left",o.left+h[1]+y+"px"),u},u.hide=function(){return f().style("opacity",0).style("pointer-events","none"),u},u.attr=function(t,e){if(arguments.length<2&&"string"==typeof t)return f().attr(t);var n=Array.prototype.slice.call(arguments);return yt.prototype.attr.apply(f(),n),u},u.style=function(t,e){if(arguments.length<2&&"string"==typeof t)return f().style(t);var n=Array.prototype.slice.call(arguments);return yt.prototype.style.apply(f(),n),u},u.direction=function(e){return arguments.length?(t=null==e?e:d(e),u):t},u.offset=function(t){return arguments.length?(e=null==t?t:d(t),u):e},u.html=function(t){return arguments.length?(n=null==t?t:d(t),u):n},u.rootElement=function(t){return arguments.length?(r=null==t?t:d(t),u):r},u.destroy=function(){return i&&(f().remove(),i=null),u};var l=Nr({n:function(){var t=p(this);return{top:t.n.y-i.offsetHeight,left:t.n.x-i.offsetWidth/2}},s:function(){var t=p(this);return{top:t.s.y,left:t.s.x-i.offsetWidth/2}},e:function(){var t=p(this);return{top:t.e.y-i.offsetHeight/2,left:t.e.x}},w:function(){var t=p(this);return{top:t.w.y-i.offsetHeight/2,left:t.w.x-i.offsetWidth}},nw:function(){var t=p(this);return{top:t.nw.y-i.offsetHeight,left:t.nw.x-i.offsetWidth}},ne:function(){var t=p(this);return{top:t.ne.y-i.offsetHeight,left:t.ne.x}},sw:function(){var t=p(this);return{top:t.sw.y,left:t.sw.x-i.offsetWidth}},se:function(){var t=p(this);return{top:t.se.y,left:t.se.x}}}),c=l.keys();function h(){var t=mt(document.createElement("div"));return t.style("position","absolute").style("top",0).style("opacity",0).style("pointer-events","none").style("box-sizing","border-box"),t.node()}function f(){return null==i&&(i=h(),r.appendChild(i)),mt(i)}function p(t){for(var e=s||t;null==e.getScreenCTM&&null!=e.parentNode;)e=e.parentNode;var n={},r=e.getScreenCTM(),i=e.getBBox(),o=i.width,u=i.height,l=i.x,c=i.y;return a.x=l,a.y=c,n.nw=a.matrixTransform(r),a.x+=o,n.ne=a.matrixTransform(r),a.y+=u,n.se=a.matrixTransform(r),a.x-=o,n.sw=a.matrixTransform(r),a.y-=u/2,n.w=a.matrixTransform(r),a.x+=o,n.e=a.matrixTransform(r),a.x-=o/2,a.y-=u/2,n.n=a.matrixTransform(r),a.y+=u,n.s=a.matrixTransform(r),n}function d(t){return"function"==typeof t?t:function(){return t}}return u}().attr("class","d3-tip").offset([10,0]).html((function(t){if(g&&"function"==typeof g)return g(t,w.node(t));var e=w.node(t),n="";return v?n="
        "+v+"
        ":e.id!==r.guid&&(n="
        "+(e.isLineage?"Lineage":"Impact")+"
        "),n+="
        "+e.toolTipLabel+"
        ",e.typeName&&(n+="
        ("+e.typeName+")
        "),e.queryText&&(n+="
        Query: "+e.queryText+"
        "),"
        "+n+"
        "}));_.call(O),N(E,w),E.selectAll("g.nodes g.label").attr("transform",(function(){return k?"translate(2,-20)":"translate(2,-38)"})).attr("font-size","10px").on("mouseenter",(function(t){it.preventDefault(),mt(this).classed("highlight",!0)})).on("mouseleave",(function(t){it.preventDefault(),mt(this).classed("highlight",!1)})).on("click",(function(t){it.preventDefault(),c&&"function"==typeof c&&c({clickedData:t}),O.hide(t)})),E.selectAll("g.nodes g.node circle").on("mouseenter",(function(t,n,r){if(m.activeNode=!0,this.getScreenCTM().translate(+this.getAttribute("cx"),+this.getAttribute("cy")),m.svg.selectAll(".node").classed("active",!1),mt(this).classed("active",!0),m._getValueFromUser(u)){var i=_r.getToolTipDirection({el:this});O.direction(i).show(t,this)}!1!==m._getValueFromUser(l)&&_r.onHoverFade(zr({opacity:.3,mouseenter:!0,hoveredNode:t},e))})).on("mouseleave",(function(t){m.activeNode=!1;var n=this;setTimeout((function(e){m.activeTip||m.activeNode||(mt(n).classed("active",!1),m._getValueFromUser(u)&&O.hide(t))}),150),!1!==m._getValueFromUser(l)&&_r.onHoverFade(zr({mouseenter:!1,hoveredNode:t},e))})).on("click",(function(t){it.defaultPrevented||(it.preventDefault(),O.hide(t),_.selectAll("g.node>circle").classed("node-detail-highlight",!1),mt(this).classed("node-detail-highlight",!0),f&&"function"==typeof f&&f({clickedData:t,el:this}))}));var S=E.selectAll("g.edgePath");S.selectAll("path.path").on("click",(function(t){if(h&&"function"==typeof h){var e=a.relations.find((function(e){if(e.fromEntityId===t.v&&e.toEntityId===t.w)return!0}));h({pathRelationObj:e,clickedData:t})}})),!1!==p&&_r.centerNode(zr(zr({},e),{},{fitToScreen:d,svgGroupEl:E,edgePathEl:S})),_r.dragNode(zr(zr({},e),{},{edgePathEl:S})),!0!==y&&this._addLegend(),this.options.afterRender&&this.options.afterRender()}else _.html('No relations to display')}},{key:"_addLegend",value:function(){if(!1!==this.options.legends){var t=mt(this.options.legendsEl||this.options.el).insert("div",":first-child").classed("legends",!0),e=t.append("span").style("color","#fb4200");e.append("i").classed("fa fa-circle-o fa-fw",!0),e.append("span").html("Current Entity"),(e=t.append("span").style("color","#686868")).append("i").classed("fa fa-hourglass-half fa-fw",!0),e.append("span").html("In Progress"),(e=t.append("span").style("color","#df9b00")).append("i").classed("fa fa-long-arrow-right fa-fw",!0),e.append("span").html("Lineage"),(e=t.append("span").style("color","#fb4200")).append("i").classed("fa fa-long-arrow-right fa-fw",!0),e.append("span").html("Impact")}}}])&&Dr(e.prototype,n),r&&Dr(e,r),t}()}])})); \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/dist/styles.css b/dashboardv3/public/js/external_lib/atlas-lineage/dist/styles.css deleted file mode 100644 index 2d7f9d9de1a..00000000000 --- a/dashboardv3/public/js/external_lib/atlas-lineage/dist/styles.css +++ /dev/null @@ -1,2 +0,0 @@ -.node{cursor:pointer}.node text{font-size:10px;font-family:sans-serif}.node .label{fill:#868686}.node .label.highlight{cursor:pointer;fill:#4a90e2;text-decoration:underline}.node .label.highlight tspan{font-weight:400}.node circle{-moz-transition:all 0.3s;-webkit-transition:all 0.3s;transition:all 0.3s;stroke-width:1.5px}.node circle.node-detail-highlight{stroke:#4a90e2;stroke-width:2px}.node circle.nodeImage.green:hover{stroke:#ffb203}.node circle.nodeImage.blue:hover{stroke:#4b91e2}.node circle.nodeImage.currentNode{stroke:#fb4200}.node circle.nodeImage:hover{-moz-transform:scale(1.4);-webkit-transform:scale(1.4);transform:scale(1.4)}.node.active circle{-moz-transform:scale(1.4);-webkit-transform:scale(1.4);transform:scale(1.4)}.node.active circle.nodeImage.green{stroke:#ffb203}.node.active circle.nodeImage.blue{stroke:#4b91e2}.legends>span{margin-right:8px;font-family:Source Sans Pro}svg.hover g.node{opacity:0.1 !important}svg.hover g.edgePath{opacity:0 !important}svg.hover g.node.hover-active-node,svg.hover g.edgePath.hover-active-path{opacity:1 !important}.invisible .node circle{transition:all 0s}.edgePath .path{cursor:pointer}.link{fill:none;stroke:#ccc;stroke-width:1.5px}.text-center{text-align:center}.d3-tip{line-height:1;font-weight:bold;padding:12px;background:rgba(0,0,0,0.8);color:#fff;z-index:999;max-width:300px;border-radius:2px}.d3-tip .tip-inner-scroll{overflow:auto;max-height:300px}.d3-tip .tip-inner-scroll h5{margin:7px 0px}.d3-tip:after{box-sizing:border-box;display:inline;font-size:10px;width:100%;line-height:1;color:rgba(0,0,0,0.8);position:absolute}.d3-tip.n:after{content:"\25BC";margin:-1px 0 0 0;top:100%;left:0;text-align:center}.d3-tip.e:after{content:"\25C0";margin:-4px 0 0 0;top:50%;left:-8px}.d3-tip.s:after{content:"\25B2";margin:0 0 1px 0;top:-8px;left:0;text-align:center}.d3-tip.w:after{content:"\25B6";margin:-4px 0 0 -1px;top:50%;left:100%}g.type-TK>rect{fill:#00ffd0}.fullscreen-mode{position:fixed;height:100% !important;top:0;bottom:0;left:0;width:100%;right:0;padding:0 !important;z-index:9999;overflow:hidden !important}.fullscreen-mode .resizeGraph{position:fixed;height:100% !important}.fullscreen-mode .resizeGraph .ui-resizable-handle{display:none}.fullscreen-mode .lineage-box{padding:10px !important}.fullscreen-mode .box-panel{margin:10px !important}@keyframes zoominoutsinglefeatured{0%{transform:scale(1, 1)}50%{transform:scale(1.2, 1.2)}100%{transform:scale(1, 1)}}.wobble{animation:zoominoutsinglefeatured 1s 5}.hidden-svg{visibility:hidden}@-webkit-keyframes blink{from{opacity:0.2}to{opacity:0.5}} - diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/package-lock.json b/dashboardv3/public/js/external_lib/atlas-lineage/package-lock.json deleted file mode 100644 index 69f5a400691..00000000000 --- a/dashboardv3/public/js/external_lib/atlas-lineage/package-lock.json +++ /dev/null @@ -1,5978 +0,0 @@ -{ - "name": "atlas-lineage-module", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/compat-data": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz", - "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==", - "dev": true, - "requires": { - "browserslist": "^4.12.0", - "invariant": "^2.2.4", - "semver": "^5.5.0" - } - }, - "@babel/core": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.4.tgz", - "integrity": "sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.4", - "@babel/helper-module-transforms": "^7.11.0", - "@babel/helpers": "^7.10.4", - "@babel/parser": "^7.11.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.11.0", - "@babel/types": "^7.11.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - } - }, - "@babel/generator": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz", - "integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", - "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", - "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz", - "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.10.4", - "browserslist": "^4.12.0", - "invariant": "^2.2.4", - "levenary": "^1.1.1", - "semver": "^5.5.0" - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz", - "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-member-expression-to-functions": "^7.10.5", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.10.4" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz", - "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-regex": "^7.10.4", - "regexpu-core": "^4.7.0" - } - }, - "@babel/helper-define-map": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", - "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/types": "^7.10.5", - "lodash": "^4.17.19" - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz", - "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", - "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", - "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", - "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-module-transforms": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", - "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-simple-access": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/template": "^7.10.4", - "@babel/types": "^7.11.0", - "lodash": "^4.17.19" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", - "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", - "dev": true - }, - "@babel/helper-regex": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", - "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", - "dev": true, - "requires": { - "lodash": "^4.17.19" - } - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz", - "integrity": "sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-wrap-function": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-replace-supers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", - "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-simple-access": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", - "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", - "dev": true, - "requires": { - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz", - "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz", - "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helpers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", - "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", - "dev": true, - "requires": { - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", - "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", - "dev": true - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", - "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-remap-async-to-generator": "^7.10.4", - "@babel/plugin-syntax-async-generators": "^7.8.0" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz", - "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz", - "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-dynamic-import": "^7.8.0" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz", - "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz", - "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.0" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz", - "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz", - "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz", - "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz", - "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-transform-parameters": "^7.10.4" - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz", - "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz", - "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz", - "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz", - "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz", - "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz", - "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz", - "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz", - "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-remap-async-to-generator": "^7.10.4" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz", - "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz", - "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz", - "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-define-map": "^7.10.4", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.10.4", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz", - "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz", - "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz", - "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz", - "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz", - "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz", - "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz", - "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz", - "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz", - "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz", - "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.10.5", - "@babel/helper-plugin-utils": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz", - "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-simple-access": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz", - "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.10.4", - "@babel/helper-module-transforms": "^7.10.5", - "@babel/helper-plugin-utils": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz", - "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz", - "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz", - "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz", - "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz", - "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz", - "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz", - "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.2" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz", - "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz", - "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz", - "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz", - "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-regex": "^7.10.4" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz", - "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz", - "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz", - "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz", - "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/preset-env": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.0.tgz", - "integrity": "sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.11.0", - "@babel/helper-compilation-targets": "^7.10.4", - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-proposal-async-generator-functions": "^7.10.4", - "@babel/plugin-proposal-class-properties": "^7.10.4", - "@babel/plugin-proposal-dynamic-import": "^7.10.4", - "@babel/plugin-proposal-export-namespace-from": "^7.10.4", - "@babel/plugin-proposal-json-strings": "^7.10.4", - "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", - "@babel/plugin-proposal-numeric-separator": "^7.10.4", - "@babel/plugin-proposal-object-rest-spread": "^7.11.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.10.4", - "@babel/plugin-proposal-optional-chaining": "^7.11.0", - "@babel/plugin-proposal-private-methods": "^7.10.4", - "@babel/plugin-proposal-unicode-property-regex": "^7.10.4", - "@babel/plugin-syntax-async-generators": "^7.8.0", - "@babel/plugin-syntax-class-properties": "^7.10.4", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.0", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0", - "@babel/plugin-syntax-top-level-await": "^7.10.4", - "@babel/plugin-transform-arrow-functions": "^7.10.4", - "@babel/plugin-transform-async-to-generator": "^7.10.4", - "@babel/plugin-transform-block-scoped-functions": "^7.10.4", - "@babel/plugin-transform-block-scoping": "^7.10.4", - "@babel/plugin-transform-classes": "^7.10.4", - "@babel/plugin-transform-computed-properties": "^7.10.4", - "@babel/plugin-transform-destructuring": "^7.10.4", - "@babel/plugin-transform-dotall-regex": "^7.10.4", - "@babel/plugin-transform-duplicate-keys": "^7.10.4", - "@babel/plugin-transform-exponentiation-operator": "^7.10.4", - "@babel/plugin-transform-for-of": "^7.10.4", - "@babel/plugin-transform-function-name": "^7.10.4", - "@babel/plugin-transform-literals": "^7.10.4", - "@babel/plugin-transform-member-expression-literals": "^7.10.4", - "@babel/plugin-transform-modules-amd": "^7.10.4", - "@babel/plugin-transform-modules-commonjs": "^7.10.4", - "@babel/plugin-transform-modules-systemjs": "^7.10.4", - "@babel/plugin-transform-modules-umd": "^7.10.4", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4", - "@babel/plugin-transform-new-target": "^7.10.4", - "@babel/plugin-transform-object-super": "^7.10.4", - "@babel/plugin-transform-parameters": "^7.10.4", - "@babel/plugin-transform-property-literals": "^7.10.4", - "@babel/plugin-transform-regenerator": "^7.10.4", - "@babel/plugin-transform-reserved-words": "^7.10.4", - "@babel/plugin-transform-shorthand-properties": "^7.10.4", - "@babel/plugin-transform-spread": "^7.11.0", - "@babel/plugin-transform-sticky-regex": "^7.10.4", - "@babel/plugin-transform-template-literals": "^7.10.4", - "@babel/plugin-transform-typeof-symbol": "^7.10.4", - "@babel/plugin-transform-unicode-escapes": "^7.10.4", - "@babel/plugin-transform-unicode-regex": "^7.10.4", - "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.11.0", - "browserslist": "^4.12.0", - "core-js-compat": "^3.6.2", - "invariant": "^2.2.2", - "levenary": "^1.1.1", - "semver": "^5.5.0" - } - }, - "@babel/preset-modules": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.3.tgz", - "integrity": "sha512-Ra3JXOHBq2xd56xSF7lMKXdjBn3T772Y1Wet3yWnkDly9zHvJki029tAFzvAAK5cf4YV3yoxuP61crYRol6SVg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/runtime": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", - "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/traverse": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", - "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.0", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.0", - "@babel/types": "^7.11.0", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" - } - }, - "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", - "to-fast-properties": "^2.0.0" - } - }, - "@types/json-schema": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", - "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==", - "dev": true - }, - "@webassemblyjs/ast": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", - "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", - "dev": true, - "requires": { - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", - "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", - "dev": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", - "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", - "dev": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", - "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", - "dev": true - }, - "@webassemblyjs/helper-code-frame": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", - "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", - "dev": true, - "requires": { - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "@webassemblyjs/helper-fsm": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", - "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", - "dev": true - }, - "@webassemblyjs/helper-module-context": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", - "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", - "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", - "dev": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", - "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", - "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", - "dev": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", - "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", - "dev": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", - "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", - "dev": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", - "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/helper-wasm-section": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-opt": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "@webassemblyjs/wast-printer": "1.9.0" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", - "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", - "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-buffer": "1.9.0", - "@webassemblyjs/wasm-gen": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", - "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-wasm-bytecode": "1.9.0", - "@webassemblyjs/ieee754": "1.9.0", - "@webassemblyjs/leb128": "1.9.0", - "@webassemblyjs/utf8": "1.9.0" - } - }, - "@webassemblyjs/wast-parser": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", - "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/floating-point-hex-parser": "1.9.0", - "@webassemblyjs/helper-api-error": "1.9.0", - "@webassemblyjs/helper-code-frame": "1.9.0", - "@webassemblyjs/helper-fsm": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", - "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/wast-parser": "1.9.0", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true - }, - "acorn": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", - "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", - "dev": true - }, - "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-errors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", - "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true, - "optional": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-loader": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", - "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", - "dev": true, - "requires": { - "find-cache-dir": "^2.1.0", - "loader-utils": "^1.4.0", - "mkdirp": "^0.5.3", - "pify": "^4.0.1", - "schema-utils": "^2.6.5" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, - "babel-plugin-syntax-class-properties": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", - "dev": true - }, - "babel-plugin-transform-class-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-plugin-syntax-class-properties": "^6.8.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - } - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - }, - "dependencies": { - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - } - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", - "dev": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "dev": true - }, - "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-rsa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", - "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "randombytes": "^2.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dev": true, - "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "~1.0.5" - } - }, - "browserslist": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.0.tgz", - "integrity": "sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001111", - "electron-to-chromium": "^1.3.523", - "escalade": "^3.0.2", - "node-releases": "^1.1.60" - } - }, - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, - "cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001118", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001118.tgz", - "integrity": "sha512-RNKPLojZo74a0cP7jFMidQI7nvLER40HgNfgKQEJ2PFm225L0ectUungNQoK3Xk3StQcFbpBPNEvoWD59436Hg==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chokidar": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", - "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" - } - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", - "dev": true - }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", - "dev": true - }, - "core-js-compat": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", - "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", - "dev": true, - "requires": { - "browserslist": "^4.8.5", - "semver": "7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true - } - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, - "css-loader": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", - "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "cssesc": "^3.0.0", - "icss-utils": "^4.1.1", - "loader-utils": "^1.2.3", - "normalize-path": "^3.0.0", - "postcss": "^7.0.32", - "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^3.0.2", - "postcss-modules-scope": "^2.2.0", - "postcss-modules-values": "^3.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^2.7.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true - }, - "cyclist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", - "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", - "dev": true - }, - "d3": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz", - "integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==", - "requires": { - "d3-array": "1", - "d3-axis": "1", - "d3-brush": "1", - "d3-chord": "1", - "d3-collection": "1", - "d3-color": "1", - "d3-contour": "1", - "d3-dispatch": "1", - "d3-drag": "1", - "d3-dsv": "1", - "d3-ease": "1", - "d3-fetch": "1", - "d3-force": "1", - "d3-format": "1", - "d3-geo": "1", - "d3-hierarchy": "1", - "d3-interpolate": "1", - "d3-path": "1", - "d3-polygon": "1", - "d3-quadtree": "1", - "d3-random": "1", - "d3-scale": "2", - "d3-scale-chromatic": "1", - "d3-selection": "1", - "d3-shape": "1", - "d3-time": "1", - "d3-time-format": "2", - "d3-timer": "1", - "d3-transition": "1", - "d3-voronoi": "1", - "d3-zoom": "1" - } - }, - "d3-array": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", - "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" - }, - "d3-axis": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz", - "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==" - }, - "d3-brush": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz", - "integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "d3-chord": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", - "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", - "requires": { - "d3-array": "1", - "d3-path": "1" - } - }, - "d3-collection": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", - "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==" - }, - "d3-color": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", - "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==" - }, - "d3-contour": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", - "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", - "requires": { - "d3-array": "^1.1.1" - } - }, - "d3-dispatch": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", - "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==" - }, - "d3-drag": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", - "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", - "requires": { - "d3-dispatch": "1", - "d3-selection": "1" - } - }, - "d3-dsv": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", - "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", - "requires": { - "commander": "2", - "iconv-lite": "0.4", - "rw": "1" - } - }, - "d3-ease": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", - "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==" - }, - "d3-fetch": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz", - "integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==", - "requires": { - "d3-dsv": "1" - } - }, - "d3-force": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz", - "integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==", - "requires": { - "d3-collection": "1", - "d3-dispatch": "1", - "d3-quadtree": "1", - "d3-timer": "1" - } - }, - "d3-format": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", - "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==" - }, - "d3-geo": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz", - "integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==", - "requires": { - "d3-array": "1" - } - }, - "d3-hierarchy": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", - "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==" - }, - "d3-interpolate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", - "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", - "requires": { - "d3-color": "1" - } - }, - "d3-path": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==" - }, - "d3-polygon": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", - "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==" - }, - "d3-quadtree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", - "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==" - }, - "d3-random": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz", - "integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==" - }, - "d3-scale": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", - "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", - "requires": { - "d3-array": "^1.2.0", - "d3-collection": "1", - "d3-format": "1", - "d3-interpolate": "1", - "d3-time": "1", - "d3-time-format": "2" - } - }, - "d3-scale-chromatic": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz", - "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==", - "requires": { - "d3-color": "1", - "d3-interpolate": "1" - } - }, - "d3-selection": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", - "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==" - }, - "d3-shape": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", - "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", - "requires": { - "d3-path": "1" - } - }, - "d3-time": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", - "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==" - }, - "d3-time-format": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", - "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", - "requires": { - "d3-time": "1" - } - }, - "d3-timer": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", - "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==" - }, - "d3-tip": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/d3-tip/-/d3-tip-0.9.1.tgz", - "integrity": "sha512-EVBfG9d+HnjIoyVXfhpytWxlF59JaobwizqMX9EBXtsFmJytjwHeYiUs74ldHQjE7S9vzfKTx2LCtvUrIbuFYg==", - "requires": { - "d3-collection": "^1.0.4", - "d3-selection": "^1.3.0" - } - }, - "d3-transition": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", - "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", - "requires": { - "d3-color": "1", - "d3-dispatch": "1", - "d3-ease": "1", - "d3-interpolate": "1", - "d3-selection": "^1.1.0", - "d3-timer": "1" - } - }, - "d3-voronoi": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", - "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==" - }, - "d3-zoom": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz", - "integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==", - "requires": { - "d3-dispatch": "1", - "d3-drag": "1", - "d3-interpolate": "1", - "d3-selection": "1", - "d3-transition": "1" - } - }, - "dagre": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", - "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", - "requires": { - "graphlib": "^2.1.8", - "lodash": "^4.17.15" - } - }, - "dagre-d3": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz", - "integrity": "sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==", - "requires": { - "d3": "^5.14", - "dagre": "^0.8.5", - "graphlib": "^2.1.8", - "lodash": "^4.17.15" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "electron-to-chromium": { - "version": "1.3.549", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.549.tgz", - "integrity": "sha512-q09qZdginlqDH3+Y1P6ch5UDTW8nZ1ijwMkxFs15J/DAWOwqolIx8HZH1UP0vReByBigk/dPlU22xS1MaZ+kpQ==", - "dev": true - }, - "elliptic": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", - "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", - "dev": true, - "requires": { - "bn.js": "^4.4.0", - "brorand": "^1.0.1", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "dev": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", - "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "memory-fs": "^0.5.0", - "tapable": "^1.0.0" - }, - "dependencies": { - "memory-fs": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", - "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - } - } - }, - "errno": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", - "dev": true, - "requires": { - "prr": "~1.0.1" - } - }, - "escalade": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", - "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "eslint-scope": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", - "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "events": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", - "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", - "dev": true - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "figgy-pudding": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", - "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", - "dev": true - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "findup-sync": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", - "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^4.0.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "requires": { - "global-prefix": "^3.0.0" - }, - "dependencies": { - "global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "requires": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - } - } - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "graphlib": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", - "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", - "requires": { - "lodash": "^4.17.15" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "icss-utils": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", - "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", - "dev": true, - "requires": { - "postcss": "^7.0.14" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true - }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, - "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", - "dev": true, - "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indexes-of": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", - "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levenary": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", - "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", - "dev": true, - "requires": { - "leven": "^3.1.0" - } - }, - "loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", - "dev": true - }, - "loader-utils": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", - "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } - } - }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "mini-css-extract-plugin": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz", - "integrity": "sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "normalize-url": "1.9.1", - "schema-utils": "^1.0.0", - "webpack-sources": "^1.1.0" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - } - } - }, - "node-releases": { - "version": "1.1.60", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", - "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", - "dev": true, - "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, - "parallel-transform": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", - "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", - "dev": true, - "requires": { - "cyclist": "^1.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, - "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path": { - "version": "0.12.7", - "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", - "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", - "dev": true, - "requires": { - "process": "^0.11.1", - "util": "^0.10.3" - } - }, - "path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true, - "optional": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "pbkdf2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", - "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "platform": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", - "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==" - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-modules-extract-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", - "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", - "dev": true, - "requires": { - "postcss": "^7.0.5" - } - }, - "postcss-modules-local-by-default": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", - "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", - "dev": true, - "requires": { - "icss-utils": "^4.1.1", - "postcss": "^7.0.32", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } - }, - "postcss-modules-scope": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", - "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", - "dev": true, - "requires": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0" - } - }, - "postcss-modules-values": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", - "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", - "dev": true, - "requires": { - "icss-utils": "^4.0.0", - "postcss": "^7.0.6" - } - }, - "postcss-selector-parser": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", - "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "postcss-value-parser": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", - "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", - "dev": true - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - }, - "dependencies": { - "bn.js": { - "version": "4.11.9", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", - "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", - "dev": true - } - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, - "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "regenerate": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", - "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", - "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - } - }, - "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", - "dev": true - }, - "regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexpu-core": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", - "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.2.0", - "regjsgen": "^0.5.1", - "regjsparser": "^0.6.4", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.2.0" - } - }, - "regjsgen": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", - "dev": true - }, - "regjsparser": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", - "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true, - "optional": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "dependencies": { - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - } - } - }, - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } - }, - "rw": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", - "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sass": { - "version": "1.26.10", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.10.tgz", - "integrity": "sha512-bzN0uvmzfsTvjz0qwccN1sPm2HxxpNI/Xa+7PlUEMS+nQvbyuEK7Y0qFqxlPHhiNHb1Ze8WQJtU31olMObkAMw==", - "dev": true, - "requires": { - "chokidar": ">=2.0.0 <4.0.0" - } - }, - "sass-loader": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz", - "integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "loader-utils": "^1.2.3", - "neo-async": "^2.6.1", - "schema-utils": "^2.6.1", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "sort-keys": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", - "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } - }, - "source-list-map": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", - "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "strict-uri-encode": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", - "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "tapable": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", - "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", - "dev": true - }, - "terser": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", - "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", - "dev": true, - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "terser-webpack-plugin": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", - "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", - "dev": true, - "requires": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^4.0.0", - "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "timers-browserify": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.11.tgz", - "integrity": "sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", - "dev": true - }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", - "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", - "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, - "optional": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", - "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "v8-compile-cache": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", - "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", - "dev": true - }, - "vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", - "dev": true - }, - "watchpack": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", - "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", - "dev": true, - "requires": { - "chokidar": "^3.4.1", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0", - "watchpack-chokidar2": "^2.0.0" - } - }, - "watchpack-chokidar2": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", - "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", - "dev": true, - "optional": true, - "requires": { - "chokidar": "^2.1.8" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "optional": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "optional": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "optional": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "optional": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - } - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "optional": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "optional": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - } - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "optional": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "optional": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "optional": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "optional": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } - } - }, - "webpack": { - "version": "4.44.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.1.tgz", - "integrity": "sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ==", - "dev": true, - "requires": { - "@webassemblyjs/ast": "1.9.0", - "@webassemblyjs/helper-module-context": "1.9.0", - "@webassemblyjs/wasm-edit": "1.9.0", - "@webassemblyjs/wasm-parser": "1.9.0", - "acorn": "^6.4.1", - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^4.3.0", - "eslint-scope": "^4.0.3", - "json-parse-better-errors": "^1.0.2", - "loader-runner": "^2.4.0", - "loader-utils": "^1.2.3", - "memory-fs": "^0.4.1", - "micromatch": "^3.1.10", - "mkdirp": "^0.5.3", - "neo-async": "^2.6.1", - "node-libs-browser": "^2.2.1", - "schema-utils": "^1.0.0", - "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.3", - "watchpack": "^1.7.4", - "webpack-sources": "^1.4.1" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } - } - }, - "webpack-cli": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz", - "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "cross-spawn": "^6.0.5", - "enhanced-resolve": "^4.1.1", - "findup-sync": "^3.0.0", - "global-modules": "^2.0.0", - "import-local": "^2.0.0", - "interpret": "^1.4.0", - "loader-utils": "^1.4.0", - "supports-color": "^6.1.0", - "v8-compile-cache": "^2.1.1", - "yargs": "^13.3.2" - }, - "dependencies": { - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "webpack-sources": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", - "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", - "dev": true, - "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", - "dev": true, - "requires": { - "errno": "~0.1.7" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } -} diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/package.json b/dashboardv3/public/js/external_lib/atlas-lineage/package.json deleted file mode 100644 index 6e03eee3f5a..00000000000 --- a/dashboardv3/public/js/external_lib/atlas-lineage/package.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "atlas-lineage-module", - "version": "1.0.0", - "description": "The module will help to render the lineage graph with the help dagre-d3,d3 js lib", - "main": "dist/index.js", - "scripts": { - "start": "NODE_ENV=development webpack --watch", - "build": "webpack" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/apache/atlas.git" - }, - "keywords": [ - "lineage", - "dagre-d3", - "d3" - ], - "author": "kevalbhatt", - "license": "Apache-2.0", - "bugs": { - "url": "https://github.com/apache/atlas/issues" - }, - "homepage": "https://github.com/apache/atlas#readme", - "dependencies": { - "d3-tip": "^0.9.1", - "dagre-d3": "^0.6.4", - "platform": "^1.3.5" - }, - "devDependencies": { - "@babel/core": "^7.9.6", - "@babel/preset-env": "^7.9.6", - "babel-loader": "^8.1.0", - "babel-plugin-transform-class-properties": "^6.24.1", - "css-loader": "^3.5.3", - "mini-css-extract-plugin": "^0.9.0", - "path": "^0.12.7", - "sass": "^1.26.5", - "sass-loader": "^8.0.2", - "webpack": "^4.43.0", - "webpack-cli": "^3.3.11" - } -} diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/src/Enums.js b/dashboardv3/public/js/external_lib/atlas-lineage/src/Enums.js deleted file mode 100644 index 2773f124905..00000000000 --- a/dashboardv3/public/js/external_lib/atlas-lineage/src/Enums.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -export default { - entityStateReadOnly: { - ACTIVE: false, - DELETED: true, - STATUS_ACTIVE: false, - STATUS_DELETED: true - } -}; \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/DataUtils.js b/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/DataUtils.js deleted file mode 100644 index 1255eb070f0..00000000000 --- a/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/DataUtils.js +++ /dev/null @@ -1,361 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -import Enums from "../Enums"; -import { curveBasis } from "d3-shape"; - -const DataUtils = { - /** - * [getBaseUrl description] - * @param {[type]} url [description] - * @return {[type]} [description] - */ - getBaseUrl: function(url) { - return url.replace(/\/[\w-]+.(jsp|html)|\/+$/gi, ""); - }, - /** - * [getEntityIconPath description] - * @param {[type]} options.entityData [description] - * @param {Object} options.errorUrl } [description] - * @return {[type]} [description] - */ - getEntityIconPath: function({ entityData, errorUrl } = {}) { - var serviceType, - status, - typeName, - iconBasePath = this.getBaseUrl(window.location.pathname) + Globals.entityImgPath; - if (entityData) { - typeName = entityData.typeName; - serviceType = entityData && entityData.serviceType; - status = entityData && entityData.status; - } - - function getImgPath(imageName) { - return iconBasePath + (Enums.entityStateReadOnly[status] ? "disabled/" + imageName : imageName); - } - - function getDefaultImgPath() { - if (entityData.isProcess) { - if (Enums.entityStateReadOnly[status]) { - return iconBasePath + "disabled/process.png"; - } else { - return iconBasePath + "process.png"; - } - } else { - if (Enums.entityStateReadOnly[status]) { - return iconBasePath + "disabled/table.png"; - } else { - return iconBasePath + "table.png"; - } - } - } - - if (entityData) { - if (errorUrl) { - var isErrorInTypeName = errorUrl && errorUrl.match("entity-icon/" + typeName + ".png|disabled/" + typeName + ".png") ? true : false; - if (serviceType && isErrorInTypeName) { - var imageName = serviceType + ".png"; - return getImgPath(imageName); - } else { - return getDefaultImgPath(); - } - } else if (entityData.typeName) { - var imageName = entityData.typeName + ".png"; - return getImgPath(imageName); - } else { - return getDefaultImgPath(); - } - } - }, - /** - * [isProcess description] - * @param {[type]} options.typeName [description] - * @param {[type]} options.superTypes [description] - * @param {[type]} options.entityDef [description] - * @return {Boolean} [description] - */ - isProcess: function({ typeName, superTypes, entityDef }) { - if (typeName == "Process") { - return true; - } - return superTypes.indexOf("Process") > -1; - }, - /** - * [isDeleted description] - * @param {[type]} node [description] - * @return {Boolean} [description] - */ - isDeleted: function(node) { - if (node === undefined) { - return; - } - return Enums.entityStateReadOnly[node.status]; - }, - isNodeToBeUpdated: function(node, filterObj) { - var isProcessHideCheck = filterObj.isProcessHideCheck, - isDeletedEntityHideCheck = filterObj.isDeletedEntityHideCheck; - var returnObj = { - isProcess: isProcessHideCheck && node.isProcess, - isDeleted: isDeletedEntityHideCheck && node.isDeleted - }; - returnObj["update"] = returnObj.isProcess || returnObj.isDeleted; - return returnObj; - }, - /** - * [getServiceType description] - * @param {[type]} options.typeName [description] - * @param {[type]} options.entityDef [description] - * @return {[type]} [description] - */ - getServiceType: function({ typeName, entityDef }) { - var serviceType = null; - if (typeName) { - if (entityDef) { - serviceType = entityDef.serviceType || null; - } - } - return serviceType; - }, - /** - * [getEntityDef description] - * @param {[type]} options.typeName [description] - * @param {[type]} options.entityDefCollection [description] - * @return {[type]} [description] - */ - getEntityDef: function({ typeName, entityDefCollection }) { - var entityDef = null; - if (typeName) { - entityDef = entityDefCollection.find(function(obj) { - return obj.name == typeName; - }); - } - return entityDef; - }, - /** - * [getNestedSuperTypes description] - * @param {[type]} options.entityDef [description] - * @param {[type]} options.entityDefCollection [description] - * @return {[type]} [description] - */ - getNestedSuperTypes: function({ entityDef, entityDefCollection }) { - var data = entityDef, - collection = entityDefCollection, - superTypes = new Set(); - - var getData = function(data, collection) { - if (data) { - if (data.superTypes && data.superTypes.length) { - data.superTypes.forEach(function(superTypeName) { - superTypes.add(superTypeName); - var collectionData = collection.find(function(obj) { - obj.name === superTypeName; - }); - if (collectionData) { - getData(collectionData, collection); - } - }); - } - } - }; - getData(data, collection); - return Array.from(superTypes); - }, - generateData: function({ data = {}, filterObj, entityDefCollection, g, guid, setGraphEdge, setGraphNode }) { - return new Promise((resolve, reject) => { - try { - var relations = data.relations || {}, - guidEntityMap = data.guidEntityMap || {}, - isHideFilterOn = filterObj.isProcessHideCheck || filterObj.isDeletedEntityHideCheck, - newHashMap = {}, - styleObj = { - fill: "none", - stroke: "#ffb203", - width: 3 - }, - makeNodeData = (relationObj) => { - if (relationObj) { - if (relationObj.updatedValues) { - return relationObj; - } - var obj = Object.assign(relationObj, { - shape: "img", - updatedValues: true, - label: relationObj.displayText.trunc(18), - toolTipLabel: relationObj.displayText, - id: relationObj.guid, - isLineage: true, - isIncomplete: relationObj.isIncomplete, - entityDef: this.getEntityDef({ typeName: relationObj.typeName, entityDefCollection }) - }); - obj["serviceType"] = this.getServiceType(obj); - obj["superTypes"] = this.getNestedSuperTypes({ - ...obj, - entityDefCollection: entityDefCollection - }); - obj["isProcess"] = this.isProcess(obj); - obj["isDeleted"] = this.isDeleted(obj); - return obj; - } - }, - crateLineageRelationshipHashMap = function({ relations } = {}) { - var newHashMap = {}; - relations.forEach(function(obj) { - if (newHashMap[obj.fromEntityId]) { - newHashMap[obj.fromEntityId].push(obj.toEntityId); - } else { - newHashMap[obj.fromEntityId] = [obj.toEntityId]; - } - }); - return newHashMap; - }, - getStyleObjStr = function(styleObj) { - return "fill:" + styleObj.fill + ";stroke:" + styleObj.stroke + ";stroke-width:" + styleObj.width; - }, - getNewToNodeRelationship = (toNodeGuid, filterObj) => { - if (toNodeGuid && relationshipMap[toNodeGuid]) { - var newRelationship = []; - relationshipMap[toNodeGuid].forEach((guid) => { - var nodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[guid]), filterObj); - if (nodeToBeUpdated.update) { - var newRelation = getNewToNodeRelationship(guid, filterObj); - if (newRelation) { - newRelationship = newRelationship.concat(newRelation); - } - } else { - newRelationship.push(guid); - } - }); - return newRelationship; - } else { - return null; - } - }, - getToNodeRelation = (toNodes, fromNodeToBeUpdated, filterObj) => { - var toNodeRelationship = []; - toNodes.forEach((toNodeGuid) => { - var toNodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[toNodeGuid]), filterObj); - if (toNodeToBeUpdated.update) { - // To node need to updated - if (pendingFromRelationship[toNodeGuid]) { - toNodeRelationship = toNodeRelationship.concat(pendingFromRelationship[toNodeGuid]); - } else { - var newToNodeRelationship = getNewToNodeRelationship(toNodeGuid, filterObj); - if (newToNodeRelationship) { - toNodeRelationship = toNodeRelationship.concat(newToNodeRelationship); - } - } - } else { - //when bothe node not to be updated. - toNodeRelationship.push(toNodeGuid); - } - }); - return toNodeRelationship; - }, - setNode = (guid) => { - if (!g._nodes[guid]) { - var nodeData = makeNodeData(guidEntityMap[guid]); - setGraphNode(guid, nodeData); - return nodeData; - } else { - return g._nodes[guid]; - } - }, - setEdge = function(fromNodeGuid, toNodeGuid, opt = {}) { - setGraphEdge(fromNodeGuid, toNodeGuid, { - arrowhead: "arrowPoint", - curve: curveBasis, - style: getStyleObjStr(styleObj), - styleObj: styleObj, - ...opt - }); - }, - setGraphData = function(fromEntityId, toEntityId) { - setNode(fromEntityId); - setNode(toEntityId); - setEdge(fromEntityId, toEntityId); - }, - pendingFromRelationship = {}; - if (isHideFilterOn) { - var relationshipMap = crateLineageRelationshipHashMap(data); - Object.keys(relationshipMap).forEach((fromNodeGuid) => { - var toNodes = relationshipMap[fromNodeGuid], - fromNodeToBeUpdated = this.isNodeToBeUpdated(makeNodeData(guidEntityMap[fromNodeGuid]), filterObj), - toNodeList = getToNodeRelation(toNodes, fromNodeToBeUpdated, filterObj); - if (fromNodeToBeUpdated.update) { - if (pendingFromRelationship[fromNodeGuid]) { - pendingFromRelationship[fromNodeGuid] = pendingFromRelationship[fromNodeGuid].concat(toNodeList); - } else { - pendingFromRelationship[fromNodeGuid] = toNodeList; - } - } else { - toNodeList.forEach(function(toNodeGuid) { - setGraphData(fromNodeGuid, toNodeGuid); - }); - } - }); - } else { - relations.forEach(function(obj) { - setGraphData(obj.fromEntityId, obj.toEntityId); - }); - } - if (g._nodes[guid]) { - if (g._nodes[guid]) { - g._nodes[guid]["isLineage"] = false; - } - this.findImpactNodeAndUpdateData({ - guid, - g, - setEdge, - getStyleObjStr - }); - } - resolve(g); - } catch (e) { - reject(e); - } - }); - }, - findImpactNodeAndUpdateData: function({ guid, getStyleObjStr, g, setEdge }) { - var that = this, - traversedMap = {}, - styleObj = { - fill: "none", - stroke: "#fb4200", - width: 3 - }, - traversed = function(toNodeList = {}, fromNodeGuid) { - let toNodeKeyList = Object.keys(toNodeList); - if (toNodeKeyList.length) { - if (!traversedMap[fromNodeGuid]) { - traversedMap[fromNodeGuid] = true; - toNodeKeyList.forEach(function(toNodeGuid) { - if (g._nodes[toNodeGuid]) { - g._nodes[toNodeGuid]["isLineage"] = false; - } - setEdge(fromNodeGuid, toNodeGuid, { - style: getStyleObjStr(styleObj), - styleObj: styleObj - }); - traversed(g._sucs[toNodeGuid], toNodeGuid); - }); - } - } - }; - traversed(g._sucs[guid], guid); - } -}; -export default DataUtils; \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/LineageUtils.js b/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/LineageUtils.js deleted file mode 100644 index 448a95ae6eb..00000000000 --- a/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/LineageUtils.js +++ /dev/null @@ -1,608 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import { select, event } from "d3-selection"; -import { zoom, zoomIdentity } from "d3-zoom"; -import { drag } from "d3-drag"; -import { line, curveBasis } from "d3-shape"; - -import platform from "platform"; - -import Enums from "../Enums"; - -const LineageUtils = { - /** - * [nodeArrowDistance variable use to define the distance between arrow and node] - * @type {Number} - */ - nodeArrowDistance: 24, - refreshGraphForSafari: function (options) { - var edgePathEl = options.edgeEl, - IEGraphRenderDone = 0; - edgePathEl.each(function (argument) { - var eleRef = this, - childNode = $(this).find("pattern"); - setTimeout(function (argument) { - $(eleRef).find("defs").append(childNode); - }, 500); - }); - }, - refreshGraphForIE: function ({ edgePathEl }) { - var IEGraphRenderDone = 0; - edgePathEl.each(function (argument) { - var childNode = $(this).find("marker"); - $(this).find("marker").remove(); - var eleRef = this; - ++IEGraphRenderDone; - setTimeout(function (argument) { - $(eleRef).find("defs").append(childNode); - --IEGraphRenderDone; - if (IEGraphRenderDone === 0) { - this.$(".fontLoader").hide(); - this.$("svg").fadeTo(1000, 1); - } - }, 1000); - }); - }, - /** - * [dragNode description] - * @param {[type]} options.g [description] - * @param {[type]} options.svg [description] - * @param {[type]} options.guid [description] - * @param {[type]} options.edgePathEl [description] - * @return {[type]} [description] - */ - dragNode: function ({ g, svg, guid, edgePathEl }) { - var dragHelper = { - dragmove: function (el, d) { - var node = select(el), - selectedNode = g.node(d), - prevX = selectedNode.x, - prevY = selectedNode.y; - - selectedNode.x += event.dx; - selectedNode.y += event.dy; - node.attr("transform", "translate(" + selectedNode.x + "," + selectedNode.y + ")"); - - var dx = selectedNode.x - prevX, - dy = selectedNode.y - prevY; - - g.edges().forEach((e) => { - if (e.v == d || e.w == d) { - var edge = g.edge(e.v, e.w); - this.translateEdge(edge, dx, dy); - select(edge.elem).select("path").attr("d", this.calcPoints(e)); - } - }); - //LineageUtils.refreshGraphForIE({ edgePathEl: edgePathEl }); - }, - translateEdge: function (e, dx, dy) { - e.points.forEach(function (p) { - p.x = p.x + dx; - p.y = p.y + dy; - }); - }, - calcPoints: function (e) { - var edge = g.edge(e.v, e.w), - tail = g.node(e.v), - head = g.node(e.w), - points = edge.points.slice(1, edge.points.length - 1), - afterslice = edge.points.slice(1, edge.points.length - 1); - points.unshift(this.intersectRect(tail, points[0])); - points.push(this.intersectRect(head, points[points.length - 1])); - return line() - .x(function (d) { - return d.x; - }) - .y(function (d) { - return d.y; - }) - .curve(curveBasis)(points); - }, - intersectRect: (node, point) => { - var x = node.x, - y = node.y, - dx = point.x - x, - dy = point.y - y, - nodeDistance = guid ? this.nodeArrowDistance + 3 : this.nodeArrowDistance, - w = nodeDistance, - h = nodeDistance, - sx = 0, - sy = 0; - - if (Math.abs(dy) * w > Math.abs(dx) * h) { - // Intersection is top or bottom of rect. - if (dy < 0) { - h = -h; - } - sx = dy === 0 ? 0 : (h * dx) / dy; - sy = h; - } else { - // Intersection is left or right of rect. - if (dx < 0) { - w = -w; - } - sx = w; - sy = dx === 0 ? 0 : (w * dy) / dx; - } - return { - x: x + sx, - y: y + sy - }; - } - }; - var dragNodeHandler = drag().on("drag", function (d) { - dragHelper.dragmove.call(dragHelper, this, d); - }), - dragEdgePathHandler = drag().on("drag", function (d) { - dragHelper.translateEdge(g.edge(d.v, d.w), event.dx, event.dy); - var edgeObj = g.edge(d.v, d.w); - select(edgeObj.elem).select("path").attr("d", dragHelper.calcPoints(d)); - }); - - dragNodeHandler(svg.selectAll("g.node")); - dragEdgePathHandler(svg.selectAll("g.edgePath")); - }, - zoomIn: function ({ svg, scaleFactor = 1.3 }) { - this.d3Zoom.scaleBy(svg.transition().duration(750), scaleFactor); - }, - zoomOut: function ({ svg, scaleFactor = 0.8 }) { - this.d3Zoom.scaleBy(svg.transition().duration(750), scaleFactor); - }, - zoom: function ({ svg, xa, ya, scale }) { - svg.transition().duration(750).call(this.d3Zoom.transform, zoomIdentity.translate(xa, ya).scale(scale)); - }, - fitToScreen: function ({ svg }) { - var node = svg.node(); - var bounds = node.getBBox(); - - var parent = node.parentElement, - fullWidth = parent.clientWidth, - fullHeight = parent.clientHeight; - - var width = bounds.width, - height = bounds.height; - var midX = bounds.x + width / 2, - midY = bounds.y + height / 2; - - var scale = (scale || 0.95) / Math.max(width / fullWidth, height / fullHeight), - xa = fullWidth / 2 - scale * midX, - ya = fullHeight / 2 - scale * midY; - this.zoom({ svg, xa, ya, scale }); - }, - /** - * [centerNode description] - * @param {[type]} options.guid [description] - * @param {[type]} options.g [description] - * @param {[type]} options.svg [description] - * @param {[type]} options.svgGroupEl [description] - * @param {[type]} options.edgePathEl [description] - * @param {[type]} options.width [description] - * @param {[type]} options.height [description] - * @param {[type]} options.onCenterZoomed [description] - * @return {[type]} [description] - */ - centerNode: function ({ guid, g, svg, svgGroupEl, edgePathEl, width, height, fitToScreen, onCenterZoomed }) { - this.d3Zoom = zoom(); - svg.call(this.d3Zoom).on("dblclick.zoom", null); - - // restrict events - - let selectedNodeEl = svg.selectAll("g.nodes>g[id='" + guid + "']"), - zoomListener = this.d3Zoom.scaleExtent([0.01, 50]).on("zoom", function () { - svgGroupEl.attr("transform", event.transform); - }), - x = null, - y = null, - scale = 1.2; - if (selectedNodeEl.empty()) { - if (fitToScreen) { - this.fitToScreen({ svg }); - return; - } else { - x = g.graph().width / 2; - y = g.graph().height / 2; - } - } else { - var matrix = selectedNodeEl - .attr("transform") - .replace(/[^0-9\-.,]/g, "") - .split(","); - // if (platform.name === "IE" || platform.name === "Microsoft Edge") { - // var matrix = selectedNode - // .attr("transform") - // .replace(/[a-z\()]/g, "") - // .split(" "); - // } - x = matrix[0]; - y = matrix[1]; - } - - var xa = -(x * scale - width / 2), - ya = -(y * scale - height / 2); - this.zoom({ svg, xa, ya, scale }); - svg.transition().duration(750).call(this.d3Zoom.transform, zoomIdentity.translate(xa, ya).scale(scale)); - - if (onCenterZoomed) { - onCenterZoomed({ newScale: scale, newTranslate: [xa, ya], d3Zoom: this.d3Zoom, selectedNodeEl }); - } - // if (platform.name === "IE") { - // LineageUtils.refreshGraphForIE({ edgePathEl: edgePathEl }); - // } - }, - /** - * [getToolTipDirection description] - * @param {[type]} options.el [description] - * @return {[type]} [description] - */ - getToolTipDirection: function ({ el }) { - var width = select("body").node().getBoundingClientRect().width, - currentELWidth = select(el).node().getBoundingClientRect(), - direction = "e"; - if (width - currentELWidth.left < 330) { - direction = width - currentELWidth.left < 330 && currentELWidth.top < 400 ? "sw" : "w"; - if (width - currentELWidth.left < 330 && currentELWidth.top > 600) { - direction = "nw"; - } - } else if (currentELWidth.top > 600) { - direction = width - currentELWidth.left < 330 && currentELWidth.top > 600 ? "nw" : "n"; - if (currentELWidth.left < 50) { - direction = "ne"; - } - } else if (currentELWidth.top < 400) { - direction = currentELWidth.left < 50 ? "se" : "s"; - } - return direction; - }, - /** - * [onHoverFade description] - * @param {[type]} options.svg [description] - * @param {[type]} options.g [description] - * @param {[type]} options.mouseenter [description] - * @param {[type]} options.opacity [description] - * @param {[type]} options.nodesToHighlight [description] - * @param {[type]} options.hoveredNode [description] - * @return {[type]} [description] - */ - onHoverFade: function ({ svg, g, mouseenter, nodesToHighlight, hoveredNode }) { - var node = svg.selectAll(".node"), - path = svg.selectAll(".edgePath"), - isConnected = function (a, b, o) { - if (a === o || (b && b.length && b.indexOf(o) != -1)) { - return true; - } - }; - if (mouseenter) { - svg.classed("hover", true); - var nextNode = g.successors(hoveredNode), - previousNode = g.predecessors(hoveredNode), - nodesToHighlight = nextNode.concat(previousNode); - node.classed("hover-active-node", function (currentNode, i, nodes) { - if (isConnected(hoveredNode, nodesToHighlight, currentNode)) { - return true; - } else { - return false; - } - }); - path.classed("hover-active-path", function (c) { - var _thisOpacity = c.v === hoveredNode || c.w === hoveredNode ? 1 : 0; - if (_thisOpacity) { - return true; - } else { - return false; - } - }); - } else { - svg.classed("hover", false); - node.classed("hover-active-node", false); - path.classed("hover-active-path", false); - } - }, - /** - * [getBaseUrl description] - * @param {[type]} path [description] - * @return {[type]} [description] - */ - getBaseUrl: function (url = window.location.pathname) { - return url.replace(/\/[\w-]+.(jsp|html)|\/+$/gi, ""); - }, - getEntityIconPath: function ({ entityData, errorUrl, imgBasePath }) { - var iconBasePath = this.getBaseUrl() + (imgBasePath || "/img/entity-icon/"); - if (entityData) { - let { typeName, serviceType, status, isProcess } = entityData; - - function getImgPath(imageName) { - return iconBasePath + (Enums.entityStateReadOnly[status] ? "disabled/" + imageName : imageName); - } - - function getDefaultImgPath() { - if (isProcess) { - if (Enums.entityStateReadOnly[status]) { - return iconBasePath + "disabled/process.png"; - } else { - return iconBasePath + "process.png"; - } - } else { - if (Enums.entityStateReadOnly[status]) { - return iconBasePath + "disabled/table.png"; - } else { - return iconBasePath + "table.png"; - } - } - } - - if (errorUrl) { - // Check if the default img path has error, if yes then stop recursion. - if (errorUrl.indexOf("table.png") > -1 || errorUrl.indexOf("process.png") > -1) { - return null; - } - var isErrorInTypeName = errorUrl && errorUrl.match("entity-icon/" + typeName + ".png|disabled/" + typeName + ".png") ? true : false; - if (serviceType && isErrorInTypeName) { - var imageName = serviceType + ".png"; - return getImgPath(imageName); - } else { - return getDefaultImgPath(); - } - } else if (typeName) { - var imageName = typeName + ".png"; - return getImgPath(imageName); - } else if (serviceType) { - var imageName = serviceType + ".png"; - return getImgPath(imageName); - } else { - return getDefaultImgPath(); - } - } - }, - base64Encode: function (file, callback) { - const reader = new FileReader(); - reader.addEventListener("load", () => callback(reader.result)); - reader.readAsDataURL(file); - }, - imgShapeRender: function (parent, bbox, node, { dagreD3, defsEl, imgBasePath, guid, isRankdirToBottom }) { - var that = this, - viewGuid = guid, - imageIconPath = this.getEntityIconPath({ entityData: node, imgBasePath }), - imgName = imageIconPath.split("/").pop(); - if (this.imageObject === undefined) { - this.imageObject = {}; - } - if (node.isDeleted) { - imgName = "deleted_" + imgName; - } - if (node.id == viewGuid) { - var currentNode = true; - } - var shapeSvg = parent - .append("circle") - .attr("fill", "url(#img_" + encodeURI(imgName) + ")") - .attr("r", isRankdirToBottom ? "30px" : "24px") - .attr("data-stroke", node.id) - .attr("stroke-width", "2px") - .attr("class", "nodeImage " + (currentNode ? "currentNode" : node.isProcess ? "process" : "node")); - if (currentNode) { - shapeSvg.attr("stroke", "#fb4200"); - } - if (node.isIncomplete === true) { - parent.attr("class", "node isIncomplete show"); - parent - .insert("foreignObject") - .attr("x", "-25") - .attr("y", "-25") - .attr("width", "50") - .attr("height", "50") - .append("xhtml:div") - .insert("i") - .attr("class", "fa fa-hourglass-half"); - } - - if (defsEl.select('pattern[id="img_' + imgName + '"]').empty()) { - defsEl - .append("pattern") - .attr("x", "0%") - .attr("y", "0%") - .attr("patternUnits", "objectBoundingBox") - .attr("id", "img_" + imgName) - .attr("width", "100%") - .attr("height", "100%") - .append("image") - .attr("href", function (d) { - var imgEl = this; - if (node) { - var getImageData = function (options) { - var imagePath = options.imagePath, - ajaxOptions = { - url: imagePath, - method: "GET", - cache: true - }; - - // if (platform.name !== "IE") { - // ajaxOptions["mimeType"] = "text/plain; charset=x-user-defined"; - // } - shapeSvg.attr("data-iconpath", imagePath); - var xhr = new XMLHttpRequest(); - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - if (xhr.status === 200) { - if (platform.name !== "IE") { - that.base64Encode(this.response, (url) => { - that.imageObject[imageIconPath] = url; - select(imgEl).attr("xlink:href", url); - }); - } else { - that.imageObject[imageIconPath] = imagePath; - } - if (imageIconPath !== shapeSvg.attr("data-iconpath")) { - shapeSvg.attr("data-iconpathorigin", imageIconPath); - } - } else if (xhr.status === 404) { - const imgPath = that.getEntityIconPath({ entityData: node, errorUrl: imagePath }); - if (imgPath === null) { - const patternEL = select(imgEl.parentElement); - patternEL.select("image").remove(); - patternEL - .attr("patternContentUnits", "objectBoundingBox") - .append("circle") - .attr("r", "24px") - .attr("fill", "#e8e8e8"); - } else { - getImageData({ - imagePath: imgPath - }); - } - } - } - }; - xhr.responseType = "blob"; - xhr.open(ajaxOptions.method, ajaxOptions.url, true); - xhr.send(null); - }; - getImageData({ - imagePath: imageIconPath - }); - } - }) - .attr("x", isRankdirToBottom ? "11" : "4") - .attr("y", isRankdirToBottom ? "20" : currentNode ? "3" : "4") - .attr("width", "40") - .attr("height", "40"); - } - - node.intersect = function (point) { - return dagreD3.intersect.circle(node, currentNode ? that.nodeArrowDistance + 3 : that.nodeArrowDistance, point); - }; - return shapeSvg; - }, - /** - * [arrowPointRender description] - * @param {[type]} {parent, id, edge, type, viewOptions [description] - * @return {[type]} [description] - */ - arrowPointRender: function (parent, id, edge, type, { dagreD3 }) { - var node = parent.node(), - parentNode = node ? node.parentNode : parent; - select(parentNode) - .select("path.path") - .attr("marker-end", "url(#" + id + ")"); - var marker = parent - .append("marker") - .attr("id", id) - .attr("viewBox", "0 0 10 10") - .attr("refX", 8) - .attr("refY", 5) - .attr("markerUnits", "strokeWidth") - .attr("markerWidth", 4) - .attr("markerHeight", 4) - .attr("orient", "auto"); - - var path = marker.append("path").attr("d", "M 0 0 L 10 5 L 0 10 z").style("fill", edge.styleObj.stroke); - dagreD3.util.applyStyle(path, edge[type + "Style"]); - }, - /** - * [saveSvg description] - * @param {[type]} options.svg [description] - * @param {[type]} options.width [description] - * @param {[type]} options.height [description] - * @param {[type]} options.downloadFileName [description] - * @param {[type]} options.onExportLineage [description] - * @return {[type]} [description] - */ - saveSvg: function ({ svg, width, height, downloadFileName, onExportLineage }) { - var that = this, - svgClone = svg.clone(true).node(), - scaleFactor = 1; - setTimeout(function () { - if (platform.name === "Firefox") { - svgClone.setAttribute("width", width); - svgClone.setAttribute("height", height); - } - const hiddenSvgEl = select("body").append("div"); - hiddenSvgEl.classed("hidden-svg", true); - hiddenSvgEl.node().appendChild(svgClone); - - const svgCloneEl = select(".hidden-svg svg"); - svgCloneEl.select("g").attr("transform", "scale(" + scaleFactor + ")"); - svgCloneEl.select("foreignObject").remove(); - - var canvasOffset = { x: 150, y: 150 }, - setWidth = svgClone.getBBox().width + canvasOffset.x, - setHeight = svgClone.getBBox().height + canvasOffset.y, - xAxis = svgClone.getBBox().x, - yAxis = svgClone.getBBox().y; - svgClone.attributes.viewBox.value = xAxis + "," + yAxis + "," + setWidth + "," + setHeight; - - var canvas = document.createElement("canvas"); - canvas.id = "canvas"; - canvas.style.display = "none"; - canvas.width = svgClone.getBBox().width * scaleFactor + canvasOffset.x; - canvas.height = svgClone.getBBox().height * scaleFactor + canvasOffset.y; - - // Append Canvas in DOM - select("body").node().appendChild(canvas); - - var ctx = canvas.getContext("2d"), - data = new XMLSerializer().serializeToString(svgClone), - DOMURL = window.URL || window.webkitURL || window; - - ctx.fillStyle = "#FFFFFF"; - ctx.fillRect(0, 0, canvas.width, canvas.height); - ctx.strokeRect(0, 0, canvas.width, canvas.height); - ctx.restore(); - - var img = new Image(canvas.width, canvas.height); - var svgBlob = new Blob([data], { type: "image/svg+xml;base64" }); - if (platform.name === "Safari") { - svgBlob = new Blob([data], { type: "image/svg+xml" }); - } - var url = DOMURL.createObjectURL(svgBlob); - - img.onload = function () { - try { - var a = document.createElement("a"); - a.download = downloadFileName; - document.body.appendChild(a); - ctx.drawImage(img, 50, 50, canvas.width, canvas.height); - canvas.toBlob(function (blob) { - if (!blob) { - onExportLineage({ status: "failed", message: "There was an error in downloading Lineage!" }); - return; - } - a.href = DOMURL.createObjectURL(blob); - if (blob.size > 10000000) { - onExportLineage({ status: "failed", message: "The Image size is huge, please open the image in a browser!" }); - } - a.click(); - onExportLineage({ status: "Success", message: "Successful" }); - if (platform.name === "Safari") { - that.refreshGraphForSafari({ - edgeEl: that.$("svg g.node") - }); - } - }, "image/png"); - hiddenSvgEl.remove(); - canvas.remove(); - } catch (err) { - onExportLineage({ status: "failed", message: "There was an error in downloading Lineage!" }); - } - }; - img.src = url; - }, 0); - } -}; -export default LineageUtils; \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/index.js b/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/index.js deleted file mode 100644 index f7153167c24..00000000000 --- a/dashboardv3/public/js/external_lib/atlas-lineage/src/Utils/index.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import LineageUtils from "./LineageUtils"; -import DataUtils from "./DataUtils"; - -String.prototype.trunc = - String.prototype.trunc || - function(n) { - return this.length > n ? this.substr(0, n - 1) + "..." : this; - }; - -export { LineageUtils, DataUtils }; \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/src/index.js b/dashboardv3/public/js/external_lib/atlas-lineage/src/index.js deleted file mode 100644 index 3ceb3d90a90..00000000000 --- a/dashboardv3/public/js/external_lib/atlas-lineage/src/index.js +++ /dev/null @@ -1,655 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -import dagreD3 from "dagre-d3"; -import { select, selection, event } from "d3-selection"; -import { curveBasis } from "d3-shape"; -import { LineageUtils, DataUtils } from "./Utils"; -import d3Tip from "d3-tip"; - -import "./styles/style.scss"; - -export default class LineageHelper { - constructor(options) { - this.options = {}; - this._updateOptions(options); - const { el, manualTrigger = false } = this.options; - if (el === undefined) { - throw new Error("LineageHelper requires el propety to render the graph"); - } - this.initReturnObj = { - init: (arg) => this.init(arg), - updateOptions: (options) => this._updateAllOptions(options), - createGraph: (opt = {}) => this._createGraph(this.options, this.graphOptions, opt), - clear: (arg) => this.clear(arg), - refresh: (arg) => this.refresh(arg), - centerAlign: (arg) => this.centerAlign(arg), - exportLineage: (arg) => this.exportLineage(arg), - zoomIn: (arg) => this.zoomIn(arg), - zoomOut: (arg) => this.zoomOut(arg), - zoom: (arg) => this.zoom(arg), - fullScreen: (arg) => this.fullScreen(arg), - searchNode: (arg) => this.searchNode(arg), - removeNodeSelection: (arg) => this.removeNodeSelection(arg), - getGraphOptions: () => this.graphOptions, - getNode: (guid, actual) => { - let rObj = null; - if (actual) { - rObj = this.actualData[guid]; - } else { - rObj = this.g._nodes[guid]; - } - if (rObj) { - rObj = Object.assign({}, rObj); - } - return rObj; - }, - getNodes: (guid, actual) => { - let rObj = null; - if (actual) { - rObj = this.actualData; - } else { - rObj = this.g._nodes; - } - if (rObj) { - rObj = Object.assign({}, rObj); - } - return rObj; - }, - setNode: this._setGraphNode, - setEdge: this._setGraphEdge - }; - if (manualTrigger === false) { - this.init(); - } - return this.initReturnObj; - } - /** - * [updateAllOptions] - * @param {[type]} - * @return {[type]} - */ - _updateAllOptions(options) { - Object.assign(this.options, options); - var svgRect = this.svg.node().getBoundingClientRect(); - this.graphOptions.width = this.options.width || svgRect.width; - this.graphOptions.height = this.options.height || svgRect.height; - const { svg, width, height, guid } = this.graphOptions; - const { fitToScreen } = this.options; - svg.select("g").node().removeAttribute("transform"); - svg.attr("viewBox", "0 0 " + width + " " + height).attr("enable-background", "new 0 0 " + width + " " + height); - this.centerAlign({ fitToScreen, guid }); - } - /** - * [updateOptions get the options from user and appedn add it in this,option context] - * @param {[Object]} options [lib options from user] - * @return {[null]} [null] - */ - _updateOptions(options) { - Object.assign(this.options, { filterObj: { isProcessHideCheck: false, isDeletedEntityHideCheck: false } }, options); - } - /** - * [init Start the graph build process] - * @return {[null]} [null] - */ - init() { - const { data = {} } = this.options; - if (data.baseEntityGuid) { - this.guid = data.baseEntityGuid; - } - // Call the initializeGraph method to initlize dagreD3 graphlib - this._initializeGraph(); - this._initGraph(); - } - /** - * [clear Allows user to clear the graph refrence and dom] - * @return {[type]} [description] - */ - clear() { - if (!this.options.el) { - this.svg.remove(); - this.svg = null; - } - this.g = null; - this.graphOptions = {}; - } - /** - * [centerAlign Allows user to center the lineage position, without rerender] - * @return {[type]} [description] - */ - centerAlign(opt = {}) { - var svgGroupEl = this.svg.select("g"), - edgePathEl = svgGroupEl.selectAll("g.edgePath"); - LineageUtils.centerNode({ - ...this.graphOptions, - svgGroupEl, - edgePathEl, - ...opt - }); - } - /** - * [zoomIn description] - * @return {[type]} [description] - */ - zoomIn(opt = {}) { - LineageUtils.zoomIn({ ...this.graphOptions, ...opt }); - } - /** - * [zoomOut description] - * @return {[type]} [description] - */ - zoomOut(opt = {}) { - LineageUtils.zoomOut({ ...this.graphOptions, ...opt }); - } - /** - * [zoom description] - * @return {[type]} [description] - */ - zoom(opt = {}) { - LineageUtils.zoom({ ...this.graphOptions, ...opt }); - } - /** - * [refresh Allows user to rerender the lineage] - * @return {[type]} [description] - */ - refresh() { - this.clear(); - this._initializeGraph(); - this._initGraph({ refresh: true }); - } - /** - * [removeNodeSelection description] - * @return {[type]} [description] - */ - removeNodeSelection() { - this.svg.selectAll("g.node>circle").classed("node-detail-highlight", false); - } - /** - * [searchNode description] - * @return {[type]} [description] - */ - searchNode({ guid, onSearchNode }) { - this.svg.selectAll(".serach-rect").remove(); - this.centerAlign({ - guid: guid, - onCenterZoomed: function (opts) { - const { selectedNodeEl } = opts; - selectedNodeEl.select(".label").attr("stroke", "#316132"); - selectedNodeEl.select("circle").classed("wobble", true); - selectedNodeEl - .insert("rect", "circle") - .attr("class", "serach-rect") - .attr("x", -50) - .attr("y", -27.5) - .attr("width", 100) - .attr("height", 55); - if (onSearchNode && typeof onSearchNode === "function") { - onSearchNode(opts); - } - } - }); - } - - /** - * [exportLineage description] - * @param {Object} options [description] - * @return {[type]} [description] - */ - exportLineage(options = {}) { - let downloadFileName = options.downloadFileName; - if (downloadFileName === undefined) { - let node = this.g._nodes[this.guid]; - if (node && node.attributes) { - downloadFileName = `${node.attributes.qualifiedName || node.attributes.name || "lineage_export"}.png`; - } else { - downloadFileName = "export.png"; - } - } - - LineageUtils.saveSvg({ - ...this.graphOptions, - downloadFileName: downloadFileName, - onExportLineage: (opt) => { - if (options.onExportLineage) { - onExportLineage(opt); - } - } - }); - } - /** - * [fullScreen description] - * @param {Object} options.el } [description] - * @return {[type]} [description] - */ - fullScreen({ el } = {}) { - if (el === undefined) { - throw new Error("LineageHelper requires el propety to apply fullScreen class"); - } - const fullScreenEl = select(el); - if (fullScreenEl.classed("fullscreen-mode")) { - fullScreenEl.classed("fullscreen-mode", false); - return false; - } else { - fullScreenEl.classed("fullscreen-mode", true); - return true; - } - } - /** - * [_getValueFromUser description] - * @param {[type]} ref [description] - * @return {[type]} [description] - */ - _getValueFromUser(ref) { - if (ref !== undefined) { - if (typeof ref === "function") { - return ref(); - } else { - return ref; - } - } - return; - } - /** - * [initializeGraph initlize the dagreD3 graphlib] - * @return {[null]} [null] - */ - _initializeGraph() { - const { width = "100%", height = "100%", el } = this.options; - - // Append the svg using d3. - this.svg = select(el); - - if (!(el instanceof SVGElement)) { - this.svg.selectAll("*").remove(); - this.svg = this.svg - .append("svg") - .attr("xmlns", "http://www.w3.org/2000/svg") - .attr(" xmlns:xlink", "http://www.w3.org/1999/xlink") - .attr("version", "1.1") - .attr("width", width) - .attr("height", height); - } - // initlize the dagreD3 graphlib - this.g = new dagreD3.graphlib.Graph() - .setGraph( - Object.assign( - { - nodesep: 50, - ranksep: 90, - rankdir: "LR", - marginx: 20, - marginy: 20, - transition: function transition(selection) { - return selection.transition().duration(500); - } - }, - this.options.dagreOptions - ) - ) - .setDefaultEdgeLabel(function () { - return {}; - }); - - // Create graphOptions for common use - var svgRect = this.svg.node().getBoundingClientRect(); - this.actualData = {}; - this.graphOptions = { - svg: this.svg, - g: this.g, - dagreD3: dagreD3, - guid: this.guid, - width: this.options.width || svgRect.width, - height: this.options.height || svgRect.height - }; - } - /** - * [_initGraph description] - * @return {[type]} [description] - */ - _initGraph({ refresh } = {}) { - if (this.svg) { - this.svg.select("g").remove(); - } - let filterObj = this.options.filterObj; - if (this.options.getFilterObj) { - let filterObjVal = this.options.getFilterObj(); - if (filterObjVal !== undefined || filterObjVal !== null) { - if (typeof filterObjVal === "object") { - filterObj = filterObjVal; - } else { - throw new Error("getFilterObj expect return type `object`,`null` or `Undefined`"); - } - } - } - - if (this.options.setDataManually === true) { - return; - } else if (this.options.data === undefined || (this.options.data && this.options.data.relations.length === 0)) { - if (this.options.beforeRender) { - this.options.beforeRender(); - } - this.svg - .append("text") - .attr("x", "50%") - .attr("y", "50%") - .attr("alignment-baseline", "middle") - .attr("text-anchor", "middle") - .text("No lineage data found"); - if (this.options.afterRender) { - this.options.afterRender(); - } - return; - } - - return DataUtils.generateData({ - ...this.options, - filterObj: filterObj, - ...this.graphOptions, - setGraphNode: this._setGraphNode, - setGraphEdge: this._setGraphEdge - }).then((graphObj) => { - this._createGraph(this.options, this.graphOptions, { refresh }); - }); - } - - /** - * [description] - * @param {[type]} guid [description] - * @param {[type]} nodeData [description] - * @return {[type]} [description] - */ - _setGraphNode = (guid, nodeData) => { - this.actualData[guid] = Object.assign({}, nodeData); - this.g.setNode(guid, nodeData); - }; - - /** - * [description] - * @param {[type]} fromGuid [description] - * @param {[type]} toGuid [description] - * @param {[type]} opts [description] - * @return {[type]} [description] - */ - _setGraphEdge = (fromGuid, toGuid, opts) => { - this.g.setEdge(fromGuid, toGuid, { - curve: curveBasis, - ...opts - }); - }; - /** - * [_createGraph description] - * @param {Object} options.data [description] - * @param {Boolean} isShowTooltip [description] - * @param {Boolean} isShowHoverPath [description] - * @param {[type]} onLabelClick [description] - * @param {[type]} onPathClick [description] - * @param {[type]} onNodeClick } [description] - * @param {[type]} graphOptions [description] - * @return {[type]} [description] - */ - _createGraph( - { - data = {}, - imgBasePath, - isShowTooltip, - isShowHoverPath, - onLabelClick, - onPathClick, - onNodeClick, - zoom, - fitToScreen, - getToolTipContent, - toolTipTitle - }, - graphOptions, - { refresh } - ) { - if (this.options.beforeRender) { - this.options.beforeRender(); - } - const that = this, - { svg, g, width, height } = graphOptions, - isRankdirToBottom = this.options.dagreOptions && this.options.dagreOptions.rankdir === "tb"; - - if (svg instanceof selection === false) { - throw new Error("svg is not initialized or something went wrong while creatig graph instance"); - return; - } - if (g._nodes === undefined || g._nodes.length === 0) { - svg.html('No relations to display'); - return; - } - - g.nodes().forEach(function (v) { - var node = g.node(v); - // Round the corners of the nodes - if (node) { - node.rx = node.ry = 5; - } - }); - - svg.attr("viewBox", "0 0 " + width + " " + height).attr("enable-background", "new 0 0 " + width + " " + height); - var svgGroupEl = svg.append("g"); - - // Append defs - var defsEl = svg.append("defs"); - - // Create the renderer - var render = new dagreD3.render(); - // Add our custom arrow (a hollow-point) - render.arrows().arrowPoint = function () { - return LineageUtils.arrowPointRender(...arguments, { ...graphOptions }); - }; - // Render custom img inside shape - render.shapes().img = function () { - return LineageUtils.imgShapeRender(...arguments, { - ...graphOptions, - isRankdirToBottom: isRankdirToBottom, - imgBasePath: that._getValueFromUser(imgBasePath), - defsEl - }); - }; - - var tooltip = d3Tip() - .attr("class", "d3-tip") - .offset([10, 0]) - .html((d) => { - if (getToolTipContent && typeof getToolTipContent === "function") { - return getToolTipContent(d, g.node(d)); - } else { - var value = g.node(d); - var htmlStr = ""; - if (toolTipTitle) { - htmlStr = "
        " + toolTipTitle + "
        "; - } else if (value.id !== this.guid) { - htmlStr = "
        " + (value.isLineage ? "Lineage" : "Impact") + "
        "; - } - - htmlStr += "
        " + value.toolTipLabel + "
        "; - if (value.typeName) { - htmlStr += "
        (" + value.typeName + ")
        "; - } - if (value.queryText) { - htmlStr += "
        Query: " + value.queryText + "
        "; - } - return "
        " + htmlStr + "
        "; - } - }); - - svg.call(tooltip); - - // if (platform.name !== "IE") { - // this.$(".fontLoader").hide(); - // } - - render(svgGroupEl, g); - - //change text postion - svgGroupEl - .selectAll("g.nodes g.label") - .attr("transform", () => { - if (isRankdirToBottom) { - return "translate(2,-20)"; - } - return "translate(2,-35)"; - }) - .on("mouseenter", function (d) { - event.preventDefault(); - select(this).classed("highlight", true); - }) - .on("mouseleave", function (d) { - event.preventDefault(); - select(this).classed("highlight", false); - }) - .on("click", function (d) { - event.preventDefault(); - if (onLabelClick && typeof onLabelClick === "function") { - onLabelClick({ clickedData: d }); - } - tooltip.hide(d); - }); - - svgGroupEl - .selectAll("g.nodes g.node circle") - .on("mouseenter", function (d, index, element) { - that.activeNode = true; - var matrix = this.getScreenCTM().translate(+this.getAttribute("cx"), +this.getAttribute("cy")); - that.svg.selectAll(".node").classed("active", false); - select(this).classed("active", true); - if (that._getValueFromUser(isShowTooltip)) { - var direction = LineageUtils.getToolTipDirection({ el: this }); - tooltip.direction(direction).show(d, this); - } - if (that._getValueFromUser(isShowHoverPath) === false) { - return; - } - LineageUtils.onHoverFade({ - opacity: 0.3, - mouseenter: true, - hoveredNode: d, - ...graphOptions - }); - }) - .on("mouseleave", function (d) { - that.activeNode = false; - var nodeEL = this; - setTimeout(function (argument) { - if (!(that.activeTip || that.activeNode)) { - select(nodeEL).classed("active", false); - if (that._getValueFromUser(isShowTooltip)) { - tooltip.hide(d); - } - } - }, 150); - if (that._getValueFromUser(isShowHoverPath) === false) { - return; - } - LineageUtils.onHoverFade({ - mouseenter: false, - hoveredNode: d, - ...graphOptions - }); - }) - .on("click", function (d) { - if (event.defaultPrevented) return; // ignore drag - event.preventDefault(); - tooltip.hide(d); - svg.selectAll("g.node>circle").classed("node-detail-highlight", false); - select(this).classed("node-detail-highlight", true); - if (onNodeClick && typeof onNodeClick === "function") { - onNodeClick({ clickedData: d, el: this }); - } - }); - - // Bind event on edgePath - var edgePathEl = svgGroupEl.selectAll("g.edgePath"); - edgePathEl.selectAll("path.path").on("click", function (d) { - if (onPathClick && typeof onPathClick === "function") { - var pathRelationObj = data.relations.find(function (obj) { - if (obj.fromEntityId === d.v && obj.toEntityId === d.w) { - return true; - } - }); - onPathClick({ pathRelationObj, clickedData: d }); - } - }); - - // tooltip hover handle to fix node hover conflict - // select("body").on("mouseover", ".d3-tip", function(el) { - // that.activeTip = true; - // }); - // select("body").on("mouseleave", ".d3-tip", function(el) { - // that.activeTip = false; - // svg.selectAll(".node").classed("active", false); - // //tooltip.hide(); - // }); - - // Center the graph - if (zoom !== false) { - LineageUtils.centerNode({ - ...graphOptions, - fitToScreen, - svgGroupEl, - edgePathEl - }); - } - - // if (platform.name === "IE") { - // LineageUtils.refreshGraphForIE({ - // edgeEl: this.$("svg .edgePath") - // }); - // } - - LineageUtils.dragNode({ - ...graphOptions, - edgePathEl - }); - - if (refresh !== true) { - this._addLegend(); - } - - if (this.options.afterRender) { - this.options.afterRender(); - } - } - _addLegend() { - if (this.options.legends === false) { - return; - } - var container = select(this.options.legendsEl || this.options.el) - .insert("div", ":first-child") - .classed("legends", true); - - let span = container.append("span").style("color", "#fb4200"); - span.append("i").classed("fa fa-circle-o fa-fw", true); - span.append("span").html("Current Entity"); - - span = container.append("span").style("color", "#686868"); - span.append("i").classed("fa fa-hourglass-half fa-fw", true); - span.append("span").html("In Progress"); - - span = container.append("span").style("color", "#df9b00"); - span.append("i").classed("fa fa-long-arrow-right fa-fw", true); - span.append("span").html("Lineage"); - - span = container.append("span").style("color", "#fb4200"); - span.append("i").classed("fa fa-long-arrow-right fa-fw", true); - span.append("span").html("Impact"); - } -} \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/src/styles/__varibale.scss b/dashboardv3/public/js/external_lib/atlas-lineage/src/styles/__varibale.scss deleted file mode 100644 index 1fb20d9c056..00000000000 --- a/dashboardv3/public/js/external_lib/atlas-lineage/src/styles/__varibale.scss +++ /dev/null @@ -1,35 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -//fonts -$font_0: Source Sans Pro; -$font_1: sans-serif; - -//Colors - -$white: #fff; -$dark_gray: #666; -$light_gray: #e8e8e8; -$black_80: rgba(0, 0, 0, 0.8); - -$color_mountain_mist_approx: #999; -$color_keppel_approx: #37bb9b; -$color_suva_gray_approx: #868686; -$color_havelock_blue_approx: #4a90e2; -$color_celeste_approx: #ccc; -$color_bright_turquoise_approx: #00ffd0; -$color_jungle_green_approx: #38bb9b; -$delete_link: #bb5838; \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/src/styles/graph.scss b/dashboardv3/public/js/external_lib/atlas-lineage/src/styles/graph.scss deleted file mode 100644 index ab1e82df38c..00000000000 --- a/dashboardv3/public/js/external_lib/atlas-lineage/src/styles/graph.scss +++ /dev/null @@ -1,278 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -/* graph.scss */ - -.node { - cursor: pointer; - - text { - font-size: 10px; - font-family: $font_1; - } - - //transition: opacity 0.3s linear; - - rect { - stroke: $color_mountain_mist_approx; - fill: $white; - stroke-width: 1.5px; - - &.serach-rect { - stroke: $color_keppel_approx; - fill: transparent; - stroke-width: 2.5px; - } - } - - .label { - fill: $color_suva_gray_approx; - - &.highlight { - cursor: pointer; - fill: $color_havelock_blue_approx; - text-decoration: underline; - - tspan { - font-weight: 400; - } - } - } - - circle { - -moz-transition: all 0.3s; - -webkit-transition: all 0.3s; - transition: all 0.3s; - stroke-width: 1.5px; - - &.node-detail-highlight { - stroke: $color_havelock_blue_approx; - stroke-width: 2px; - } - - &.nodeImage { - &.green:hover { - stroke: #ffb203; - } - - &.blue:hover { - stroke: #4b91e2; - } - - &.currentNode { - stroke: #fb4200; - } - - &:hover { - -moz-transform: scale(1.4); - -webkit-transform: scale(1.4); - transform: scale(1.4); - } - } - } - - &.active { - circle { - -moz-transform: scale(1.4); - -webkit-transform: scale(1.4); - transform: scale(1.4); - - &.nodeImage { - &.green { - stroke: #ffb203; - } - - &.blue { - stroke: #4b91e2; - } - } - } - } -} - -.legends { - > span { - margin-right: 8px; - font-family: $font_0; - } -} - -svg.hover { - g.node { - opacity: 0.1 !important; - } - - g.edgePath { - opacity: 0 !important; - } - - g.node.hover-active-node, - g.edgePath.hover-active-path { - opacity: 1 !important; - } -} - -.invisible { - .node circle { - transition: all 0s; - } -} - -.edgePath { - .path { - cursor: pointer; - } -} - -.link { - fill: none; - stroke: $color_celeste_approx; - stroke-width: 1.5px; -} - -.text-center { - text-align: center; -} - -.d3-tip { - line-height: 1; - font-weight: bold; - padding: 12px; - background: $black_80; - color: $white; - z-index: 999; - max-width: 300px; //Instead of the line below you could use @include border-radius($radius, $vertical-radius) - border-radius: 2px; - - .tip-inner-scroll { - overflow: auto; - max-height: 300px; - h5 { - margin: 7px 0px; - } - } - - /* Creates a small triangle extender for the tooltip */ - &:after { - box-sizing: border-box; - display: inline; - font-size: 10px; - width: 100%; - line-height: 1; - color: rgba(0, 0, 0, 0.8); - position: absolute; - } - - /* Nrthward tooltips */ - &.n:after { - content: "\25BC"; - margin: -1px 0 0 0; - top: 100%; - left: 0; - text-align: center; - } - - /* Eastward tooltips */ - &.e:after { - content: "\25C0"; - margin: -4px 0 0 0; - top: 50%; - left: -8px; - } - - /* Southward tooltips */ - &.s:after { - content: "\25B2"; - margin: 0 0 1px 0; - top: -8px; - left: 0; - text-align: center; - } - - /* Westward tooltips */ - &.w:after { - content: "\25B6"; - margin: -4px 0 0 -1px; - top: 50%; - left: 100%; - } -} - -g.type-TK > rect { - fill: $color_bright_turquoise_approx; -} - -.fullscreen-mode { - position: fixed; - height: 100% !important; - top: 0; - bottom: 0; - left: 0; - width: 100%; - right: 0; - padding: 0 !important; - z-index: 9999; - overflow: hidden !important; - - .resizeGraph { - position: fixed; - height: 100% !important; - - .ui-resizable-handle { - display: none; - } - } - - .lineage-box { - padding: 10px !important; - } - - .box-panel { - margin: 10px !important; - } -} - -@keyframes zoominoutsinglefeatured { - 0% { - transform: scale(1, 1); - } - - 50% { - transform: scale(1.2, 1.2); - } - - 100% { - transform: scale(1, 1); - } -} - -.wobble { - animation: zoominoutsinglefeatured 1s 5; -} - -.hidden-svg { - visibility: hidden; -} - -@-webkit-keyframes blink { - from { - opacity: 0.2; - } - - to { - opacity: 0.5; - } -} \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/src/styles/style.scss b/dashboardv3/public/js/external_lib/atlas-lineage/src/styles/style.scss deleted file mode 100644 index 7a7ac77e742..00000000000 --- a/dashboardv3/public/js/external_lib/atlas-lineage/src/styles/style.scss +++ /dev/null @@ -1,19 +0,0 @@ -// Licensed to the Apache Software Foundation (ASF) under one -// or more contributor license agreements. See the NOTICE file -// distributed with this work for additional information -// regarding copyright ownership. The ASF licenses this file -// to you 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. - -@import "./__varibale.scss"; -@import "./graph.scss"; - diff --git a/dashboardv3/public/js/external_lib/atlas-lineage/webpack.config.js b/dashboardv3/public/js/external_lib/atlas-lineage/webpack.config.js deleted file mode 100644 index 020603f206b..00000000000 --- a/dashboardv3/public/js/external_lib/atlas-lineage/webpack.config.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -const path = require("path"); -const MiniCssExtractPlugin = require("mini-css-extract-plugin"); - -const distPath = path.resolve(__dirname, "dist"); - -const node_env = process.env.NODE_ENV ? process.env.NODE_ENV : 'production'; - -const config = { - mode: node_env, - entry: "./src/index.js", - output: { - library: "LineageHelper", - libraryTarget: "umd", - path: distPath, - filename: "index.js" - }, - plugins: [new MiniCssExtractPlugin({ filename: "styles.css" })], - externals: { - //don't bundle the 'react' npm package with our bundle.js - //but get it from a global 'React' variable - d3: "d3", - "dagre-d3": "dagreD3", - platform: "platform", - dagre: "dagre", - graphlib: "graphlib" - }, - module: { - rules: [ - { - test: /\.m?js$/, - exclude: /(node_modules|bower_components)/, - use: { - loader: "babel-loader", - options: { - presets: ["@babel/preset-env"], - plugins: ["transform-class-properties"] - } - } - }, - { - test: /\.s[ac]ss$/i, - use: [ - MiniCssExtractPlugin.loader, - // Translates CSS into CommonJS - "css-loader", - // Compiles Sass to CSS - "sass-loader" - ] - } - ] - } -}; - -if (process.env.NODE_ENV === "development") { - config.devtool = "inline-source-map"; -} -module.exports = config; \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/backgrid-columnmanager/css/Backgrid.ColumnManager.css b/dashboardv3/public/js/external_lib/backgrid-columnmanager/css/Backgrid.ColumnManager.css deleted file mode 100644 index 89a2446dcf6..00000000000 --- a/dashboardv3/public/js/external_lib/backgrid-columnmanager/css/Backgrid.ColumnManager.css +++ /dev/null @@ -1,114 +0,0 @@ -#control { - margin: 0 0 10px 0; -} - -div.columnmanager-visibilitycontrol { - margin: 0 auto; - position: relative; - width: 50px; -} - -div.columnmanager-visibilitycontrol > button.dropdown-button { - background-image: -moz-linear-gradient(top, #ffffff, #dbdbdb); - background-image: -webkit-gradient(linear,left top,left bottom, - color-stop(0, #ffffff),color-stop(1, #dbdbdb)); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#dbdbdb'); - -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#dbdbdb')"; - border: 1px solid #fff; - -moz-box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.4); - -webkit-box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.4); - box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.4); - text-decoration: none; - text-shadow: #fff 0 1px 0; - color: #597390; - font-weight: bold; -} - -div.columnmanager-visibilitycontrol > button.dropdown-button:hover { - background-image: -moz-linear-gradient(top, #ffffff, #eeeeee); - background-image: -webkit-gradient(linear,left top,left bottom, - color-stop(0, #ffffff),color-stop(1, #eeeeee)); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#eeeeee'); - -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#ffffff', EndColorStr='#eeeeee')"; - color: #000; -} - -div.columnmanager-visibilitycontrol > button.dropdown-button:active { - background-image: -moz-linear-gradient(top, #dbdbdb, #ffffff); - background-image: -webkit-gradient(linear,left top,left bottom, - color-stop(0, #dbdbdb),color-stop(1, #ffffff)); - filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#dbdbdb', EndColorStr='#ffffff'); - -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorStr='#dbdbdb', EndColorStr='#ffffff')"; - text-shadow: 0px -1px 0 rgba(255, 255, 255, 0.5); -} - -div.columnmanager-dropdown-container { - cursor: default; - position: absolute; - z-index: 10; - top: 0; - left: 0; - background: #fff; - border: solid 1px #bbb; - -webkit-box-shadow: #999999 0 1px 3px; - -moz-box-shadow: #999999 0 1px 3px; - box-shadow: #999999 0 1px 3px; - width: 200px; - display: none !important; - min-height: 20px; - max-height: 400px; - font-size: 14px; - line-height: 1.1em; - font-weight: normal; - text-align: left; - color: #444; - text-transform: none; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; - pointer-events: none; -} - -div.columnmanager-dropdown-container.open { - display: block !important; - pointer-events: auto; -} - -.columnmanager-dropdown-container > li { - list-style-type:none; - padding: 5px 0px 0px 20px; - border-bottom: solid 1px lightgray; - cursor: pointer; -} - -.columnmanager-dropdown-container > li:hover { - background-color: #f0f0f0; -} - -.columnmanager-dropdown-container > li:last-child { - border-bottom: none; -} - -.columnmanager-dropdown-container > li > span.indicator { - width: 20px; - display: inline-block; -} -.columnmanager-dropdown-container > li.visible > span.indicator::before { - content: "✓"; - color: blue; -} - -.columnmanager-dropdown-container > li > span.column-label { - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - display: inline-block; - width: 150px; - } - -th.columnVisibility { - overflow: visible; -} diff --git a/dashboardv3/public/js/external_lib/backgrid-columnmanager/js/Backgrid.ColumnManager.js b/dashboardv3/public/js/external_lib/backgrid-columnmanager/js/Backgrid.ColumnManager.js deleted file mode 100644 index a77852ffe10..00000000000 --- a/dashboardv3/public/js/external_lib/backgrid-columnmanager/js/Backgrid.ColumnManager.js +++ /dev/null @@ -1,960 +0,0 @@ -"use strict"; - -/** - * A column manager for backgrid - * - * @module Backgrid.ColumnManager - */ - -// Dependencies -var _ = require("underscore"); -var $ = require("jquery"); -var Backbone = require("backbone"); -var Backgrid = require("backgrid"); - -/** - * Manages visibility of columns. - * - * @class Backgrid.Extension.ColumnManager ColumnManager - * @constructor - * @param {Backgrid.Columns} columns - * @param {Object} [options] - * @param {number} [options.initialColumnCount] Initial amount of columns to show. Default is null (All visible). - * @param {boolean} [options.trackSize] - * @param {boolean} [options.trackOrder] - * @param {boolean} [options.trackVisibility] - * @param {string} [options.stateChecking] can be "strict" or "loose". - * @param {boolean} [options.saveState] - * @param {string} [options.saveStateKey] Storage key. Must be unique for location. Can be left out if this plugin is only used in one place. - * @param {string} [options.saveStateLocation] Can be "localStorage" (default) or "sessionStorage" (be aware, session stored values are lost when window is closed) - * @param {boolean} [options.loadStateOnInit] - * @param {Array} [state] - */ -Backgrid.Extension.ColumnManager = function (columns, options, state) { - // Bind backbone events - _.extend(this, Backbone.Events); - - // Save options and merge with defaults - var defaults = { - initialColumnsVisible: null, - - // State options - trackSize: true, - trackOrder: true, - trackVisibility: true, - stateChecking: "strict", - saveState: false, - saveStateKey: "", - saveStateLocation: "localStorage", - loadStateOnInit: false - }; - this.options = _.extend({}, defaults, options); - this.state = []; - - // Check if columns is instance of Backgrid.Columns - if (columns instanceof Backgrid.Columns) { - // Save columns - this.columns = columns; - - // Add columnManager to columns (instance) - columns.columnManager = this; - this.addManagerToColumns(); - - // Set state if provided - var storedState = (this.options.loadStateOnInit) ? this.loadState() : false; - if (state && this.checkStateValidity(state)) { - this.setState(state, true); - } - else if (storedState) { - this.setState(storedState, true); - } - else { - // If no initial state is provided, adhere to initial column visibility settings - this.setInitialColumnVisibility(); - - // Set current state - this.setState(this.getStateFromColumns()); - } - - // Listen to column events - if (this.options.trackVisibility || this.options.trackSize || this.options.trackOrder) { - //this.stateUpdateHandler = _.bind(this.stateUpdateHandler, this); - var events = "" + - ((this.options.trackVisibility) ? "change:renderable " : "") + - ((this.options.trackSize) ? "resize " : "") + - ((this.options.trackOrder) ? "ordered" : ""); - this.columns.on(events, _.bind(this.stateUpdateHandler, this)); - } - } - else { - // Issue warning - console.error("Backgrid.ColumnManager: options.columns is not an instance of Backgrid.Columns"); - } -}; - -/** - * Loops over all columns and sets the visibility according to provided options. - * - * @method setInitialColumnVisibility - */ -Backgrid.Extension.ColumnManager.prototype.setInitialColumnVisibility = function () { - var self = this; - - // Loop columns and set renderable property according to settings - var initialColumnsVisible = self.options.initialColumnsVisible; - - if (initialColumnsVisible) { - self.columns.each(function (col, index) { - col.set("renderable", (col.get("alwaysVisible")) ? true : index < initialColumnsVisible); - }); - } -}; - -/** - * Loops over all columns and adds the columnManager instance to VisibilityHeaderCell columns. - * - * @method addManagerToColumns - */ -Backgrid.Extension.ColumnManager.prototype.addManagerToColumns = function () { - var self = this; - - self.columns.each(function (col) { - // Look for header cell - if (col.get("headerCell") === Backgrid.Extension.ColumnManager.ColumnVisibilityHeaderCell) { - col.set("headerCell", col.get("headerCell").extend({ - columnManager: self - })); - } - - if (col.get("headerCell") instanceof Backgrid.Extension.ColumnManager.ColumnVisibilityHeaderCell) { - col.get("headerCell").columnManager = self; - } - }); -}; - -/** - * Convenience function to retrieve a column either directly or by its id. - * Returns false if no column is found. - * - * @method getColumn - * @param {string|number|Backgrid.Column} col - * @return {Backgrid.Column|boolean} - */ -Backgrid.Extension.ColumnManager.prototype.getColumn = function (col) { - // If column is a string or number, try to find a column which has that ID - if (_.isNumber(col) || _.isString(col)) { - col = this.columns.get(col); - } - return (col instanceof Backgrid.Column) ? col : false; -}; - -/** - * Hides a column - * - * @method hidecolumn - * @param {string|number|Backgrid.Column} col - */ -Backgrid.Extension.ColumnManager.prototype.hideColumn = function (col) { - // If column is a valid backgrid column, set the renderable property to false - var column = this.getColumn(col); - if (column) { - column.set("renderable", false); - } -}; - -/** - * Shows a column - * - * @method showColumn - * @param {string|number|Backgrid.Column} col - */ -Backgrid.Extension.ColumnManager.prototype.showColumn = function (col) { - // If column is a valid backgrid column, set the renderable property to true - var column = this.getColumn(col); - if (column) { - column.set("renderable", true); - } -}; - -/** - * Toggles a columns' visibility - * - * @method toggleColumnVisibility - * @param {string|number|Backgrid.Column} col - */ -Backgrid.Extension.ColumnManager.prototype.toggleColumnVisibility = function (col) { - // If column is a valid backgrid column, set the renderable property to true - var column = this.getColumn(col); - if (column) { - if (column.get("renderable")) { - this.hideColumn(column); - } - else { - this.showColumn(column); - } - } -}; - -/** - * Returns the managed column collection - * - * @method getColumnCollection - * @return {Backgrid.Columns} - */ -Backgrid.Extension.ColumnManager.prototype.getColumnCollection = function () { - return this.columns; -}; - -/** - * - * @method setState - * @param {Array} state - * @param {boolean} applyState - * @return {boolean} - */ -Backgrid.Extension.ColumnManager.prototype.setState = function (state, applyState) { - var self = this; - - // Filter state - _.filter(state, function(columnState) { - if (!_.has(columnState, "name")) { - return false; - } - - var column = self.columns.findWhere({ - name: state.name - }); - - return typeof column !== "undefined"; - }); - - // Check if state is valid - if (self.checkStateValidity(state) && state !== self.state) { - // Apply and save state - self.state = state; - self.trigger("state-changed", state); - - if (applyState) { - return self.applyStateToColumns(); - } - else { - return self.saveState(); - } - } - return false; -}; - -/** - * @method getState - * @return {Array} - */ -Backgrid.Extension.ColumnManager.prototype.getState = function () { - return this.state; -}; - -/** - * - * @method checkStateValidity - * @return {boolean} - */ -Backgrid.Extension.ColumnManager.prototype.checkStateValidity = function (state) { - // Has to be array - if (!_.isArray(state) && _.isEmpty(state)) { - return false; - } - - function checkValidityColumnState() { - return _.every(state, function(column) { - var valid = true; - - // We require a name key - if (!_.has(column, "name")) { - valid = false; - } - - // If renderable is set, should be boolean - if (_.has(column, "renderable")) { - if (!_.isBoolean(column.renderable)) { - valid = false; - } - } - - // If displayOrder is set, should be a number - if (_.has(column, "displayOrder")) { - if (!_.isNumber(column.displayOrder)) { - valid = false; - } - } - - // If width is set, should be a number or a string - if (_.has(column, "width")) { - if (!_.isNumber(column.width) && !_.isString(column.width)) { - valid = false; - } - } - - return valid; - }); - } - - // Check if state is valid - if (this.options.stateChecking === "loose") { - // At least we require 'name' keys in every objec - return checkValidityColumnState(); - } - else { - // Strict check - // Requires same length and valid name keys. - if (state.length !== this.columns.length && !checkValidityColumnState()) { - return false; - } - - var columnNameKeys = this.columns.map(function (column) { - return column.get("name"); - }); - - var newStateNameKeys = _.map(state, function (column) { - return column.name; - }); - - return columnNameKeys.sort().toString() === newStateNameKeys.sort().toString(); - } -}; - - -/** - * - * @method loadState - * @return {boolean} - */ -Backgrid.Extension.ColumnManager.prototype.loadState = function () { - // Get state from storage - var state = JSON.parse(this.getStorage().getItem(this.getStorageKey())); - if (this.checkStateValidity(state)) { - return state; - } - return false; -}; - -/** - * - * @method saveState - * @param {boolean} [force] Override save settings. - * @return {boolean} - */ -Backgrid.Extension.ColumnManager.prototype.saveState = function (force) { - if (this.options.saveState || force) { - this.getStorage().setItem(this.getStorageKey(), JSON.stringify(this.state)); - this.trigger("state-saved"); - return true; - } - return false; -}; - -/** - * @method getStorage - * @return {boolean|Storage} - * @private - */ -Backgrid.Extension.ColumnManager.prototype.getStorage = function () { - // Check if storage functionality is available - if (typeof Storage !== "undefined") { - return (this.options.saveStateLocation === "sessionStorage") ? sessionStorage : localStorage; - } - else { - console.error("ColMrg: No storage support detected. State won't be saved."); - return false; - } -}; - -/** - * @method getStorageKey - * @return {string} - * @private - */ -Backgrid.Extension.ColumnManager.prototype.getStorageKey = function () { - return (this.options.saveStateKey) ? "backgrid-colmgr-" + this.options.saveStateKey : "backgrid-colmgr"; -}; - -/** - * @method stateUpdateHandler - * @return {boolean} - * @private - */ -Backgrid.Extension.ColumnManager.prototype.stateUpdateHandler = function () { - var state = this.getStateFromColumns(); - return this.setState(state); -}; - -/** - * @method getStateFromColumn - * @return {Array} - */ -Backgrid.Extension.ColumnManager.prototype.getStateFromColumns = function() { - var self = this; - - // Map state from columns - return this.columns.map(function(column) { - var columnState = { - name: column.get("name") - }; - - if (self.options.trackVisibility) { - columnState.renderable = column.get("renderable"); - } - if (self.options.trackOrder) { - columnState.displayOrder = column.get("displayOrder"); - } - if (self.options.trackSize) { - columnState.width = column.get("width"); - } - return columnState; - }); -}; - -/** - * @method applyStateToColumns - * @private - */ -Backgrid.Extension.ColumnManager.prototype.applyStateToColumns = function () { - var self = this; - - // Loop state - var ordered = false; - _.each(this.state, function(columnState) { - // Find column - var column = self.columns.findWhere({ - name: columnState.name - }); - - if (_.has(columnState, "renderable")) { - column.set("renderable", columnState.renderable); - } - if (_.has(columnState, "width")) { - var oldWidth = column.get("width"); - column.set("width", columnState.width, {silent: true}); - if (oldWidth !== columnState.width) { - column.trigger("resize", column, columnState.width, oldWidth); - } - } - - if (_.has(columnState, "displayOrder")) { - if (columnState.displayOrder !== column.get("displayOrder")) { - ordered = true; - } - column.set("displayOrder", columnState.displayOrder, {silent: true}); - } - }); - - if (ordered) { - self.columns.sort(); - self.columns.trigger("ordered"); - } -}; - -////////////////////////////////////////////// -/////////////// UI Controls ////////////////// -////////////////////////////////////////////// - -/** - * A dropdown item view - * - * @class DropDownItemView - * @extends Backbone.View - */ -var DropDownItemView = Backbone.View.extend({ - className: "columnmanager-dropdown-item", - tagName: "li", - - /** - * @method initialize - * @param {object} opts - * @param {Backgrid.Extension.ColumnManager} opts.columnManager ColumnManager instance. - * @param {Backgrid.Column} opts.column A backgrid column. - */ - initialize: function (opts) { - this.columnManager = opts.columnManager; - this.column = opts.column; - this.template = opts.template; - - _.bindAll(this, "render", "toggleVisibility"); - this.column.on("change:renderable", this.render, this); - this.el.addEventListener("click", this.toggleVisibility, true); - }, - - /** - * @method render - * @return {DropDownItemView} - */ - render: function () { - this.$el.empty(); - - this.$el.append(this.template({ - label: this.column.get("label") - })); - - if (this.column.get("renderable")) { - this.$el.addClass((this.column.get("renderable")) ? "visible" : null); - } - else { - this.$el.removeClass("visible"); - } - - return this; - }, - - /** - * Toggles visibility of column. - * - * @method toggleVisibility - * @param {object} e - */ - toggleVisibility: function (e) { - if (e) { - this.stopPropagation(e); - } - this.columnManager.toggleColumnVisibility(this.column); - }, - - /** - * Convenience function to stop event propagation. - * - * @method stopPropagation - * @param {object} e - * @private - */ - stopPropagation: function (e) { - e.stopPropagation(); - e.stopImmediatePropagation(); - e.preventDefault(); - } -}); - - -/** - * Dropdown view container. - * - * @class DropDownView - * @extends Backbone.view - */ -var DropDownView = Backbone.View.extend({ - /** - * @property className - * @type String - * @default "columnmanager-dropdown-container" - */ - className: "columnmanager-dropdown-container", - - /** - * @method initialize - * @param {object} opts - * @param {Backgrid.Extension.ColumnManager} opts.columnManager ColumnManager instance. - * @param {Backbone.View} opts.DropdownItemView View to be used for the items. - * @param {Function} opts.dropdownItemTemplate - */ - initialize: function (opts) { - this.options = opts; - this.columnManager = opts.columnManager; - this.ItemView = (opts.DropdownItemView instanceof Backbone.View) ? opts.DropdownItemView : DropDownItemView; - this.$dropdownButton = opts.$dropdownButton; - - this.on("dropdown:opened", this.open, this); - this.on("dropdown:closed", this.close, this); - this.columnManager.columns.on("add remove", this.render, this); - }, - - /** - * @method render - * @return {DropDownView} - */ - render: function () { - var view = this; - view.$el.empty(); - - // List all columns - this.columnManager.columns.each(function (col) { - if (!col.get("alwaysVisible")) { - view.$el.append(new view.ItemView({ - column: col, - columnManager: view.columnManager, - template: view.options.dropdownItemTemplate - }).render().el); - } - }); - - return this; - }, - - /** - * Opens the dropdown. - * - * @method open - */ - open: function () { - this.$el.addClass("open"); - - // Get button - var $button = this.$dropdownButton; - - // Align - var align; - if (this.options.align === "auto") { - // Determine what alignment fits - var viewPortWidth = document.body.clientWidth || document.body.clientWidth; - align = (($button.offset().left + this.$el.outerWidth()) > viewPortWidth) ? "left" : "right"; - } - else { - align = (this.options.align === "left" || this.options.align === "right") ? - (this.options.align === "right" ? "right" : "left") : "right"; - } - - var offset; - if (align === "left") { - // Align right by default - offset = $button.offset().left + $button.outerWidth() - this.$el.outerWidth(); - this.$el.css("left", offset + "px"); - } - else { - offset = $button.offset().left; - this.$el.css("left", offset + "px"); - } - - // Height position - var offsetHeight = $button.offset().top + $button.outerHeight(); - this.$el.css("top", offsetHeight + "px"); - }, - - /** - * Closes the dropdown. - * - * @method close - */ - close: function () { - this.$el.removeClass("open"); - } -}); - -/** - * UI control which manages visibility of columns. - * Inspired by: https://github.com/kjantzer/backbonejs-dropdown-view. - * - * @class Backgrid.Extension.ColumnManagerVisibilityControl - * @extends Backbone.View - */ -Backgrid.Extension.ColumnManagerVisibilityControl = Backbone.View.extend({ - /** - * @property tagName - * @type String - * @default "div" - */ - tagName: "div", - - /** - * @property className - * @type String - * @default "columnmanager-visibilitycontrol" - */ - className: "columnmanager-visibilitycontrol", - - /** - * @property defaultEvents - * @type Object - */ - defaultEvents: { - "click": "stopPropagation" - }, - - /** - * @property defaultOpts - * @type Object - */ - defaultOpts: { - width: null, - closeOnEsc: true, - closeOnClick: true, - openOnInit: false, - columnManager: null, - - // Button - buttonTemplate: _.template(""), - - // Container - DropdownView: DropDownView, - dropdownAlign: "auto", - - // Item view - DropdownItemView: DropDownItemView, - dropdownItemTemplate: _.template("<%= label %>") - }, - - /** - * @method initialize - * @param {Object} opts - * @param {Backgrid.Extension.ColumnManager} opts.columnManager ColumnManager instance - */ - initialize: function (opts) { - this.options = _.extend({}, this.defaultOpts, opts); - this.events = _.extend({}, this.defaultEvents, this.events || {}); - this.columnManager = opts.columnManager; - - // Option checking - if (!this.columnManager instanceof Backgrid.Extension.ColumnManager) { - console.error("Backgrid.ColumnManager: options.columns is not an instance of Backgrid.Columns"); - } - - // Bind scope to events - _.bindAll(this, "deferClose", "stopDeferClose", "closeOnEsc", "toggle", "render"); - - // UI events - document.body.addEventListener("click", this.deferClose, true); - this.el.addEventListener("click", this.stopDeferClose, true); - if (this.options.closeOnEsc) { - document.body.addEventListener("keyup", this.closeOnEsc, false); - } - this.el.addEventListener("click", this.toggle, false); - - // Create elements - this.setup(); - - // Listen for dropdown view events indicating to open and/or close - this.view.on("dropdown:close", this.close, this); - this.view.on("dropdown:open", this.open, this); - }, - - /** - * @method delayStart - * @private - */ - delayStart: function () { - clearTimeout(this.closeTimeout); - this.delayTimeout = setTimeout(this.open.bind(this), this.options.delay); - }, - - /** - * @method delayEnd - * @private - */ - delayEnd: function () { - clearTimeout(this.delayTimeout); - this.closeTimeout = setTimeout(this.close.bind(this), 300); - }, - - /** - * @method setup - * @private - */ - setup: function () { - // Override element width - if (this.options.width) { - this.$el.width(this.options.width + "px"); - } - - // Create button element - this.$dropdownButton = $(this.options.buttonTemplate()); - - var viewOptions = { - columnManager: this.columnManager, - DropdownItemView: this.options.DropdownItemView, - dropdownItemTemplate: this.options.dropdownItemTemplate, - align: this.options.dropdownAlign, - $dropdownButton: this.$dropdownButton - }; - - // Check if a different childView has been provided, if not, use default dropdown view - this.view = (this.options.DropdownView instanceof Backbone.View) ? - new this.options.DropdownView(viewOptions) : - new DropDownView(viewOptions); - }, - - /** - * @method setup - */ - render: function () { - this.$el.empty(); - - // Render button - this.$el.append(this.$dropdownButton); - - // Render inner view - this.view.render(); // tell the inner view to render itself - $(document.body).append(this.view.el); - return this; - }, - - /** - * Convenience function to stop event propagation - * - * @method stopPropagation - * @param {object} e - * @private - */ - stopPropagation: function (e) { - e.stopPropagation(); - e.stopImmediatePropagation(); - e.preventDefault(); - }, - - /** - * Toggle the dropdown visibility - * - * @method toggle - * @param {object} [e] - */ - toggle: function (e) { - if (this.isOpen !== true) { - this.open(e); - } - else { - this.close(e); - } - }, - - /** - * Open the dropdown - * - * @method open - * @param {object} [e] - */ - open: function (e) { - clearTimeout(this.closeTimeout); - clearTimeout(this.deferCloseTimeout); - - if (e) { - if (e.stopPropagation) { - e.stopPropagation(); - } - if (e.preventDefault) { - e.preventDefault(); - } - e.cancelBubble = true; - } - - // Don't do anything if already open - if (this.isOpen) { - return; - } - - this.isOpen = true; - this.$el.addClass("open"); - this.trigger("dropdown:opened"); - - // Notify child view - this.view.trigger("dropdown:opened"); - }, - - /** - * Close the dropdown - * - * @method close - * @param {object} [e] - */ - close: function (e) { - // Don't do anything if already closed - if (!this.isOpen) { - return; - } - - this.isOpen = false; - this.$el.removeClass("open"); - this.trigger("dropdown:closed"); - - // Notify child view - this.view.trigger("dropdown:closed"); - }, - - /** - * Close the dropdown on esc - * - * @method closeOnEsc - * @param {object} e - * @private - */ - closeOnEsc: function (e) { - if (e.which === 27) { - this.deferClose(); - } - }, - - /** - * @method deferClose - * @private - */ - deferClose: function () { - this.deferCloseTimeout = setTimeout(this.close.bind(this), 0); - }, - - /** - * @method stopDeferClose - * @private - */ - stopDeferClose: function (e) { - clearTimeout(this.deferCloseTimeout); - }, - - /** - * Clean up this control - * - * @method remove - * @chainable - */ - remove: function () { - // Remove event listeners - document.body.removeEventListener("click", this.deferClose); - this.el.removeEventListener("click", this.stopDeferClose); - if (this.options.closeOnEsc) { - document.body.removeEventListener("keyup", this.closeOnEsc); - } - this.el.removeEventListener("click", this.toggle); - - // Remove DOM element - $(this.view.el).remove(); - - // Invoke original backbone methods - return Backbone.View.prototype.remove.apply(this, arguments); - } -}); - -/** - * Backgrid HeaderCell containing ColumnManagerVisibilityControl - * - * @class Backgrid.Extension.ColumnVisibilityHeaderCell - * @extends Backgrid.HeaderCell - */ - -Backgrid.Extension.ColumnManager.ColumnVisibilityHeaderCell = Backgrid.HeaderCell.extend({ - initialize: function (options) { - Backgrid.HeaderCell.prototype.initialize.apply(this, arguments); - - // Add class - this.$el.addClass(this.column.get("name")); - }, - render: function () { - this.$el.empty(); - - // Add control - var colVisibilityControl = this.colVisibilityControl = new Backgrid.Extension.ColumnManagerVisibilityControl({ - columnManager: this.columnManager - }); - - // Add to header - this.$el.html(colVisibilityControl.render().el); - - this.delegateEvents(); - return this; - }, - - /** - * Clean up this cell. - * - * @method remove - * @chainable - */ - remove: function () { - // Remove UI control - this.colVisibilityControl.remove(); - - // Invoke super - /*eslint no-underscore-dangle:0*/ - return Backgrid.HeaderCell.__super__.remove.apply(this, arguments); - } -}); diff --git a/dashboardv3/public/js/external_lib/es5-shim.min.js b/dashboardv3/public/js/external_lib/es5-shim.min.js deleted file mode 100644 index aa8175b18eb..00000000000 --- a/dashboardv3/public/js/external_lib/es5-shim.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * https://github.com/es-shims/es5-shim - * @license es5-shim Copyright 2009-2015 by contributors, MIT License - * see https://github.com/es-shims/es5-shim/blob/v4.5.7/LICENSE - */ -(function(t,r){"use strict";if(typeof define==="function"&&define.amd){define(r)}else if(typeof exports==="object"){module.exports=r()}else{t.returnExports=r()}})(this,function(){var t=Array;var r=t.prototype;var e=Object;var n=e.prototype;var i=Function;var a=i.prototype;var o=String;var f=o.prototype;var u=Number;var l=u.prototype;var s=r.slice;var c=r.splice;var v=r.push;var h=r.unshift;var p=r.concat;var y=r.join;var d=a.call;var g=a.apply;var w=Math.max;var b=Math.min;var T=n.toString;var m=typeof Symbol==="function"&&typeof Symbol.toStringTag==="symbol";var D;var x=Function.prototype.toString,S=/^\s*class /,O=function isES6ClassFn(t){try{var r=x.call(t);var e=r.replace(/\/\/.*\n/g,"");var n=e.replace(/\/\*[.\s\S]*\*\//g,"");var i=n.replace(/\n/gm," ").replace(/ {2}/g," ");return S.test(i)}catch(a){return false}},E=function tryFunctionObject(t){try{if(O(t)){return false}x.call(t);return true}catch(r){return false}},j="[object Function]",I="[object GeneratorFunction]",D=function isCallable(t){if(!t){return false}if(typeof t!=="function"&&typeof t!=="object"){return false}if(m){return E(t)}if(O(t)){return false}var r=T.call(t);return r===j||r===I};var M;var U=RegExp.prototype.exec,F=function tryRegexExec(t){try{U.call(t);return true}catch(r){return false}},N="[object RegExp]";M=function isRegex(t){if(typeof t!=="object"){return false}return m?F(t):T.call(t)===N};var C;var k=String.prototype.valueOf,R=function tryStringObject(t){try{k.call(t);return true}catch(r){return false}},A="[object String]";C=function isString(t){if(typeof t==="string"){return true}if(typeof t!=="object"){return false}return m?R(t):T.call(t)===A};var P=e.defineProperty&&function(){try{var t={};e.defineProperty(t,"x",{enumerable:false,value:t});for(var r in t){return false}return t.x===t}catch(n){return false}}();var $=function(t){var r;if(P){r=function(t,r,n,i){if(!i&&r in t){return}e.defineProperty(t,r,{configurable:true,enumerable:false,writable:true,value:n})}}else{r=function(t,r,e,n){if(!n&&r in t){return}t[r]=e}}return function defineProperties(e,n,i){for(var a in n){if(t.call(n,a)){r(e,a,n[a],i)}}}}(n.hasOwnProperty);var J=function isPrimitive(t){var r=typeof t;return t===null||r!=="object"&&r!=="function"};var Y=u.isNaN||function(t){return t!==t};var Z={ToInteger:function ToInteger(t){var r=+t;if(Y(r)){r=0}else if(r!==0&&r!==1/0&&r!==-(1/0)){r=(r>0||-1)*Math.floor(Math.abs(r))}return r},ToPrimitive:function ToPrimitive(t){var r,e,n;if(J(t)){return t}e=t.valueOf;if(D(e)){r=e.call(t);if(J(r)){return r}}n=t.toString;if(D(n)){r=n.call(t);if(J(r)){return r}}throw new TypeError},ToObject:function(t){if(t==null){throw new TypeError("can't convert "+t+" to object")}return e(t)},ToUint32:function ToUint32(t){return t>>>0}};var z=function Empty(){};$(a,{bind:function bind(t){var r=this;if(!D(r)){throw new TypeError("Function.prototype.bind called on incompatible "+r)}var n=s.call(arguments,1);var a;var o=function(){if(this instanceof a){var i=g.call(r,this,p.call(n,s.call(arguments)));if(e(i)===i){return i}return this}else{return g.call(r,t,p.call(n,s.call(arguments)))}};var f=w(0,r.length-n.length);var u=[];for(var l=0;l1){a=arguments[1]}if(!D(t)){throw new TypeError("Array.prototype.forEach callback must be a function")}while(++n1){o=arguments[1]}if(!D(r)){throw new TypeError("Array.prototype.map callback must be a function")}for(var f=0;f1){o=arguments[1]}if(!D(t)){throw new TypeError("Array.prototype.filter callback must be a function")}for(var f=0;f1){i=arguments[1]}if(!D(t)){throw new TypeError("Array.prototype.every callback must be a function")}for(var a=0;a1){i=arguments[1]}if(!D(t)){throw new TypeError("Array.prototype.some callback must be a function")}for(var a=0;a=2){a=arguments[1]}else{do{if(i in e){a=e[i++];break}if(++i>=n){throw new TypeError("reduce of empty array with no initial value")}}while(true)}for(;i=2){i=arguments[1]}else{do{if(a in e){i=e[a--];break}if(--a<0){throw new TypeError("reduceRight of empty array with no initial value")}}while(true)}if(a<0){return i}do{if(a in e){i=t(i,e[a],a,r)}}while(a--);return i}},!at);var ot=r.indexOf&&[0,1].indexOf(1,2)!==-1;$(r,{indexOf:function indexOf(t){var r=et&&C(this)?X(this,""):Z.ToObject(this);var e=Z.ToUint32(r.length);if(e===0){return-1}var n=0;if(arguments.length>1){n=Z.ToInteger(arguments[1])}n=n>=0?n:w(0,e+n);for(;n1){n=b(n,Z.ToInteger(arguments[1]))}n=n>=0?n:e-Math.abs(n);for(;n>=0;n--){if(n in r&&t===r[n]){return n}}return-1}},ft);var ut=function(){var t=[1,2];var r=t.splice();return t.length===2&&_(r)&&r.length===0}();$(r,{splice:function splice(t,r){if(arguments.length===0){return[]}else{return c.apply(this,arguments)}}},!ut);var lt=function(){var t={};r.splice.call(t,0,0,1);return t.length===1}();$(r,{splice:function splice(t,r){if(arguments.length===0){return[]}var e=arguments;this.length=w(Z.ToInteger(this.length),0);if(arguments.length>0&&typeof r!=="number"){e=H(arguments);if(e.length<2){K(e,this.length-t)}else{e[1]=Z.ToInteger(r)}}return c.apply(this,e)}},!lt);var st=function(){var r=new t(1e5);r[8]="x";r.splice(1,1);return r.indexOf("x")===7}();var ct=function(){var t=256;var r=[];r[t]="a";r.splice(t+1,0,"b");return r[t]==="a"}();$(r,{splice:function splice(t,r){var e=Z.ToObject(this);var n=[];var i=Z.ToUint32(e.length);var a=Z.ToInteger(t);var f=a<0?w(i+a,0):b(a,i);var u=b(w(Z.ToInteger(r),0),i-f);var l=0;var s;while(ly){delete e[l-1];l-=1}}else if(v>u){l=i-u;while(l>f){s=o(l+u-1);h=o(l+v-1);if(G(e,s)){e[h]=e[s]}else{delete e[h]}l-=1}}l=f;for(var d=0;d=0&&!_(t)&&D(t.callee)};var Ct=Ft(arguments)?Ft:Nt;$(e,{keys:function keys(t){var r=D(t);var e=Ct(t);var n=t!==null&&typeof t==="object";var i=n&&C(t);if(!n&&!r&&!e){throw new TypeError("Object.keys called on a non-object")}var a=[];var f=xt&&r;if(i&&St||e){for(var u=0;u11){return t+1}return t},getMonth:function getMonth(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Bt(this);var r=Ht(this);if(t<0&&r>11){return 0}return r},getDate:function getDate(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Bt(this);var r=Ht(this);var e=Wt(this);if(t<0&&r>11){if(r===12){return e}var n=nr(0,t+1);return n-e+1}return e},getUTCFullYear:function getUTCFullYear(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Lt(this);if(t<0&&Xt(this)>11){return t+1}return t},getUTCMonth:function getUTCMonth(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Lt(this);var r=Xt(this);if(t<0&&r>11){return 0}return r},getUTCDate:function getUTCDate(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Lt(this);var r=Xt(this);var e=qt(this);if(t<0&&r>11){if(r===12){return e}var n=nr(0,t+1);return n-e+1}return e}},Pt);$(Date.prototype,{toUTCString:function toUTCString(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=Kt(this);var r=qt(this);var e=Xt(this);var n=Lt(this);var i=Qt(this);var a=Vt(this);var o=_t(this);return rr[t]+", "+(r<10?"0"+r:r)+" "+er[e]+" "+n+" "+(i<10?"0"+i:i)+":"+(a<10?"0"+a:a)+":"+(o<10?"0"+o:o)+" GMT"}},Pt||Yt);$(Date.prototype,{toDateString:function toDateString(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=this.getDay();var r=this.getDate();var e=this.getMonth();var n=this.getFullYear();return rr[t]+" "+er[e]+" "+(r<10?"0"+r:r)+" "+n}},Pt||Zt);if(Pt||zt){Date.prototype.toString=function toString(){if(!this||!(this instanceof Date)){throw new TypeError("this is not a Date object.")}var t=this.getDay();var r=this.getDate();var e=this.getMonth();var n=this.getFullYear();var i=this.getHours();var a=this.getMinutes();var o=this.getSeconds();var f=this.getTimezoneOffset();var u=Math.floor(Math.abs(f)/60);var l=Math.floor(Math.abs(f)%60);return rr[t]+" "+er[e]+" "+(r<10?"0"+r:r)+" "+n+" "+(i<10?"0"+i:i)+":"+(a<10?"0"+a:a)+":"+(o<10?"0"+o:o)+" GMT"+(f>0?"-":"+")+(u<10?"0"+u:u)+(l<10?"0"+l:l)};if(P){e.defineProperty(Date.prototype,"toString",{configurable:true,enumerable:false,writable:true})}}var ir=-621987552e5;var ar="-000001";var or=Date.prototype.toISOString&&new Date(ir).toISOString().indexOf(ar)===-1;var fr=Date.prototype.toISOString&&new Date(-1).toISOString()!=="1969-12-31T23:59:59.999Z";var ur=d.bind(Date.prototype.getTime);$(Date.prototype,{toISOString:function toISOString(){if(!isFinite(this)||!isFinite(ur(this))){throw new RangeError("Date.prototype.toISOString called on non-finite value.")}var t=Lt(this);var r=Xt(this);t+=Math.floor(r/12);r=(r%12+12)%12;var e=[r+1,qt(this),Qt(this),Vt(this),_t(this)];t=(t<0?"-":t>9999?"+":"")+L("00000"+Math.abs(t),0<=t&&t<=9999?-4:-6);for(var n=0;n=7&&l>hr){var p=Math.floor(l/hr)*hr;var y=Math.floor(p/1e3);v+=y;h-=y*1e3}c=s===1&&o(e)===e?new t(r.parse(e)):s>=7?new t(e,n,i,a,f,v,h):s>=6?new t(e,n,i,a,f,v):s>=5?new t(e,n,i,a,f):s>=4?new t(e,n,i,a):s>=3?new t(e,n,i):s>=2?new t(e,n):s>=1?new t(e instanceof t?+e:e):new t}else{c=t.apply(this,arguments)}if(!J(c)){$(c,{constructor:r},true)}return c};var e=new RegExp("^"+"(\\d{4}|[+-]\\d{6})"+"(?:-(\\d{2})"+"(?:-(\\d{2})"+"(?:"+"T(\\d{2})"+":(\\d{2})"+"(?:"+":(\\d{2})"+"(?:(\\.\\d{1,}))?"+")?"+"("+"Z|"+"(?:"+"([-+])"+"(\\d{2})"+":(\\d{2})"+")"+")?)?)?)?"+"$");var n=[0,31,59,90,120,151,181,212,243,273,304,334,365];var i=function dayFromMonth(t,r){var e=r>1?1:0;return n[r]+Math.floor((t-1969+e)/4)-Math.floor((t-1901+e)/100)+Math.floor((t-1601+e)/400)+365*(t-1970)};var a=function toUTC(r){var e=0;var n=r;if(pr&&n>hr){var i=Math.floor(n/hr)*hr;var a=Math.floor(i/1e3);e+=a;n-=a*1e3}return u(new t(1970,0,1,0,0,e,n))};for(var f in t){if(G(t,f)){r[f]=t[f]}}$(r,{now:t.now,UTC:t.UTC},true);r.prototype=t.prototype;$(r.prototype,{constructor:r},true);var l=function parse(r){var n=e.exec(r);if(n){var o=u(n[1]),f=u(n[2]||1)-1,l=u(n[3]||1)-1,s=u(n[4]||0),c=u(n[5]||0),v=u(n[6]||0),h=Math.floor(u(n[7]||0)*1e3),p=Boolean(n[4]&&!n[8]),y=n[9]==="-"?1:-1,d=u(n[10]||0),g=u(n[11]||0),w;var b=c>0||v>0||h>0;if(s<(b?24:25)&&c<60&&v<60&&h<1e3&&f>-1&&f<12&&d<24&&g<60&&l>-1&&l=0){e+=dr.data[r];dr.data[r]=Math.floor(e/t);e=e%t*dr.base}},numToString:function numToString(){var t=dr.size;var r="";while(--t>=0){if(r!==""||t===0||dr.data[t]!==0){var e=o(dr.data[t]);if(r===""){r=e}else{r+=L("0000000",0,7-e.length)+e}}}return r},pow:function pow(t,r,e){return r===0?e:r%2===1?pow(t,r-1,e*t):pow(t*t,r/2,e)},log:function log(t){var r=0;var e=t;while(e>=4096){r+=12;e/=4096}while(e>=2){r+=1;e/=2}return r}};var gr=function toFixed(t){var r,e,n,i,a,f,l,s;r=u(t);r=Y(r)?0:Math.floor(r);if(r<0||r>20){throw new RangeError("Number.toFixed called with invalid number of decimals")}e=u(this);if(Y(e)){return"NaN"}if(e<=-1e21||e>=1e21){return o(e)}n="";if(e<0){n="-";e=-e}i="0";if(e>1e-21){a=dr.log(e*dr.pow(2,69,1))-69;f=a<0?e*dr.pow(2,-a,1):e/dr.pow(2,a,1);f*=4503599627370496;a=52-a;if(a>0){dr.multiply(0,f);l=r;while(l>=7){dr.multiply(1e7,0);l-=7}dr.multiply(dr.pow(10,l,1),0);l=a-1;while(l>=23){dr.divide(1<<23);l-=23}dr.divide(1<0){s=i.length;if(s<=r){i=n+L("0.0000000000000000000",0,r-s+2)+i}else{i=n+L(i,0,s-r)+"."+L(i,s-r)}}else{i=n+i}return i};$(l,{toFixed:gr},yr);var wr=function(){try{return 1..toPrecision(undefined)==="1"}catch(t){return true}}();var br=l.toPrecision;$(l,{toPrecision:function toPrecision(t){return typeof t==="undefined"?br.call(this):br.call(this,t)}},wr);if("ab".split(/(?:ab)*/).length!==2||".".split(/(.?)(.?)/).length!==4||"tesst".split(/(s)*/)[1]==="t"||"test".split(/(?:)/,-1).length!==4||"".split(/.?/).length||".".split(/()()/).length>1){(function(){var t=typeof/()??/.exec("")[1]==="undefined";var r=Math.pow(2,32)-1;f.split=function(e,n){var i=String(this);if(typeof e==="undefined"&&n===0){return[]}if(!M(e)){return X(this,e,n)}var a=[];var o=(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.unicode?"u":"")+(e.sticky?"y":""),f=0,u,l,s,c;var h=new RegExp(e.source,o+"g");if(!t){u=new RegExp("^"+h.source+"$(?!\\s)",o)}var p=typeof n==="undefined"?r:Z.ToUint32(n);l=h.exec(i);while(l){s=l.index+l[0].length;if(s>f){K(a,L(i,f,l.index));if(!t&&l.length>1){l[0].replace(u,function(){for(var t=1;t1&&l.index=p){break}}if(h.lastIndex===l.index){h.lastIndex++}l=h.exec(i)}if(f===i.length){if(c||!h.test("")){K(a,"")}}else{K(a,L(i,f))}return a.length>p?H(a,0,p):a}})()}else if("0".split(void 0,0).length){f.split=function split(t,r){if(typeof t==="undefined"&&r===0){return[]}return X(this,t,r)}}var Tr=f.replace;var mr=function(){var t=[];"x".replace(/x(.)?/g,function(r,e){K(t,e)});return t.length===1&&typeof t[0]==="undefined"}();if(!mr){f.replace=function replace(t,r){var e=D(r);var n=M(t)&&/\)[*?]/.test(t.source);if(!e||!n){return Tr.call(this,t,r)}else{var i=function(e){var n=arguments.length;var i=t.lastIndex;t.lastIndex=0;var a=t.exec(e)||[];t.lastIndex=i;K(a,arguments[n-2],arguments[n-1]);return r.apply(this,a)};return Tr.call(this,t,i)}}}var Dr=f.substr;var xr="".substr&&"0b".substr(-1)!=="b";$(f,{substr:function substr(t,r){var e=t;if(t<0){e=w(this.length+t,0)}return Dr.call(this,e,r)}},xr);var Sr=" \n\x0B\f\r \xa0\u1680\u180e\u2000\u2001\u2002\u2003"+"\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028"+"\u2029\ufeff";var Or="\u200b";var Er="["+Sr+"]";var jr=new RegExp("^"+Er+Er+"*");var Ir=new RegExp(Er+Er+"*$");var Mr=f.trim&&(Sr.trim()||!Or.trim());$(f,{trim:function trim(){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}return o(this).replace(jr,"").replace(Ir,"")}},Mr);var Ur=d.bind(String.prototype.trim);var Fr=f.lastIndexOf&&"abc\u3042\u3044".lastIndexOf("\u3042\u3044",2)!==-1;$(f,{lastIndexOf:function lastIndexOf(t){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}var r=o(this);var e=o(t);var n=arguments.length>1?u(arguments[1]):NaN;var i=Y(n)?Infinity:Z.ToInteger(n);var a=b(w(i,0),r.length);var f=e.length;var l=a+f;while(l>0){l=w(0,l-f);var s=q(L(r,l,a+f),e);if(s!==-1){return l+s}}return-1}},Fr);var Nr=f.lastIndexOf;$(f,{lastIndexOf:function lastIndexOf(t){return Nr.apply(this,arguments)}},f.lastIndexOf.length!==1);if(parseInt(Sr+"08")!==8||parseInt(Sr+"0x16")!==22){parseInt=function(t){var r=/^[\-+]?0[xX]/;return function parseInt(e,n){var i=Ur(e);var a=u(n)||(r.test(i)?16:10);return t(i,a)}}(parseInt)}if(1/parseFloat("-0")!==-Infinity){parseFloat=function(t){return function parseFloat(r){var e=Ur(r);var n=t(e);return n===0&&L(e,0,1)==="-"?-0:n}}(parseFloat)}if(String(new RangeError("test"))!=="RangeError: test"){var Cr=function toString(){if(typeof this==="undefined"||this===null){throw new TypeError("can't convert "+this+" to object")}var t=this.name;if(typeof t==="undefined"){t="Error"}else if(typeof t!=="string"){t=o(t)}var r=this.message;if(typeof r==="undefined"){r=""}else if(typeof r!=="string"){r=o(r)}if(!t){return r}if(!r){return t}return t+": "+r};Error.prototype.toString=Cr}if(P){var kr=function(t,r){if(Q(t,r)){var e=Object.getOwnPropertyDescriptor(t,r);e.enumerable=false;Object.defineProperty(t,r,e)}};kr(Error.prototype,"message");if(Error.prototype.message!==""){Error.prototype.message=""}kr(Error.prototype,"name")}if(String(/a/gim)!=="/a/gim"){var Rr=function toString(){var t="/"+this.source+"/";if(this.global){t+="g"}if(this.ignoreCase){t+="i"}if(this.multiline){t+="m"}return t};RegExp.prototype.toString=Rr}}); -//# sourceMappingURL=es5-shim.map \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.eot b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.eot deleted file mode 100644 index abb86d98a84..00000000000 Binary files a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.eot and /dev/null differ diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.svg b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.svg deleted file mode 100644 index 3fda041c6e7..00000000000 --- a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.svg +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.ttf b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.ttf deleted file mode 100644 index 3e4e263ba99..00000000000 Binary files a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.ttf and /dev/null differ diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff deleted file mode 100644 index ce91d12bf4f..00000000000 Binary files a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff and /dev/null differ diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff2 b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff2 deleted file mode 100644 index 8935ab54a86..00000000000 Binary files a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-600.woff2 and /dev/null differ diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.eot b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.eot deleted file mode 100644 index 74c1bb40c1a..00000000000 Binary files a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.eot and /dev/null differ diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.svg b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.svg deleted file mode 100644 index 0b6b6ab6667..00000000000 --- a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.svg +++ /dev/null @@ -1,339 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.ttf b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.ttf deleted file mode 100644 index 773089dd0d3..00000000000 Binary files a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.ttf and /dev/null differ diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff deleted file mode 100644 index 832c960d698..00000000000 Binary files a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff and /dev/null differ diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff2 b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff2 deleted file mode 100644 index 8922fdc678d..00000000000 Binary files a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-700.woff2 and /dev/null differ diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.eot b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.eot deleted file mode 100644 index 8af53738f25..00000000000 Binary files a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.eot and /dev/null differ diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.svg b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.svg deleted file mode 100644 index 64f90f599b5..00000000000 --- a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.svg +++ /dev/null @@ -1,344 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.ttf b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.ttf deleted file mode 100644 index c603136aa7e..00000000000 Binary files a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.ttf and /dev/null differ diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff deleted file mode 100644 index 600602a44b6..00000000000 Binary files a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff and /dev/null differ diff --git a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff2 b/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff2 deleted file mode 100644 index 88ef1301221..00000000000 Binary files a/dashboardv3/public/js/external_lib/fonts/source-sans-pro/source-sans-pro-v10-latin-regular.woff2 and /dev/null differ diff --git a/dashboardv3/public/js/external_lib/idealTimeout/store.min.js b/dashboardv3/public/js/external_lib/idealTimeout/store.min.js deleted file mode 100644 index 7334a7e724b..00000000000 --- a/dashboardv3/public/js/external_lib/idealTimeout/store.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/* Copyright (c) 2010-2013 Marcus Westin */ -"use strict";(function(e,t){typeof define=="function"&&define.amd?define([],t):typeof exports=="object"?module.exports=t():e.store=t()})(this,function(){function o(){try{return r in t&&t[r]}catch(e){return!1}}var e={},t=window,n=t.document,r="localStorage",i="script",s;e.disabled=!1,e.version="1.3.17",e.set=function(e,t){},e.get=function(e,t){},e.has=function(t){return e.get(t)!==undefined},e.remove=function(e){},e.clear=function(){},e.transact=function(t,n,r){r==null&&(r=n,n=null),n==null&&(n={});var i=e.get(t,n);r(i),e.set(t,i)},e.getAll=function(){},e.forEach=function(){},e.serialize=function(e){return JSON.stringify(e)},e.deserialize=function(e){if(typeof e!="string")return undefined;try{return JSON.parse(e)}catch(t){return e||undefined}};if(o())s=t[r],e.set=function(t,n){return n===undefined?e.remove(t):(s.setItem(t,e.serialize(n)),n)},e.get=function(t,n){var r=e.deserialize(s.getItem(t));return r===undefined?n:r},e.remove=function(e){s.removeItem(e)},e.clear=function(){s.clear()},e.getAll=function(){var t={};return e.forEach(function(e,n){t[e]=n}),t},e.forEach=function(t){for(var n=0;ndocument.w=window'),a.close(),u=a.w.frames[0].document,s=u.createElement("div")}catch(f){s=n.createElement("div"),u=n.body}var l=function(t){return function(){var n=Array.prototype.slice.call(arguments,0);n.unshift(s),u.appendChild(s),s.addBehavior("#default#userData"),s.load(r);var i=t.apply(e,n);return u.removeChild(s),i}},c=new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]","g"),h=function(e){return e.replace(/^d/,"___$&").replace(c,"___")};e.set=l(function(t,n,i){return n=h(n),i===undefined?e.remove(n):(t.setAttribute(n,e.serialize(i)),t.save(r),i)}),e.get=l(function(t,n,r){n=h(n);var i=e.deserialize(t.getAttribute(n));return i===undefined?r:i}),e.remove=l(function(e,t){t=h(t),e.removeAttribute(t),e.save(r)}),e.clear=l(function(e){var t=e.XMLDocument.documentElement.attributes;e.load(r);while(t.length)e.removeAttribute(t[0].name);e.save(r)}),e.getAll=function(t){var n={};return e.forEach(function(e,t){n[e]=t}),n},e.forEach=l(function(t,n){var r=t.XMLDocument.documentElement.attributes;for(var i=0,s;s=r[i];++i)n(s.name,e.deserialize(t.getAttribute(s.name)))})}try{var p="__storejs__";e.set(p,p),e.get(p)!=p&&(e.disabled=!0),e.remove(p)}catch(f){e.disabled=!0}return e.enabled=!e.disabled,e}) \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/jquery-ui/jquery-ui.min.css b/dashboardv3/public/js/external_lib/jquery-ui/jquery-ui.min.css deleted file mode 100644 index 83e8d60277f..00000000000 --- a/dashboardv3/public/js/external_lib/jquery-ui/jquery-ui.min.css +++ /dev/null @@ -1,7 +0,0 @@ -/*! jQuery UI - v1.12.1 - 2019-07-04 -* http://jqueryui.com -* Includes: draggable.css, core.css, resizable.css, autocomplete.css, menu.css, theme.css -* To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=base&cornerRadiusShadow=8px&offsetLeftShadow=0px&offsetTopShadow=0px&thicknessShadow=5px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=666666&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=aaaaaa&iconColorError=cc0000&fcError=5f3f3f&borderColorError=f1a899&bgTextureError=flat&bgColorError=fddfdf&iconColorHighlight=777620&fcHighlight=777620&borderColorHighlight=dad55e&bgTextureHighlight=flat&bgColorHighlight=fffa90&iconColorActive=ffffff&fcActive=ffffff&borderColorActive=003eff&bgTextureActive=flat&bgColorActive=007fff&iconColorHover=555555&fcHover=2b2b2b&borderColorHover=cccccc&bgTextureHover=flat&bgColorHover=ededed&iconColorDefault=777777&fcDefault=454545&borderColorDefault=c5c5c5&bgTextureDefault=flat&bgColorDefault=f6f6f6&iconColorContent=444444&fcContent=333333&borderColorContent=dddddd&bgTextureContent=flat&bgColorContent=ffffff&iconColorHeader=444444&fcHeader=333333&borderColorHeader=dddddd&bgTextureHeader=flat&bgColorHeader=e9e9e9&cornerRadius=3px&fwDefault=normal&fsDefault=1em&ffDefault=Arial%2CHelvetica%2Csans-serif -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-widget{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Arial,Helvetica,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #c5c5c5}.ui-widget-content{border:1px solid #ddd;background:#fff;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #ddd;background:#e9e9e9;color:#333;font-weight:bold}.ui-widget-header a{color:#333}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #c5c5c5;background:#f6f6f6;font-weight:normal;color:#454545}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#454545;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #ccc;background:#ededed;font-weight:normal;color:#2b2b2b}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#2b2b2b;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #003eff;background:#007fff;font-weight:normal;color:#fff}.ui-icon-background,.ui-state-active .ui-icon-background{border:#003eff;background-color:#fff}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#fff;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #dad55e;background:#fffa90;color:#777620}.ui-state-checked{border:1px solid #dad55e;background:#fffa90}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#777620}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #f1a899;background:#fddfdf;color:#5f3f3f}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#5f3f3f}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#5f3f3f}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_444444_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_555555_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_ffffff_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_777620_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cc0000_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_777777_256x240.png")}.ui-icon-blank{background-position:16px 16px}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:3px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:3px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:3px}.ui-widget-overlay{background:#aaa;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:0 0 5px #666;box-shadow:0 0 5px #666} \ No newline at end of file diff --git a/dashboardv3/public/js/external_lib/jquery-ui/jquery-ui.min.js b/dashboardv3/public/js/external_lib/jquery-ui/jquery-ui.min.js deleted file mode 100644 index e0f2255ad76..00000000000 --- a/dashboardv3/public/js/external_lib/jquery-ui/jquery-ui.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/*! jQuery UI - v1.12.1 - 2019-07-04 -* http://jqueryui.com -* Includes: widget.js, position.js, data.js, disable-selection.js, keycode.js, labels.js, scroll-parent.js, unique-id.js, widgets/draggable.js, widgets/resizable.js, widgets/autocomplete.js, widgets/menu.js, widgets/mouse.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js -* Copyright jQuery Foundation and other contributors; Licensed MIT */ - -(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){t.ui=t.ui||{},t.ui.version="1.12.1";var e=0,i=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},l=e.split(".")[0];e=e.split(".")[1];var h=l+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply(null,[{}].concat(s))),t.expr[":"][h.toLowerCase()]=function(e){return!!t.data(e,h)},t[l]=t[l]||{},n=t[l][e],o=t[l][e]=function(t,e){return this._createWidget?(arguments.length&&this._createWidget(t,e),void 0):new o(t,e)},t.extend(o,n,{version:s.version,_proto:t.extend({},s),_childConstructors:[]}),a=new i,a.options=t.widget.extend({},a.options),t.each(s,function(e,s){return t.isFunction(s)?(r[e]=function(){function t(){return i.prototype[e].apply(this,arguments)}function n(t){return i.prototype[e].apply(this,t)}return function(){var e,i=this._super,o=this._superApply;return this._super=t,this._superApply=n,e=s.apply(this,arguments),this._super=i,this._superApply=o,e}}(),void 0):(r[e]=s,void 0)}),o.prototype=t.widget.extend(a,{widgetEventPrefix:n?a.widgetEventPrefix||e:e},r,{constructor:o,namespace:l,widgetName:e,widgetFullName:h}),n?(t.each(n._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete n._childConstructors):i._childConstructors.push(o),t.widget.bridge(e,o),o},t.widget.extend=function(e){for(var s,n,o=i.call(arguments,1),a=0,r=o.length;r>a;a++)for(s in o[a])n=o[a][s],o[a].hasOwnProperty(s)&&void 0!==n&&(e[s]=t.isPlainObject(n)?t.isPlainObject(e[s])?t.widget.extend({},e[s],n):t.widget.extend({},n):n);return e},t.widget.bridge=function(e,s){var n=s.prototype.widgetFullName||e;t.fn[e]=function(o){var a="string"==typeof o,r=i.call(arguments,1),l=this;return a?this.length||"instance"!==o?this.each(function(){var i,s=t.data(this,n);return"instance"===o?(l=s,!1):s?t.isFunction(s[o])&&"_"!==o.charAt(0)?(i=s[o].apply(s,r),i!==s&&void 0!==i?(l=i&&i.jquery?l.pushStack(i.get()):i,!1):void 0):t.error("no such method '"+o+"' for "+e+" widget instance"):t.error("cannot call methods on "+e+" prior to initialization; "+"attempted to call method '"+o+"'")}):l=void 0:(r.length&&(o=t.widget.extend.apply(null,[o].concat(r))),this.each(function(){var e=t.data(this,n);e?(e.option(o||{}),e._init&&e._init()):t.data(this,n,new s(o,this))})),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
        ",options:{classes:{},disabled:!1,create:null},_createWidget:function(i,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=e++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=t(),this.hoverable=t(),this.focusable=t(),this.classesElementLookup={},s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this.options=t.widget.extend({},this.options,this._getCreateOptions(),i),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){var e=this;this._destroy(),t.each(this.classesElementLookup,function(t,i){e._removeClass(i,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:t.noop,widget:function(){return this.element},option:function(e,i){var s,n,o,a=e;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof e)if(a={},s=e.split("."),e=s.shift(),s.length){for(n=a[e]=t.widget.extend({},this.options[e]),o=0;s.length-1>o;o++)n[s[o]]=n[s[o]]||{},n=n[s[o]];if(e=s.pop(),1===arguments.length)return void 0===n[e]?null:n[e];n[e]=i}else{if(1===arguments.length)return void 0===this.options[e]?null:this.options[e];a[e]=i}return this._setOptions(a),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(e){var i,s,n;for(i in e)n=this.classesElementLookup[i],e[i]!==this.options.classes[i]&&n&&n.length&&(s=t(n.get()),this._removeClass(n,i),s.addClass(this._classes({element:s,keys:i,classes:e,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(e){function i(i,o){var a,r;for(r=0;i.length>r;r++)a=n.classesElementLookup[i[r]]||t(),a=e.add?t(t.unique(a.get().concat(e.element.get()))):t(a.not(e.element).get()),n.classesElementLookup[i[r]]=a,s.push(i[r]),o&&e.classes[i[r]]&&s.push(e.classes[i[r]])}var s=[],n=this;return e=t.extend({element:this.element,classes:this.options.classes||{}},e),this._on(e.element,{remove:"_untrackClassesElement"}),e.keys&&i(e.keys.match(/\S+/g)||[],!0),e.extra&&i(e.extra.match(/\S+/g)||[]),s.join(" ")},_untrackClassesElement:function(e){var i=this;t.each(i.classesElementLookup,function(s,n){-1!==t.inArray(e.target,n)&&(i.classesElementLookup[s]=t(n.not(e.target).get()))})},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){s="boolean"==typeof s?s:i;var n="string"==typeof t||null===t,o={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s};return o.element.toggleClass(this._classes(o),s),this},_on:function(e,i,s){var n,o=this;"boolean"!=typeof e&&(s=i,i=e,e=!1),s?(i=n=t(i),this.bindings=this.bindings.add(i)):(s=i,i=this.element,n=this.widget()),t.each(s,function(s,a){function r(){return e||o.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof a?o[a]:a).apply(o,arguments):void 0}"string"!=typeof a&&(r.guid=a.guid=a.guid||r.guid||t.guid++);var l=s.match(/^([\w:-]*)\s*(.*)$/),h=l[1]+o.eventNamespace,c=l[2];c?n.on(h,c,r):i.on(h,r)})},_off:function(e,i){i=(i||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.off(i).off(i),this.bindings=t(this.bindings.not(e).get()),this.focusable=t(this.focusable.not(e).get()),this.hoverable=t(this.hoverable.not(e).get())},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){this._addClass(t(e.currentTarget),null,"ui-state-hover")},mouseleave:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){this._addClass(t(e.currentTarget),null,"ui-state-focus")},focusout:function(e){this._removeClass(t(e.currentTarget),null,"ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}}),t.widget,function(){function e(t,e,i){return[parseFloat(t[0])*(u.test(t[0])?e/100:1),parseFloat(t[1])*(u.test(t[1])?i/100:1)]}function i(e,i){return parseInt(t.css(e,i),10)||0}function s(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}var n,o=Math.max,a=Math.abs,r=/left|center|right/,l=/top|center|bottom/,h=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,d=t.fn.position;t.position={scrollbarWidth:function(){if(void 0!==n)return n;var e,i,s=t("
        "),o=s.children()[0];return t("body").append(s),e=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,e===i&&(i=s[0].clientWidth),s.remove(),n=e-i},getScrollInfo:function(e){var i=e.isWindow||e.isDocument?"":e.element.css("overflow-x"),s=e.isWindow||e.isDocument?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.widthi?"left":e>0?"right":"center",vertical:0>r?"top":s>0?"bottom":"middle"};h>p&&p>a(e+i)&&(u.horizontal="center"),c>f&&f>a(s+r)&&(u.vertical="middle"),u.important=o(a(e),a(i))>o(a(s),a(r))?"horizontal":"vertical",n.using.call(this,t,u)}),l.offset(t.extend(D,{using:r}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,l=n-r,h=r+e.collisionWidth-a-n;e.collisionWidth>a?l>0&&0>=h?(i=t.left+l+e.collisionWidth-a-n,t.left+=l-i):t.left=h>0&&0>=l?n:l>h?n+a-e.collisionWidth:n:l>0?t.left+=l:h>0?t.left-=h:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,l=n-r,h=r+e.collisionHeight-a-n;e.collisionHeight>a?l>0&&0>=h?(i=t.top+l+e.collisionHeight-a-n,t.top+=l-i):t.top=h>0&&0>=l?n:l>h?n+a-e.collisionHeight:n:l>0?t.top+=l:h>0?t.top-=h:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,o=n.offset.left+n.scrollLeft,r=n.width,l=n.isWindow?n.scrollLeft:n.offset.left,h=t.left-e.collisionPosition.marginLeft,c=h-l,u=h+e.collisionWidth-r-l,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-r-o,(0>i||a(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-l,(s>0||u>a(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,o=n.offset.top+n.scrollTop,r=n.height,l=n.isWindow?n.scrollTop:n.offset.top,h=t.top-e.collisionPosition.marginTop,c=h-l,u=h+e.collisionHeight-r-l,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,g=-2*e.offset[1];0>c?(s=t.top+p+f+g+e.collisionHeight-r-o,(0>s||a(c)>s)&&(t.top+=p+f+g)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+g-l,(i>0||u>a(i))&&(t.top+=p+f+g))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}}}(),t.ui.position,t.extend(t.expr[":"],{data:t.expr.createPseudo?t.expr.createPseudo(function(e){return function(i){return!!t.data(i,e)}}):function(e,i,s){return!!t.data(e,s[3])}}),t.fn.extend({disableSelection:function(){var t="onselectstart"in document.createElement("div")?"selectstart":"mousedown";return function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}}(),enableSelection:function(){return this.off(".ui-disableSelection")}}),t.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},t.ui.escapeSelector=function(){var t=/([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g;return function(e){return e.replace(t,"\\$1")}}(),t.fn.labels=function(){var e,i,s,n,o;return this[0].labels&&this[0].labels.length?this.pushStack(this[0].labels):(n=this.eq(0).parents("label"),s=this.attr("id"),s&&(e=this.eq(0).parents().last(),o=e.add(e.length?e.siblings():this.siblings()),i="label[for='"+t.ui.escapeSelector(s)+"']",n=n.add(o.find(i).addBack(i))),this.pushStack(n))},t.fn.scrollParent=function(e){var i=this.css("position"),s="absolute"===i,n=e?/(auto|scroll|hidden)/:/(auto|scroll)/,o=this.parents().filter(function(){var e=t(this);return s&&"static"===e.css("position")?!1:n.test(e.css("overflow")+e.css("overflow-y")+e.css("overflow-x"))}).eq(0);return"fixed"!==i&&o.length?o:t(this[0].ownerDocument||document)},t.fn.extend({uniqueId:function(){var t=0;return function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++t)})}}(),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&t(this).removeAttr("id")})}}),t.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var s=!1;t(document).on("mouseup",function(){s=!1}),t.widget("ui.mouse",{version:"1.12.1",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):void 0}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(e){if(!s){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(e),this._mouseDownEvent=e;var i=this,n=1===e.which,o="string"==typeof this.options.cancel&&e.target.nodeName?t(e.target).closest(this.options.cancel).length:!1;return n&&!o&&this._mouseCapture(e)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){i.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(e)!==!1,!this._mouseStarted)?(e.preventDefault(),!0):(!0===t.data(e.target,this.widgetName+".preventClickEvent")&&t.removeData(e.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return i._mouseMove(t)},this._mouseUpDelegate=function(t){return i._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),e.preventDefault(),s=!0,!0)):!0}},_mouseMove:function(e){if(this._mouseMoved){if(t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button)return this._mouseUp(e);if(!e.which)if(e.originalEvent.altKey||e.originalEvent.ctrlKey||e.originalEvent.metaKey||e.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(e)}return(e.which||e.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,s=!1,e.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),t.ui.plugin={add:function(e,i,s){var n,o=t.ui[e].prototype;for(n in s)o.plugins[n]=o.plugins[n]||[],o.plugins[n].push([i,s[n]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;o.length>n;n++)t.options[o[n][0]]&&o[n][1].apply(t.element,i)}},t.ui.safeActiveElement=function(t){var e;try{e=t.activeElement}catch(i){e=t.body}return e||(e=t.body),e.nodeName||(e=t.body),e},t.ui.safeBlur=function(e){e&&"body"!==e.nodeName.toLowerCase()&&t(e).trigger("blur")},t.widget("ui.draggable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this._addClass("ui-draggable"),this._setHandleClassName(),this._mouseInit()},_setOption:function(t,e){this._super(t,e),"handle"===t&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){return(this.helper||this.element).is(".ui-draggable-dragging")?(this.destroyOnClear=!0,void 0):(this._removeHandleClassName(),this._mouseDestroy(),void 0)},_mouseCapture:function(e){var i=this.options;return this.helper||i.disabled||t(e.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(e),this.handle?(this._blurActiveElement(e),this._blockFrames(i.iframeFix===!0?"iframe":i.iframeFix),!0):!1)},_blockFrames:function(e){this.iframeBlocks=this.document.find(e).map(function(){var e=t(this);return t("
        ").css("position","absolute").appendTo(e.parent()).outerWidth(e.outerWidth()).outerHeight(e.outerHeight()).offset(e.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(e){var i=t.ui.safeActiveElement(this.document[0]),s=t(e.target);s.closest(i).length||t.ui.safeBlur(i)},_mouseStart:function(e){var i=this.options;return this.helper=this._createHelper(e),this._addClass(this.helper,"ui-draggable-dragging"),this._cacheHelperProportions(),t.ui.ddmanager&&(t.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=this.helper.parents().filter(function(){return"fixed"===t(this).css("position")}).length>0,this.positionAbs=this.element.offset(),this._refreshOffsets(e),this.originalPosition=this.position=this._generatePosition(e,!1),this.originalPageX=e.pageX,this.originalPageY=e.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",e)===!1?(this._clear(),!1):(this._cacheHelperProportions(),t.ui.ddmanager&&!i.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this._mouseDrag(e,!0),t.ui.ddmanager&&t.ui.ddmanager.dragStart(this,e),!0)},_refreshOffsets:function(t){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:t.pageX-this.offset.left,top:t.pageY-this.offset.top}},_mouseDrag:function(e,i){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(e,!0),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",e,s)===!1)return this._mouseUp(new t.Event("mouseup",e)),!1;this.position=s.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),!1},_mouseStop:function(e){var i=this,s=!1;return t.ui.ddmanager&&!this.options.dropBehaviour&&(s=t.ui.ddmanager.drop(this,e)),this.dropped&&(s=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||t.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?t(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",e)!==!1&&i._clear()}):this._trigger("stop",e)!==!1&&this._clear(),!1},_mouseUp:function(e){return this._unblockFrames(),t.ui.ddmanager&&t.ui.ddmanager.dragStop(this,e),this.handleElement.is(e.target)&&this.element.trigger("focus"),t.ui.mouse.prototype._mouseUp.call(this,e)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp(new t.Event("mouseup",{target:this.element[0]})):this._clear(),this},_getHandle:function(e){return this.options.handle?!!t(e.target).closest(this.element.find(this.options.handle)).length:!0},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this._addClass(this.handleElement,"ui-draggable-handle")},_removeHandleClassName:function(){this._removeClass(this.handleElement,"ui-draggable-handle")},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper),n=s?t(i.helper.apply(this.element[0],[e])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return n.parents("body").length||n.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s&&n[0]===this.element[0]&&this._setPositionRelative(),n[0]===this.element[0]||/(fixed|absolute)/.test(n.css("position"))||n.css("position","absolute"),n},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_isRootNode:function(t){return/(html|body)/i.test(t.tagName)||t===this.document[0]},_getParentOffset:function(){var e=this.offsetParent.offset(),i=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==i&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),this._isRootNode(this.offsetParent[0])&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var t=this.element.position(),e=this._isRootNode(this.scrollParent[0]);return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+(e?0:this.scrollParent.scrollTop()),left:t.left-(parseInt(this.helper.css("left"),10)||0)+(e?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options,o=this.document[0];return this.relativeContainer=null,n.containment?"window"===n.containment?(this.containment=[t(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,t(window).scrollLeft()+t(window).width()-this.helperProportions.width-this.margins.left,t(window).scrollTop()+(t(window).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):"document"===n.containment?(this.containment=[0,0,t(o).width()-this.helperProportions.width-this.margins.left,(t(o).height()||o.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],void 0):n.containment.constructor===Array?(this.containment=n.containment,void 0):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=t(n.containment),s=i[0],s&&(e=/(scroll|auto)/.test(i.css("overflow")),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(e?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=i),void 0):(this.containment=null,void 0)},_convertPositionTo:function(t,e){e||(e=this.position);var i="absolute"===t?1:-1,s=this._isRootNode(this.scrollParent[0]);return{top:e.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:s?0:this.offset.scroll.top)*i,left:e.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:s?0:this.offset.scroll.left)*i}},_generatePosition:function(t,e){var i,s,n,o,a=this.options,r=this._isRootNode(this.scrollParent[0]),l=t.pageX,h=t.pageY;return r&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),e&&(this.containment&&(this.relativeContainer?(s=this.relativeContainer.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,t.pageX-this.offset.click.lefti[2]&&(l=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(h=i[3]+this.offset.click.top)),a.grid&&(n=a.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/a.grid[1])*a.grid[1]:this.originalPageY,h=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-a.grid[1]:n+a.grid[1]:n,o=a.grid[0]?this.originalPageX+Math.round((l-this.originalPageX)/a.grid[0])*a.grid[0]:this.originalPageX,l=i?o-this.offset.click.left>=i[0]||o-this.offset.click.left>i[2]?o:o-this.offset.click.left>=i[0]?o-a.grid[0]:o+a.grid[0]:o),"y"===a.axis&&(l=this.originalPageX),"x"===a.axis&&(h=this.originalPageY)),{top:h-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:r?0:this.offset.scroll.top),left:l-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:r?0:this.offset.scroll.left)}},_clear:function(){this._removeClass(this.helper,"ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_trigger:function(e,i,s){return s=s||this._uiHash(),t.ui.plugin.call(this,e,[i,s,this],!0),/^(drag|start|stop)/.test(e)&&(this.positionAbs=this._convertPositionTo("absolute"),s.offset=this.positionAbs),t.Widget.prototype._trigger.call(this,e,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),t.ui.plugin.add("draggable","connectToSortable",{start:function(e,i,s){var n=t.extend({},i,{item:s.element});s.sortables=[],t(s.options.connectToSortable).each(function(){var i=t(this).sortable("instance");i&&!i.options.disabled&&(s.sortables.push(i),i.refreshPositions(),i._trigger("activate",e,n))})},stop:function(e,i,s){var n=t.extend({},i,{item:s.element});s.cancelHelperRemoval=!1,t.each(s.sortables,function(){var t=this;t.isOver?(t.isOver=0,s.cancelHelperRemoval=!0,t.cancelHelperRemoval=!1,t._storedCSS={position:t.placeholder.css("position"),top:t.placeholder.css("top"),left:t.placeholder.css("left")},t._mouseStop(e),t.options.helper=t.options._helper):(t.cancelHelperRemoval=!0,t._trigger("deactivate",e,n))})},drag:function(e,i,s){t.each(s.sortables,function(){var n=!1,o=this;o.positionAbs=s.positionAbs,o.helperProportions=s.helperProportions,o.offset.click=s.offset.click,o._intersectsWith(o.containerCache)&&(n=!0,t.each(s.sortables,function(){return this.positionAbs=s.positionAbs,this.helperProportions=s.helperProportions,this.offset.click=s.offset.click,this!==o&&this._intersectsWith(this.containerCache)&&t.contains(o.element[0],this.element[0])&&(n=!1),n})),n?(o.isOver||(o.isOver=1,s._parent=i.helper.parent(),o.currentItem=i.helper.appendTo(o.element).data("ui-sortable-item",!0),o.options._helper=o.options.helper,o.options.helper=function(){return i.helper[0]},e.target=o.currentItem[0],o._mouseCapture(e,!0),o._mouseStart(e,!0,!0),o.offset.click.top=s.offset.click.top,o.offset.click.left=s.offset.click.left,o.offset.parent.left-=s.offset.parent.left-o.offset.parent.left,o.offset.parent.top-=s.offset.parent.top-o.offset.parent.top,s._trigger("toSortable",e),s.dropped=o.element,t.each(s.sortables,function(){this.refreshPositions() -}),s.currentItem=s.element,o.fromOutside=s),o.currentItem&&(o._mouseDrag(e),i.position=o.position)):o.isOver&&(o.isOver=0,o.cancelHelperRemoval=!0,o.options._revert=o.options.revert,o.options.revert=!1,o._trigger("out",e,o._uiHash(o)),o._mouseStop(e,!0),o.options.revert=o.options._revert,o.options.helper=o.options._helper,o.placeholder&&o.placeholder.remove(),i.helper.appendTo(s._parent),s._refreshOffsets(e),i.position=s._generatePosition(e,!0),s._trigger("fromSortable",e),s.dropped=!1,t.each(s.sortables,function(){this.refreshPositions()}))})}}),t.ui.plugin.add("draggable","cursor",{start:function(e,i,s){var n=t("body"),o=s.options;n.css("cursor")&&(o._cursor=n.css("cursor")),n.css("cursor",o.cursor)},stop:function(e,i,s){var n=s.options;n._cursor&&t("body").css("cursor",n._cursor)}}),t.ui.plugin.add("draggable","opacity",{start:function(e,i,s){var n=t(i.helper),o=s.options;n.css("opacity")&&(o._opacity=n.css("opacity")),n.css("opacity",o.opacity)},stop:function(e,i,s){var n=s.options;n._opacity&&t(i.helper).css("opacity",n._opacity)}}),t.ui.plugin.add("draggable","scroll",{start:function(t,e,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(e,i,s){var n=s.options,o=!1,a=s.scrollParentNotHidden[0],r=s.document[0];a!==r&&"HTML"!==a.tagName?(n.axis&&"x"===n.axis||(s.overflowOffset.top+a.offsetHeight-e.pageY=0;d--)l=s.snapElements[d].left-s.margins.left,h=l+s.snapElements[d].width,c=s.snapElements[d].top-s.margins.top,u=c+s.snapElements[d].height,l-g>_||m>h+g||c-g>b||v>u+g||!t.contains(s.snapElements[d].item.ownerDocument,s.snapElements[d].item)?(s.snapElements[d].snapping&&s.options.snap.release&&s.options.snap.release.call(s.element,e,t.extend(s._uiHash(),{snapItem:s.snapElements[d].item})),s.snapElements[d].snapping=!1):("inner"!==f.snapMode&&(n=g>=Math.abs(c-b),o=g>=Math.abs(u-v),a=g>=Math.abs(l-_),r=g>=Math.abs(h-m),n&&(i.position.top=s._convertPositionTo("relative",{top:c-s.helperProportions.height,left:0}).top),o&&(i.position.top=s._convertPositionTo("relative",{top:u,left:0}).top),a&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l-s.helperProportions.width}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h}).left)),p=n||o||a||r,"outer"!==f.snapMode&&(n=g>=Math.abs(c-v),o=g>=Math.abs(u-b),a=g>=Math.abs(l-m),r=g>=Math.abs(h-_),n&&(i.position.top=s._convertPositionTo("relative",{top:c,left:0}).top),o&&(i.position.top=s._convertPositionTo("relative",{top:u-s.helperProportions.height,left:0}).top),a&&(i.position.left=s._convertPositionTo("relative",{top:0,left:l}).left),r&&(i.position.left=s._convertPositionTo("relative",{top:0,left:h-s.helperProportions.width}).left)),!s.snapElements[d].snapping&&(n||o||a||r||p)&&s.options.snap.snap&&s.options.snap.snap.call(s.element,e,t.extend(s._uiHash(),{snapItem:s.snapElements[d].item})),s.snapElements[d].snapping=n||o||a||r||p)}}),t.ui.plugin.add("draggable","stack",{start:function(e,i,s){var n,o=s.options,a=t.makeArray(t(o.stack)).sort(function(e,i){return(parseInt(t(e).css("zIndex"),10)||0)-(parseInt(t(i).css("zIndex"),10)||0)});a.length&&(n=parseInt(t(a[0]).css("zIndex"),10)||0,t(a).each(function(e){t(this).css("zIndex",n+e)}),this.css("zIndex",n+a.length))}}),t.ui.plugin.add("draggable","zIndex",{start:function(e,i,s){var n=t(i.helper),o=s.options;n.css("zIndex")&&(o._zIndex=n.css("zIndex")),n.css("zIndex",o.zIndex)},stop:function(e,i,s){var n=s.options;n._zIndex&&t(i.helper).css("zIndex",n._zIndex)}}),t.ui.draggable,t.widget("ui.resizable",t.ui.mouse,{version:"1.12.1",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,classes:{"ui-resizable-se":"ui-icon ui-icon-gripsmall-diagonal-se"},containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(t){return parseFloat(t)||0},_isNumber:function(t){return!isNaN(parseFloat(t))},_hasScroll:function(e,i){if("hidden"===t(e).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",n=!1;return e[s]>0?!0:(e[s]=1,n=e[s]>0,e[s]=0,n)},_create:function(){var e,i=this.options,s=this;this._addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!i.aspectRatio,aspectRatio:i.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:i.helper||i.ghost||i.animate?i.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(t("
        ").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,e={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(e),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(e),this._proportionallyResize()),this._setupHandles(),i.autoHide&&t(this.element).on("mouseenter",function(){i.disabled||(s._removeClass("ui-resizable-autohide"),s._handles.show())}).on("mouseleave",function(){i.disabled||s.resizing||(s._addClass("ui-resizable-autohide"),s._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeData("resizable").removeData("ui-resizable").off(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;default:}},_setupHandles:function(){var e,i,s,n,o,a=this.options,r=this;if(this.handles=a.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=t(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),s=this.handles.split(","),this.handles={},i=0;s.length>i;i++)e=t.trim(s[i]),n="ui-resizable-"+e,o=t("
        "),this._addClass(o,"ui-resizable-handle "+n),o.css({zIndex:a.zIndex}),this.handles[e]=".ui-resizable-"+e,this.element.append(o);this._renderAxis=function(e){var i,s,n,o;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String?this.handles[i]=this.element.children(this.handles[i]).first().show():(this.handles[i].jquery||this.handles[i].nodeType)&&(this.handles[i]=t(this.handles[i]),this._on(this.handles[i],{mousedown:r._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(s=t(this.handles[i],this.element),o=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,o),this._proportionallyResize()),this._handles=this._handles.add(this.handles[i])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){r.resizing||(this.className&&(o=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),r.axis=o&&o[1]?o[1]:"se")}),a.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._handles.remove()},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(e){var i,s,n,o=this.options,a=this.element;return this.resizing=!0,this._renderProxy(),i=this._num(this.helper.css("left")),s=this._num(this.helper.css("top")),o.containment&&(i+=t(o.containment).scrollLeft()||0,s+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:i,top:s},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:a.width(),height:a.height()},this.originalSize=this._helper?{width:a.outerWidth(),height:a.outerHeight()}:{width:a.width(),height:a.height()},this.sizeDiff={width:a.outerWidth()-a.width(),height:a.outerHeight()-a.height()},this.originalPosition={left:i,top:s},this.originalMousePosition={left:e.pageX,top:e.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,n=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===n?this.axis+"-resize":n),this._addClass("ui-resizable-resizing"),this._propagate("start",e),!0},_mouseDrag:function(e){var i,s,n=this.originalMousePosition,o=this.axis,a=e.pageX-n.left||0,r=e.pageY-n.top||0,l=this._change[o];return this._updatePrevProperties(),l?(i=l.apply(this,[e,a,r]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),s=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(s)||(this._updatePrevProperties(),this._trigger("resize",e,this.ui()),this._applyChanges()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,o,a,r,l,h=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&this._hasScroll(i[0],"left")?0:c.sizeDiff.height,o=s?0:c.sizeDiff.width,a={width:c.helper.width()-o,height:c.helper.height()-n},r=parseFloat(c.element.css("left"))+(c.position.left-c.originalPosition.left)||null,l=parseFloat(c.element.css("top"))+(c.position.top-c.originalPosition.top)||null,h.animate||this.element.css(t.extend(a,{top:l,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!h.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s,n,o,a=this.options;o={minWidth:this._isNumber(a.minWidth)?a.minWidth:0,maxWidth:this._isNumber(a.maxWidth)?a.maxWidth:1/0,minHeight:this._isNumber(a.minHeight)?a.minHeight:0,maxHeight:this._isNumber(a.maxHeight)?a.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,s=o.minWidth/this.aspectRatio,i=o.maxHeight*this.aspectRatio,n=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),s>o.minHeight&&(o.minHeight=s),o.maxWidth>i&&(o.maxWidth=i),o.maxHeight>n&&(o.maxHeight=n)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),this._isNumber(t.left)&&(this.position.left=t.left),this._isNumber(t.top)&&(this.position.top=t.top),this._isNumber(t.height)&&(this.size.height=t.height),this._isNumber(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,i=this.size,s=this.axis;return this._isNumber(t.height)?t.width=t.height*this.aspectRatio:this._isNumber(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===s&&(t.left=e.left+(i.width-t.width),t.top=null),"nw"===s&&(t.top=e.top+(i.height-t.height),t.left=e.left+(i.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,i=this.axis,s=this._isNumber(t.width)&&e.maxWidth&&e.maxWidtht.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalSize.width,l=this.originalPosition.top+this.originalSize.height,h=/sw|nw|w/.test(i),c=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&h&&(t.left=r-e.minWidth),s&&h&&(t.left=r-e.maxWidth),a&&c&&(t.top=l-e.minHeight),n&&c&&(t.top=l-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];4>e;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;this._proportionallyResizeElements.length>e;e++)t=this._proportionallyResizeElements[e],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(t)),t.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("
        "),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).resizable("instance"),s=i.options,n=i._proportionallyResizeElements,o=n.length&&/textarea/i.test(n[0].nodeName),a=o&&i._hasScroll(n[0],"left")?0:i.sizeDiff.height,r=o?0:i.sizeDiff.width,l={width:i.size.width-r,height:i.size.height-a},h=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,c=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(l,c&&h?{top:c,left:h}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var e,i,s,n,o,a,r,l=t(this).resizable("instance"),h=l.options,c=l.element,u=h.containment,d=u instanceof t?u.get(0):/parent/.test(u)?c.parent().get(0):u;d&&(l.containerElement=t(d),/document/.test(u)||u===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(e=t(d),i=[],t(["Top","Right","Left","Bottom"]).each(function(t,s){i[t]=l._num(e.css("padding"+s))}),l.containerOffset=e.offset(),l.containerPosition=e.position(),l.containerSize={height:e.innerHeight()-i[3],width:e.innerWidth()-i[1]},s=l.containerOffset,n=l.containerSize.height,o=l.containerSize.width,a=l._hasScroll(d,"left")?d.scrollWidth:o,r=l._hasScroll(d)?d.scrollHeight:n,l.parentData={element:d,left:s.left,top:s.top,width:a,height:r}))},resize:function(e){var i,s,n,o,a=t(this).resizable("instance"),r=a.options,l=a.containerOffset,h=a.position,c=a._aspectRatio||e.shiftKey,u={top:0,left:0},d=a.containerElement,p=!0;d[0]!==document&&/static/.test(d.css("position"))&&(u=l),h.left<(a._helper?l.left:0)&&(a.size.width=a.size.width+(a._helper?a.position.left-l.left:a.position.left-u.left),c&&(a.size.height=a.size.width/a.aspectRatio,p=!1),a.position.left=r.helper?l.left:0),h.top<(a._helper?l.top:0)&&(a.size.height=a.size.height+(a._helper?a.position.top-l.top:a.position.top),c&&(a.size.width=a.size.height*a.aspectRatio,p=!1),a.position.top=a._helper?l.top:0),n=a.containerElement.get(0)===a.element.parent().get(0),o=/relative|absolute/.test(a.containerElement.css("position")),n&&o?(a.offset.left=a.parentData.left+a.position.left,a.offset.top=a.parentData.top+a.position.top):(a.offset.left=a.element.offset().left,a.offset.top=a.element.offset().top),i=Math.abs(a.sizeDiff.width+(a._helper?a.offset.left-u.left:a.offset.left-l.left)),s=Math.abs(a.sizeDiff.height+(a._helper?a.offset.top-u.top:a.offset.top-l.top)),i+a.size.width>=a.parentData.width&&(a.size.width=a.parentData.width-i,c&&(a.size.height=a.size.width/a.aspectRatio,p=!1)),s+a.size.height>=a.parentData.height&&(a.size.height=a.parentData.height-s,c&&(a.size.width=a.size.height*a.aspectRatio,p=!1)),p||(a.position.left=a.prevPosition.left,a.position.top=a.prevPosition.top,a.size.width=a.prevSize.width,a.size.height=a.prevSize.height)},stop:function(){var e=t(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.containerPosition,o=e.containerElement,a=t(e.helper),r=a.offset(),l=a.outerWidth()-e.sizeDiff.width,h=a.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:l,height:h}),e._helper&&!i.animate&&/static/.test(o.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:l,height:h})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).resizable("instance"),i=e.options;t(i.alsoResize).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseFloat(e.width()),height:parseFloat(e.height()),left:parseFloat(e.css("left")),top:parseFloat(e.css("top"))})})},resize:function(e,i){var s=t(this).resizable("instance"),n=s.options,o=s.originalSize,a=s.originalPosition,r={height:s.size.height-o.height||0,width:s.size.width-o.width||0,top:s.position.top-a.top||0,left:s.position.left-a.left||0};t(n.alsoResize).each(function(){var e=t(this),s=t(this).data("ui-resizable-alsoresize"),n={},o=e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(s[e]||0)+(r[e]||0);i&&i>=0&&(n[e]=i||null)}),e.css(n)})},stop:function(){t(this).removeData("ui-resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).resizable("instance"),i=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:i.height,width:i.width,margin:0,left:0,top:0}),e._addClass(e.ghost,"ui-resizable-ghost"),t.uiBackCompat!==!1&&"string"==typeof e.options.ghost&&e.ghost.addClass(this.options.ghost),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).resizable("instance");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).resizable("instance");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e,i=t(this).resizable("instance"),s=i.options,n=i.size,o=i.originalSize,a=i.originalPosition,r=i.axis,l="number"==typeof s.grid?[s.grid,s.grid]:s.grid,h=l[0]||1,c=l[1]||1,u=Math.round((n.width-o.width)/h)*h,d=Math.round((n.height-o.height)/c)*c,p=o.width+u,f=o.height+d,g=s.maxWidth&&p>s.maxWidth,m=s.maxHeight&&f>s.maxHeight,_=s.minWidth&&s.minWidth>p,v=s.minHeight&&s.minHeight>f;s.grid=l,_&&(p+=h),v&&(f+=c),g&&(p-=h),m&&(f-=c),/^(se|s|e)$/.test(r)?(i.size.width=p,i.size.height=f):/^(ne)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.top=a.top-d):/^(sw)$/.test(r)?(i.size.width=p,i.size.height=f,i.position.left=a.left-u):((0>=f-c||0>=p-h)&&(e=i._getPaddingPlusBorderDimensions(this)),f-c>0?(i.size.height=f,i.position.top=a.top-d):(f=c-e.height,i.size.height=f,i.position.top=a.top+o.height-f),p-h>0?(i.size.width=p,i.position.left=a.left-u):(p=h-e.width,i.size.width=p,i.position.left=a.left+o.width-p))}}),t.ui.resizable,t.widget("ui.menu",{version:"1.12.1",defaultElement:"