diff --git a/integration/quarkus-keycloak-authorization/.classpath b/integration/quarkus-keycloak-authorization/.classpath new file mode 100644 index 0000000..2881385 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/.classpath @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/integration/quarkus-keycloak-authorization/.mvn/wrapper/maven-wrapper.jar b/integration/quarkus-keycloak-authorization/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..bf82ff0 Binary files /dev/null and b/integration/quarkus-keycloak-authorization/.mvn/wrapper/maven-wrapper.jar differ diff --git a/integration/quarkus-keycloak-authorization/.mvn/wrapper/maven-wrapper.properties b/integration/quarkus-keycloak-authorization/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..dc3affc --- /dev/null +++ b/integration/quarkus-keycloak-authorization/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar diff --git a/integration/quarkus-keycloak-authorization/.project b/integration/quarkus-keycloak-authorization/.project new file mode 100644 index 0000000..a465598 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/.project @@ -0,0 +1,23 @@ + + + security-keycloak-authorization-quickstart + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/integration/quarkus-keycloak-authorization/.settings/org.eclipse.core.resources.prefs b/integration/quarkus-keycloak-authorization/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..4641f22 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//target/generated-sources/annotations=UTF-8 +encoding/=UTF-8 +encoding/config=UTF-8 diff --git a/integration/quarkus-keycloak-authorization/.settings/org.eclipse.jdt.core.prefs b/integration/quarkus-keycloak-authorization/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..55e549b --- /dev/null +++ b/integration/quarkus-keycloak-authorization/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.methodParameters=generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 +org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.release=disabled +org.eclipse.jdt.core.compiler.source=11 diff --git a/integration/quarkus-keycloak-authorization/.settings/org.eclipse.m2e.core.prefs b/integration/quarkus-keycloak-authorization/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/integration/quarkus-keycloak-authorization/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/integration/quarkus-keycloak-authorization/README.adoc b/integration/quarkus-keycloak-authorization/README.adoc new file mode 100644 index 0000000..3c651ba --- /dev/null +++ b/integration/quarkus-keycloak-authorization/README.adoc @@ -0,0 +1,13 @@ +# Using Keycloak Authorization Services and Policy Enforcer to Protect JAX-RS Applications + + +Start postgres DB: + +`docker compose up` + +Run the application in dev mode: + +`mvn quarkus:dev` + + + diff --git a/integration/quarkus-keycloak-authorization/config/keycloak-keystore.jks b/integration/quarkus-keycloak-authorization/config/keycloak-keystore.jks new file mode 100644 index 0000000..6961a6b Binary files /dev/null and b/integration/quarkus-keycloak-authorization/config/keycloak-keystore.jks differ diff --git a/integration/quarkus-keycloak-authorization/config/quarkus-realm.json b/integration/quarkus-keycloak-authorization/config/quarkus-realm.json new file mode 100644 index 0000000..4d78ab7 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/config/quarkus-realm.json @@ -0,0 +1,1659 @@ +{ + "id" : "11d78bf6-6d10-4484-baba-a1388379d68b", + "realm" : "quarkus", + "notBefore" : 0, + "revokeRefreshToken" : false, + "refreshTokenMaxReuse" : 0, + "accessTokenLifespan" : 300, + "accessTokenLifespanForImplicitFlow" : 900, + "ssoSessionIdleTimeout" : 1800, + "ssoSessionMaxLifespan" : 36000, + "ssoSessionIdleTimeoutRememberMe" : 0, + "ssoSessionMaxLifespanRememberMe" : 0, + "offlineSessionIdleTimeout" : 2592000, + "offlineSessionMaxLifespanEnabled" : false, + "offlineSessionMaxLifespan" : 5184000, + "accessCodeLifespan" : 60, + "accessCodeLifespanUserAction" : 300, + "accessCodeLifespanLogin" : 1800, + "actionTokenGeneratedByAdminLifespan" : 43200, + "actionTokenGeneratedByUserLifespan" : 300, + "enabled" : true, + "sslRequired" : "external", + "registrationAllowed" : false, + "registrationEmailAsUsername" : false, + "rememberMe" : false, + "verifyEmail" : false, + "loginWithEmailAllowed" : true, + "duplicateEmailsAllowed" : false, + "resetPasswordAllowed" : false, + "editUsernameAllowed" : false, + "bruteForceProtected" : false, + "permanentLockout" : false, + "maxFailureWaitSeconds" : 900, + "minimumQuickLoginWaitSeconds" : 60, + "waitIncrementSeconds" : 60, + "quickLoginCheckMilliSeconds" : 1000, + "maxDeltaTimeSeconds" : 43200, + "failureFactor" : 30, + "roles" : { + "realm" : [ { + "id" : "3fc80564-13ac-4e7b-9986-322f571e82bc", + "name" : "confidential", + "composite" : false, + "clientRole" : false, + "containerId" : "11d78bf6-6d10-4484-baba-a1388379d68b", + "attributes" : { } + }, { + "id" : "39eb64c8-66a9-4983-9c81-27ea7e2f6273", + "name" : "uma_authorization", + "description" : "${role_uma_authorization}", + "composite" : false, + "clientRole" : false, + "containerId" : "11d78bf6-6d10-4484-baba-a1388379d68b", + "attributes" : { } + }, { + "id" : "8c1abe12-62fe-4a06-ae0d-f5fb67dddbb0", + "name" : "admin", + "composite" : false, + "clientRole" : false, + "containerId" : "11d78bf6-6d10-4484-baba-a1388379d68b", + "attributes" : { } + }, { + "id" : "5afce544-6a3c-495f-b805-fd737cf5081e", + "name" : "user", + "composite" : false, + "clientRole" : false, + "containerId" : "11d78bf6-6d10-4484-baba-a1388379d68b", + "attributes" : { } + }, { + "id" : "bc431d62-a80a-425b-961a-0fb3fc59006d", + "name" : "offline_access", + "description" : "${role_offline-access}", + "composite" : false, + "clientRole" : false, + "containerId" : "11d78bf6-6d10-4484-baba-a1388379d68b", + "attributes" : { } + } ], + "client" : { + "realm-management" : [ { + "id" : "7db1f38d-d436-4725-93fd-030a3bbe628e", + "name" : "manage-identity-providers", + "description" : "${role_manage-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "1163b9bd-7319-4154-a25f-0101b2548d21", + "name" : "impersonation", + "description" : "${role_impersonation}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "73d0a556-072b-404f-bf8e-10e2544c8c27", + "name" : "view-identity-providers", + "description" : "${role_view-identity-providers}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "7e727e28-2095-4443-b2da-865e684f2308", + "name" : "view-realm", + "description" : "${role_view-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "df9e5352-f835-4467-bcaf-cb1b5f55c1ec", + "name" : "query-users", + "description" : "${role_query-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "fa77909a-32a3-41ae-9983-2b92ae03080c", + "name" : "manage-clients", + "description" : "${role_manage-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "a8780507-dc72-4433-8b95-b8e4f3c37d0e", + "name" : "manage-events", + "description" : "${role_manage-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "f7f4697a-3977-42f6-af86-9bb006cf4d04", + "name" : "realm-admin", + "description" : "${role_realm-admin}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "impersonation", "manage-identity-providers", "view-identity-providers", "view-realm", "query-users", "manage-clients", "manage-events", "manage-realm", "view-authorization", "manage-authorization", "view-users", "create-client", "query-clients", "query-groups", "manage-users", "view-clients", "view-events", "query-realms" ] + } + }, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "ca7dc1ce-a981-4efe-b3f0-a7192b6d3943", + "name" : "manage-realm", + "description" : "${role_manage-realm}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "a0ab4faa-00a9-4f52-ac9f-8e764b6a8126", + "name" : "view-authorization", + "description" : "${role_view-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "0b4ed5e0-eceb-4d81-ba05-fa67022abe59", + "name" : "manage-authorization", + "description" : "${role_manage-authorization}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "c10336be-06f3-40ef-bef5-28d8c9b8a1e2", + "name" : "create-client", + "description" : "${role_create-client}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "1a1ffadc-11d5-44ea-bac0-d94372c8ae5c", + "name" : "view-users", + "description" : "${role_view-users}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-groups", "query-users" ] + } + }, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "5ba9a1a3-9027-4531-8253-b91f6058513c", + "name" : "query-clients", + "description" : "${role_query-clients}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "b4fba807-7a7e-4e3e-bd31-45703305a9e3", + "name" : "query-groups", + "description" : "${role_query-groups}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "c9384254-0af3-434c-b4ed-7c94f59a8247", + "name" : "manage-users", + "description" : "${role_manage-users}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "9a0022f2-bd58-4418-828c-a8e7abe3346b", + "name" : "view-clients", + "description" : "${role_view-clients}", + "composite" : true, + "composites" : { + "client" : { + "realm-management" : [ "query-clients" ] + } + }, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "83df8311-4366-4d22-9425-eccc343faa3f", + "name" : "view-events", + "description" : "${role_view-events}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + }, { + "id" : "e81bf277-047f-4bdd-afd6-59e2016c5066", + "name" : "query-realms", + "description" : "${role_query-realms}", + "composite" : false, + "clientRole" : true, + "containerId" : "376bd940-e50a-4495-80fc-9c6c07312748", + "attributes" : { } + } ], + "security-admin-console" : [ ], + "admin-cli" : [ ], + "backend-service" : [ { + "id" : "df147a91-6da7-4bbc-866c-f30cf99b2637", + "name" : "uma_protection", + "composite" : false, + "clientRole" : true, + "containerId" : "0ac5df91-e044-4051-bd03-106a3a5fb9cc", + "attributes" : { } + } ], + "broker" : [ { + "id" : "d36865b0-7ade-4bcd-a7dc-1dacbd80f169", + "name" : "read-token", + "description" : "${role_read-token}", + "composite" : false, + "clientRole" : true, + "containerId" : "53d4fe53-a039-471e-886a-28eddc950e95", + "attributes" : { } + } ], + "account" : [ { + "id" : "539325a0-d9b3-4821-97ee-d42999296b62", + "name" : "view-profile", + "description" : "${role_view-profile}", + "composite" : false, + "clientRole" : true, + "containerId" : "e55e1234-38fa-432d-8d90-39f5e024688d", + "attributes" : { } + }, { + "id" : "e4af836c-c884-4a57-8b1d-fb673b0fe3a5", + "name" : "manage-account", + "description" : "${role_manage-account}", + "composite" : true, + "composites" : { + "client" : { + "account" : [ "manage-account-links" ] + } + }, + "clientRole" : true, + "containerId" : "e55e1234-38fa-432d-8d90-39f5e024688d", + "attributes" : { } + }, { + "id" : "35d1c998-bcae-4ab1-a026-4c67bff49a98", + "name" : "manage-account-links", + "description" : "${role_manage-account-links}", + "composite" : false, + "clientRole" : true, + "containerId" : "e55e1234-38fa-432d-8d90-39f5e024688d", + "attributes" : { } + } ] + } + }, + "groups" : [ ], + "defaultRoles" : [ "uma_authorization", "offline_access" ], + "requiredCredentials" : [ "password" ], + "otpPolicyType" : "totp", + "otpPolicyAlgorithm" : "HmacSHA1", + "otpPolicyInitialCounter" : 0, + "otpPolicyDigits" : 6, + "otpPolicyLookAheadWindow" : 1, + "otpPolicyPeriod" : 30, + "otpSupportedApplications" : [ "FreeOTP", "Google Authenticator" ], + "scopeMappings" : [ { + "clientScope" : "offline_access", + "roles" : [ "offline_access" ] + } ], + "clients" : [ { + "id" : "e55e1234-38fa-432d-8d90-39f5e024688d", + "clientId" : "account", + "name" : "${client_account}", + "baseUrl" : "/auth/realms/quarkus/account", + "surrogateAuthRequired" : false, + "enabled" : true, + "clientAuthenticatorType" : "client-secret", + "secret" : "0136c3ef-0dfd-4b13-a6d0-2c8b6358edec", + "defaultRoles" : [ "view-profile", "manage-account" ], + "redirectUris" : [ "/auth/realms/quarkus/account/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "role_list", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "e9cc41a2-8e35-4d5e-949e-4879880c2ddb", + "clientId" : "admin-cli", + "name" : "${client_admin-cli}", + "surrogateAuthRequired" : false, + "enabled" : true, + "clientAuthenticatorType" : "client-secret", + "secret" : "a951803a-79c7-46a6-8197-e32835286971", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : false, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "role_list", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "53d4fe53-a039-471e-886a-28eddc950e95", + "clientId" : "broker", + "name" : "${client_broker}", + "surrogateAuthRequired" : false, + "enabled" : true, + "clientAuthenticatorType" : "client-secret", + "secret" : "e1f7edd7-e15c-43b4-8736-ff8204d16836", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "role_list", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "0ac5df91-e044-4051-bd03-106a3a5fb9cc", + "clientId" : "backend-service", + "surrogateAuthRequired" : false, + "enabled" : true, + "clientAuthenticatorType" : "client-secret", + "secret" : "secret", + "redirectUris" : ["*"], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : true, + "serviceAccountsEnabled" : true, + "authorizationServicesEnabled" : true, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : true, + "nodeReRegistrationTimeout" : -1, + "protocolMappers" : [ { + "id" : "3eac903f-c16b-4a78-a7e8-eb8f4d402b71", + "name" : "Client ID", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "clientId", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "clientId", + "jsonType.label" : "String" + } + }, { + "id" : "8422cefe-7f42-4f3b-abad-5f06f7d4b748", + "name" : "Client IP Address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "clientAddress", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "clientAddress", + "jsonType.label" : "String" + } + }, { + "id" : "988e47d6-2055-45eb-82d6-0b8b25c629fc", + "name" : "Client Host", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usersessionmodel-note-mapper", + "consentRequired" : false, + "config" : { + "user.session.note" : "clientHost", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "clientHost", + "jsonType.label" : "String" + } + } ], + "defaultClientScopes" : [ "web-origins", "role_list", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ], + "authorizationSettings" : { + "allowRemoteResourceManagement": true, + "policyEnforcementMode": "ENFORCING", + "resources": [ + { + "name": "User Resource", + "ownerManagedAccess": false, + "attributes": {}, + "_id": "df1b74a9-3f10-499d-a581-368de48e512b", + "uris": [ + "/product/v1/users/*" + ] + }, + { + "name": "Administration Resource", + "ownerManagedAccess": false, + "attributes": {}, + "_id": "7124e2f1-e6dc-44b4-87ab-24b010090b97", + "uris": [ + "/product/v1/admin/*" + ] + } + ], + "policies": [ + { + "id": "b8710fa6-160e-4de0-adf3-398c7007a0af", + "name": "Any User Policy", + "description": "Any user granted with the user role can access something", + "type": "role", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "roles": "[{\"id\":\"user\",\"required\":false}]" + } + }, + { + "id": "fcef30b2-68b2-4b78-9f3d-9162c6cdf5cb", + "name": "Only Administrators", + "description": "Only administrators can access", + "type": "role", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "roles": "[{\"id\":\"admin\",\"required\":false}]" + } + }, + { + "id": "3479dd56-02e9-4222-94fe-6a13cd065195", + "name": "User Resource Permission", + "type": "resource", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"User Resource\"]", + "applyPolicies": "[\"Any User Policy\"]" + } + }, + { + "id": "60188298-d55b-4066-b231-6a7c56ff7cc5", + "name": "Administration Resource Permission", + "type": "resource", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"Administration Resource\"]", + "applyPolicies": "[\"Only Administrators\"]" + } + } + ], + "scopes": [], + "decisionStrategy": "UNANIMOUS" + } + }, { + "id" : "376bd940-e50a-4495-80fc-9c6c07312748", + "clientId" : "realm-management", + "name" : "${client_realm-management}", + "surrogateAuthRequired" : false, + "enabled" : true, + "clientAuthenticatorType" : "client-secret", + "secret" : "c41b709a-a012-4c69-89d7-4f926dba0619", + "redirectUris" : [ ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : true, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : false, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "defaultClientScopes" : [ "web-origins", "role_list", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + }, { + "id" : "a8732cac-ae0f-44ec-b7f3-bd2c41eff13c", + "clientId" : "security-admin-console", + "name" : "${client_security-admin-console}", + "baseUrl" : "/auth/admin/quarkus/console/index.html", + "surrogateAuthRequired" : false, + "enabled" : true, + "clientAuthenticatorType" : "client-secret", + "secret" : "e571b211-2550-475d-b87f-116ff54091ee", + "redirectUris" : [ "/auth/admin/quarkus/console/*" ], + "webOrigins" : [ ], + "notBefore" : 0, + "bearerOnly" : false, + "consentRequired" : false, + "standardFlowEnabled" : true, + "implicitFlowEnabled" : false, + "directAccessGrantsEnabled" : false, + "serviceAccountsEnabled" : false, + "publicClient" : true, + "frontchannelLogout" : false, + "protocol" : "openid-connect", + "attributes" : { }, + "authenticationFlowBindingOverrides" : { }, + "fullScopeAllowed" : false, + "nodeReRegistrationTimeout" : 0, + "protocolMappers" : [ { + "id" : "280528ca-5e96-4bb9-9fc0-20311caac32d", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + } ], + "defaultClientScopes" : [ "web-origins", "role_list", "profile", "roles", "email" ], + "optionalClientScopes" : [ "address", "phone", "offline_access", "microprofile-jwt" ] + } ], + "clientScopes" : [ { + "id" : "520cc3ef-2c6b-4d84-bcde-8c063241f4bd", + "name" : "address", + "description" : "OpenID Connect built-in scope: address", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${addressScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "c1d3bd07-0a5f-4f4f-b381-c58a7b723029", + "name" : "address", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-address-mapper", + "consentRequired" : false, + "config" : { + "user.attribute.formatted" : "formatted", + "user.attribute.country" : "country", + "user.attribute.postal_code" : "postal_code", + "userinfo.token.claim" : "true", + "user.attribute.street" : "street", + "id.token.claim" : "true", + "user.attribute.region" : "region", + "access.token.claim" : "true", + "user.attribute.locality" : "locality" + } + } ] + }, { + "id" : "19920c96-a383-4f35-8ee9-27833263cf03", + "name" : "email", + "description" : "OpenID Connect built-in scope: email", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${emailScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "36a0adf0-6c25-419f-98d7-cdeada8661aa", + "name" : "email", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "email", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email", + "jsonType.label" : "String" + } + }, { + "id" : "b0c39901-5e5d-4436-b685-908bb90ea1d9", + "name" : "email verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "emailVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "email_verified", + "jsonType.label" : "boolean" + } + } ] + }, { + "id" : "55b3ee1c-cbf9-4526-93d7-aa56a9c5f1cb", + "name" : "microprofile-jwt", + "description" : "Microprofile - JWT built-in scope", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "false" + }, + "protocolMappers" : [ { + "id" : "59128144-a21a-4744-bb55-e66ff0503b18", + "name" : "upn", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "upn", + "jsonType.label" : "String" + } + }, { + "id" : "69351a63-7d6e-45d0-be47-088c83b20fdb", + "name" : "groups", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "multivalued" : "true", + "user.attribute" : "foo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "groups", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "3f190f54-8e3a-4c82-a799-bd12ddc475b2", + "name" : "offline_access", + "description" : "OpenID Connect built-in scope: offline_access", + "protocol" : "openid-connect", + "attributes" : { + "consent.screen.text" : "${offlineAccessScopeConsentText}", + "display.on.consent.screen" : "true" + } + }, { + "id" : "defa3480-5368-4f34-8075-49fb982b71b3", + "name" : "phone", + "description" : "OpenID Connect built-in scope: phone", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${phoneScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "069ae414-9e98-4612-a3d6-e8b5a1fa841d", + "name" : "phone number verified", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumberVerified", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number_verified", + "jsonType.label" : "boolean" + } + }, { + "id" : "cea58e24-d0e0-4cc6-9e34-7b3bf7d6d85b", + "name" : "phone number", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "phoneNumber", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "phone_number", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "b7321e2e-dd8e-41cf-a527-c765155c3f78", + "name" : "profile", + "description" : "OpenID Connect built-in scope: profile", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "true", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${profileScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "1d4d3df5-7af5-488e-8477-0ad7cb74d50a", + "name" : "nickname", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "nickname", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "nickname", + "jsonType.label" : "String" + } + }, { + "id" : "1a5e26d6-211e-4f8a-b696-0ea9577db25a", + "name" : "zoneinfo", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "zoneinfo", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "zoneinfo", + "jsonType.label" : "String" + } + }, { + "id" : "18971685-6dd7-420f-9c09-879c4f2d54d8", + "name" : "updated at", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "updatedAt", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "updated_at", + "jsonType.label" : "String" + } + }, { + "id" : "b970d96b-0156-4db0-9beb-9c84c173e619", + "name" : "birthdate", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "birthdate", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "birthdate", + "jsonType.label" : "String" + } + }, { + "id" : "50287033-df21-45c6-aa46-c3060e6f9855", + "name" : "given name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "firstName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "given_name", + "jsonType.label" : "String" + } + }, { + "id" : "3dc6b97e-7063-4077-98d1-0cacf9029c7b", + "name" : "full name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-full-name-mapper", + "consentRequired" : false, + "config" : { + "id.token.claim" : "true", + "access.token.claim" : "true", + "userinfo.token.claim" : "true" + } + }, { + "id" : "3fb9391b-376c-42ef-b012-4df461c617cc", + "name" : "middle name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "middleName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "middle_name", + "jsonType.label" : "String" + } + }, { + "id" : "83f7fc4a-5386-4f86-a103-6585e138b61d", + "name" : "username", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "username", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "preferred_username", + "jsonType.label" : "String" + } + }, { + "id" : "8ef177b3-f485-44b1-afee-1901393b00c7", + "name" : "family name", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-property-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "lastName", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "family_name", + "jsonType.label" : "String" + } + }, { + "id" : "e994cbc7-2a1a-4465-b7b7-12b35b4fe49e", + "name" : "gender", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "gender", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "gender", + "jsonType.label" : "String" + } + }, { + "id" : "abaa4c9e-1fa2-4b45-a1bb-b3d650de9aca", + "name" : "picture", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "picture", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "picture", + "jsonType.label" : "String" + } + }, { + "id" : "bf21b514-81fd-4bbe-9236-bab5fcf54561", + "name" : "locale", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "locale", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "locale", + "jsonType.label" : "String" + } + }, { + "id" : "254f8de4-08e7-4d3d-a87f-4b238f0f922b", + "name" : "profile", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "profile", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "profile", + "jsonType.label" : "String" + } + }, { + "id" : "7934bf2a-cfc3-4b2d-a5cb-287f3ed2a977", + "name" : "website", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-attribute-mapper", + "consentRequired" : false, + "config" : { + "userinfo.token.claim" : "true", + "user.attribute" : "website", + "id.token.claim" : "true", + "access.token.claim" : "true", + "claim.name" : "website", + "jsonType.label" : "String" + } + } ] + }, { + "id" : "f3dc793d-6011-4861-b538-399dde5434c0", + "name" : "role_list", + "description" : "SAML role list", + "protocol" : "saml", + "attributes" : { + "consent.screen.text" : "${samlRoleListScopeConsentText}", + "display.on.consent.screen" : "true" + }, + "protocolMappers" : [ { + "id" : "22eeabf8-a3c3-4026-a351-367f8ace7927", + "name" : "role list", + "protocol" : "saml", + "protocolMapper" : "saml-role-list-mapper", + "consentRequired" : false, + "config" : { + "single" : "false", + "attribute.nameformat" : "Basic", + "attribute.name" : "Role" + } + } ] + }, { + "id" : "f72c1acd-c367-41b1-8646-b6bd5fff3e3f", + "name" : "roles", + "description" : "OpenID Connect scope for add user roles to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "true", + "consent.screen.text" : "${rolesScopeConsentText}" + }, + "protocolMappers" : [ { + "id" : "cd8e589e-5fa7-4dae-bf6e-e8f6a3fd3cff", + "name" : "realm roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-realm-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "realm_access.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + }, { + "id" : "708b19d1-0709-4278-b5a1-bcbeec11f51a", + "name" : "audience resolve", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-audience-resolve-mapper", + "consentRequired" : false, + "config" : { } + }, { + "id" : "25e97210-30c7-4f35-be11-407f1fa674cb", + "name" : "client roles", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-usermodel-client-role-mapper", + "consentRequired" : false, + "config" : { + "user.attribute" : "foo", + "access.token.claim" : "true", + "claim.name" : "resource_access.${client_id}.roles", + "jsonType.label" : "String", + "multivalued" : "true" + } + } ] + }, { + "id" : "52618957-a4e8-4c6f-a902-217f2c41a2fd", + "name" : "web-origins", + "description" : "OpenID Connect scope for add allowed web origins to the access token", + "protocol" : "openid-connect", + "attributes" : { + "include.in.token.scope" : "false", + "display.on.consent.screen" : "false", + "consent.screen.text" : "" + }, + "protocolMappers" : [ { + "id" : "a66ddadf-312f-491f-993c-fa58685815c6", + "name" : "allowed web origins", + "protocol" : "openid-connect", + "protocolMapper" : "oidc-allowed-origins-mapper", + "consentRequired" : false, + "config" : { } + } ] + } ], + "defaultDefaultClientScopes" : [ "role_list", "profile", "email", "roles", "web-origins" ], + "defaultOptionalClientScopes" : [ "offline_access", "address", "phone", "microprofile-jwt" ], + "browserSecurityHeaders" : { + "contentSecurityPolicyReportOnly" : "", + "xContentTypeOptions" : "nosniff", + "xRobotsTag" : "none", + "xFrameOptions" : "SAMEORIGIN", + "xXSSProtection" : "1; mode=block", + "contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "strictTransportSecurity" : "max-age=31536000; includeSubDomains" + }, + "smtpServer" : { }, + "eventsEnabled" : false, + "eventsListeners" : [ "jboss-logging" ], + "enabledEventTypes" : [ ], + "adminEventsEnabled" : false, + "adminEventsDetailsEnabled" : false, + "components" : { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy" : [ { + "id" : "a7679218-373d-48ca-88f8-429985faeae3", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "saml-user-attribute-mapper", "saml-user-property-mapper", "oidc-address-mapper", "saml-role-list-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-attribute-mapper", "oidc-usermodel-property-mapper" ] + } + }, { + "id" : "2ebf6f9f-4bfc-44b9-ad7c-282f2274d35b", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "552093c3-0a0a-4234-ad7c-ae660f0f0db1", + "name" : "Allowed Client Scopes", + "providerId" : "allowed-client-templates", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "allow-default-scopes" : [ "true" ] + } + }, { + "id" : "8f27cf74-cee7-4a73-851f-982ee45157ca", + "name" : "Trusted Hosts", + "providerId" : "trusted-hosts", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "host-sending-registration-request-must-match" : [ "true" ], + "client-uris-must-match" : [ "true" ] + } + }, { + "id" : "ff570525-6c96-4500-9d73-c02e708b39de", + "name" : "Full Scope Disabled", + "providerId" : "scope", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "b52284eb-123a-4718-aac9-857530a24a9b", + "name" : "Max Clients Limit", + "providerId" : "max-clients", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { + "max-clients" : [ "200" ] + } + }, { + "id" : "2b8c0a6d-d5c0-4ea2-8a9c-4843d3e04ec6", + "name" : "Consent Required", + "providerId" : "consent-required", + "subType" : "anonymous", + "subComponents" : { }, + "config" : { } + }, { + "id" : "bf59de5a-2c93-43cc-a9aa-03be0129fe53", + "name" : "Allowed Protocol Mapper Types", + "providerId" : "allowed-protocol-mappers", + "subType" : "authenticated", + "subComponents" : { }, + "config" : { + "allowed-protocol-mapper-types" : [ "saml-user-attribute-mapper", "oidc-full-name-mapper", "saml-role-list-mapper", "saml-user-property-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper", "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper" ] + } + } ], + "org.keycloak.keys.KeyProvider" : [ { + "id" : "b3efd9cc-28b6-4404-82af-8a48a966b8ff", + "name" : "rsa-generated", + "providerId" : "rsa-generated", + "subComponents" : { }, + "config" : { + "privateKey" : [ "MIIEowIBAAKCAQEAn5T13suF8mlS+pJXp0U1bto41nW55wpcs+Rps8ZVCRyJKWqzwSCYnI7lm0rB2wBpAAO4OPoj1zlmVoFmBPsDU9Xf7rjsJb5LIzIQDCZY44aSDZt6RR+gakPiQvlzHyW/RozYpngDJF7TsTD7rdRF1xQ4RprfBF8fwK/xsU7pxbeom5xDHZhz3fiw8s+7UdbmnazDHfAjU58aUrLGgVRfUsuoHjtsptYlOIXEifaeMetXZE+HhqLYRHQPDap5fbBJl773Trosn7N9nmzN4x1xxGj9So21WC5UboQs9sAIVgizc4omjZ5Y4RN9HLH7G4YwJctNntzmnJhDui9zAO+zSQIDAQABAoIBADi+F7rTtVoft0Cfnok8o6Y58/HVxHdxiMryUd95iy0FN4RBi48FTx6D9QKFz25Ws/8sU2n3D51srIXf1u24b1N0/f39RQKaqk7mcyxOylaEuBQcj5pah4ihgKd92UBfBKdKV5LBo6RgD3e2yhbiHr8+UlBQqzH7vOef6Bm6zIbfmi3N88swAJhP0YizRZFklsbmLsK6nkwyro00CHJvPVKSBbM+ad+/zIBsLw56MvNngB5TuFguUgoljd6M1T2z4utmZGlTUqrfE1onAVLJZoGnRohyIr7dJEg6YxWR70PxsgmkDKyeRvet9P1trO0n+OSprusfrC3cHJStabap1V0CgYEA1A/CtsqTnjdYYsB19eumZgdpzUgNc/YEAzZ/OWb8yTLoB2ncci+63A1rXHUXAqJFY7vtjn5mxv7SuASNbUrzq+6KfZvC1x9XEtnczqT/ypunNfxmIZuj8Nuu6vtURguZ8kPPwdkI8toTizRFeRE5ZDBvoQryiEVYugfHaHT5vzsCgYEAwKWODwquI0Lv9BuwdNVrBXQpkKh3ZfYOA7i9xvhxlM7xUu8OMCwwCPn3r7vrW5APjTqX4h330mJ44SLEs+7gbCUs4BbJBLA6g0ChlHa9PTkxp6tk2nDF/B34fxiZSRkE85L+d+at0Dc3hnlzLCJCzJawGpoPniPU9e4w0p4dN0sCgYAsGnMGjS8SUrRhJWHjGXVr9tK8TOXvXhULjgP7rj2Yoqu7Dvs4DFEyft/7RKbad2EzEtyfLA64CDtO5jN7rYDsGxpWcVSeZPg5BXJ0z8AbJTArfCjJiJMZ/rZsTIUEZFlKF2xYBolj6JLz+pUQTtK+0YwF1D8ItFN1rTR9twZSDQKBgQC6sPXNX+VH6LuPTjIf1x8CxwLs3EXxOpV0R9kp9GRl+HJnk6GlT30xhcThufQo5KAdllXQXIhoiuNoEoCbevhj9Vbax1oBQCNERSMRNEzKAx46xd9TzYwgeo7x5E3QR/3DaoVOfu+cY5ZcrF/PulgP2kxJS1mtQD5GIpGP2oinpwKBgGqiqTFPqRcelx76vBvTU+Jp1zM62T4AotbMrSQR/oUvqHe5Ytj/SbZx+wbbHAiyGgV700Mosyviik83YEAbR3kdOPjgYvAJJW2Y3jEMdQ7MwriXz8XLh5BGmYfVjkSOJXed9ua9WlYLKOJeXXv191BbDvrx5NXuJyVVU4vJx3YZ" ], + "certificate" : [ "MIICnTCCAYUCBgFp4EYIrjANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDDAdwcm90ZWFuMB4XDTE5MDQwMjIyNTYxOVoXDTI5MDQwMjIyNTc1OVowEjEQMA4GA1UEAwwHcHJvdGVhbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJ+U9d7LhfJpUvqSV6dFNW7aONZ1uecKXLPkabPGVQkciSlqs8EgmJyO5ZtKwdsAaQADuDj6I9c5ZlaBZgT7A1PV3+647CW+SyMyEAwmWOOGkg2bekUfoGpD4kL5cx8lv0aM2KZ4AyRe07Ew+63URdcUOEaa3wRfH8Cv8bFO6cW3qJucQx2Yc934sPLPu1HW5p2swx3wI1OfGlKyxoFUX1LLqB47bKbWJTiFxIn2njHrV2RPh4ai2ER0Dw2qeX2wSZe+9066LJ+zfZ5szeMdccRo/UqNtVguVG6ELPbACFYIs3OKJo2eWOETfRyx+xuGMCXLTZ7c5pyYQ7ovcwDvs0kCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAVtmRKDb4OK5iSA46tagMBkp6L7WuPpCWuHGWwobEP+BecYsShW7zP3s12oA8SNSwbhvu0CRqgzxhuypgf3hKQFVU153Erv4hzkj+8S0s5LR/ZE7tDNY2lzJ3yQKXy3Md7EkuzzvOZ50MTrcSKAanWq/ZW1OTnrtGymj5zGJnTg7mMnJzEIGePxkvPu/QdchiPBLqxfZYm1jsFGY25djOC3N/KmVcRVmPRGuu6D8tBFHlKoPfZYPdbMvsvs24aupHKRcZ+ofTCpK+2Qo8c0pSSqeEYHGmuGqC6lC6ozxtxSABPO9Q1R1tZBU7Kg5HvXUwwmoVS3EGub46YbHqbmWMLg==" ], + "priority" : [ "100" ] + } + }, { + "id" : "20460ca5-ec24-4a9b-839a-457743d3f841", + "name" : "hmac-generated", + "providerId" : "hmac-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "96afd00e-85cf-4d35-b18e-061d3813d8b2" ], + "secret" : [ "qBFGKdUGf6xDgKphnRfoFzIzaFHJW4bYnZ9MinPFzN38X5_ctq-2u1q5RdZzeJukXvk2biHB8_s3DxWmmLZFsA" ], + "priority" : [ "100" ], + "algorithm" : [ "HS256" ] + } + }, { + "id" : "4f02d984-7a23-4ce1-8591-848a71390efe", + "name" : "aes-generated", + "providerId" : "aes-generated", + "subComponents" : { }, + "config" : { + "kid" : [ "b04473d3-8395-4016-b455-19a9e951106b" ], + "secret" : [ "x68mMOVdz3qKWzltzReV0g" ], + "priority" : [ "100" ] + } + } ] + }, + "internationalizationEnabled" : false, + "supportedLocales" : [ ], + "authenticationFlows" : [ { + "id" : "d6c3e282-a738-4b8b-98c2-378b9faf8344", + "alias" : "Handle Existing Account", + "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-confirm-link", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "idp-email-verification", + "requirement" : "ALTERNATIVE", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "requirement" : "ALTERNATIVE", + "priority" : 30, + "flowAlias" : "Verify Existing Account by Re-authentication", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "4855860b-4009-4f1b-ba6b-60581618ea62", + "alias" : "Verify Existing Account by Re-authentication", + "description" : "Reauthentication of existing account", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "idp-username-password-form", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "auth-otp-form", + "requirement" : "OPTIONAL", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "8a9872b0-65f1-47ff-9565-fa826ac64cd4", + "alias" : "browser", + "description" : "browser based authentication", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-cookie", + "requirement" : "ALTERNATIVE", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "auth-spnego", + "requirement" : "DISABLED", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "identity-provider-redirector", + "requirement" : "ALTERNATIVE", + "priority" : 25, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "requirement" : "ALTERNATIVE", + "priority" : 30, + "flowAlias" : "forms", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "51b8ed14-62b6-49b3-b602-0b51508349e0", + "alias" : "clients", + "description" : "Base authentication for clients", + "providerId" : "client-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "client-secret", + "requirement" : "ALTERNATIVE", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "client-jwt", + "requirement" : "ALTERNATIVE", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "client-secret-jwt", + "requirement" : "ALTERNATIVE", + "priority" : 30, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "client-x509", + "requirement" : "ALTERNATIVE", + "priority" : 40, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "9b65133a-ee71-494a-a659-6804513fc30b", + "alias" : "direct grant", + "description" : "OpenID Connect Resource Owner Grant", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "direct-grant-validate-username", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "direct-grant-validate-password", + "requirement" : "REQUIRED", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "direct-grant-validate-otp", + "requirement" : "OPTIONAL", + "priority" : 30, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "f62bc4ad-25ac-4f83-963b-32820af3a683", + "alias" : "docker auth", + "description" : "Used by Docker clients to authenticate against the IDP", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "docker-http-basic-authenticator", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "1b423fe7-f312-404c-903b-f1260a77259b", + "alias" : "first broker login", + "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticatorConfig" : "review profile config", + "authenticator" : "idp-review-profile", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticatorConfig" : "create unique user config", + "authenticator" : "idp-create-user-if-unique", + "requirement" : "ALTERNATIVE", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "requirement" : "ALTERNATIVE", + "priority" : 30, + "flowAlias" : "Handle Existing Account", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "9c9530b3-e3c6-481b-99e8-1461a9752e8e", + "alias" : "forms", + "description" : "Username, password, otp and other auth forms.", + "providerId" : "basic-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "auth-username-password-form", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "auth-otp-form", + "requirement" : "OPTIONAL", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "70fb94ac-354c-4629-a5fe-5135d0137964", + "alias" : "http challenge", + "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "no-cookie-redirect", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "basic-auth", + "requirement" : "REQUIRED", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "basic-auth-otp", + "requirement" : "DISABLED", + "priority" : 30, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "auth-spnego", + "requirement" : "DISABLED", + "priority" : 40, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "08292a4a-6722-4e33-a5d9-354c2628f567", + "alias" : "registration", + "description" : "registration flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-page-form", + "requirement" : "REQUIRED", + "priority" : 10, + "flowAlias" : "registration form", + "userSetupAllowed" : false, + "autheticatorFlow" : true + } ] + }, { + "id" : "668dc4b6-fe1a-4d24-ab5b-bc76e20ac390", + "alias" : "registration form", + "description" : "registration form", + "providerId" : "form-flow", + "topLevel" : false, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "registration-user-creation", + "requirement" : "REQUIRED", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "registration-profile-action", + "requirement" : "REQUIRED", + "priority" : 40, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "registration-password-action", + "requirement" : "REQUIRED", + "priority" : 50, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "registration-recaptcha-action", + "requirement" : "DISABLED", + "priority" : 60, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "a0e191f0-ce9a-4a75-b6e4-97332b05f7e5", + "alias" : "reset credentials", + "description" : "Reset credentials for a user if they forgot their password or something", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "reset-credentials-choose-user", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "reset-credential-email", + "requirement" : "REQUIRED", + "priority" : 20, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "reset-password", + "requirement" : "REQUIRED", + "priority" : 30, + "userSetupAllowed" : false, + "autheticatorFlow" : false + }, { + "authenticator" : "reset-otp", + "requirement" : "OPTIONAL", + "priority" : 40, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + }, { + "id" : "ad4beb21-8e9a-4fca-af41-0f757169f26c", + "alias" : "saml ecp", + "description" : "SAML ECP Profile Authentication Flow", + "providerId" : "basic-flow", + "topLevel" : true, + "builtIn" : true, + "authenticationExecutions" : [ { + "authenticator" : "http-basic-authenticator", + "requirement" : "REQUIRED", + "priority" : 10, + "userSetupAllowed" : false, + "autheticatorFlow" : false + } ] + } ], + "authenticatorConfig" : [ { + "id" : "25632f91-6071-423a-8e9c-7322cdc1b011", + "alias" : "create unique user config", + "config" : { + "require.password.update.after.registration" : "false" + } + }, { + "id" : "02d7f70b-1ebc-4e72-a65c-d94a600895ac", + "alias" : "review profile config", + "config" : { + "update.profile.on.first.login" : "missing" + } + } ], + "requiredActions" : [ { + "alias" : "CONFIGURE_TOTP", + "name" : "Configure OTP", + "providerId" : "CONFIGURE_TOTP", + "enabled" : true, + "defaultAction" : false, + "priority" : 10, + "config" : { } + }, { + "alias" : "terms_and_conditions", + "name" : "Terms and Conditions", + "providerId" : "terms_and_conditions", + "enabled" : false, + "defaultAction" : false, + "priority" : 20, + "config" : { } + }, { + "alias" : "UPDATE_PASSWORD", + "name" : "Update Password", + "providerId" : "UPDATE_PASSWORD", + "enabled" : true, + "defaultAction" : false, + "priority" : 30, + "config" : { } + }, { + "alias" : "UPDATE_PROFILE", + "name" : "Update Profile", + "providerId" : "UPDATE_PROFILE", + "enabled" : true, + "defaultAction" : false, + "priority" : 40, + "config" : { } + }, { + "alias" : "VERIFY_EMAIL", + "name" : "Verify Email", + "providerId" : "VERIFY_EMAIL", + "enabled" : true, + "defaultAction" : false, + "priority" : 50, + "config" : { } + } ], + "browserFlow" : "browser", + "registrationFlow" : "registration", + "directGrantFlow" : "direct grant", + "resetCredentialsFlow" : "reset credentials", + "clientAuthenticationFlow" : "clients", + "dockerAuthenticationFlow" : "docker auth", + "attributes" : { + "_browser_header.xXSSProtection" : "1; mode=block", + "_browser_header.xFrameOptions" : "SAMEORIGIN", + "_browser_header.strictTransportSecurity" : "max-age=31536000; includeSubDomains", + "permanentLockout" : "false", + "quickLoginCheckMilliSeconds" : "1000", + "_browser_header.xRobotsTag" : "none", + "maxFailureWaitSeconds" : "900", + "minimumQuickLoginWaitSeconds" : "60", + "failureFactor" : "30", + "actionTokenGeneratedByUserLifespan" : "300", + "maxDeltaTimeSeconds" : "43200", + "_browser_header.xContentTypeOptions" : "nosniff", + "offlineSessionMaxLifespan" : "5184000", + "actionTokenGeneratedByAdminLifespan" : "43200", + "_browser_header.contentSecurityPolicyReportOnly" : "", + "bruteForceProtected" : "false", + "_browser_header.contentSecurityPolicy" : "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "waitIncrementSeconds" : "60", + "offlineSessionMaxLifespanEnabled" : "false" + }, + "users" : [ { + "id" : "af134cab-f41c-4675-b141-205f975db679", + "username" : "admin", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "type" : "password", + "hashedSaltedValue" : "NICTtwsvSxJ5hL8hLAuleDUv9jwZcuXgxviMXvR++cciyPtiIEStEaJUyfA9DOir59awjPrHOumsclPVjNBplA==", + "salt" : "T/2P5o5oxFJUEk68BRURRg==", + "hashIterations" : 27500, + "counter" : 0, + "algorithm" : "pbkdf2-sha256", + "digits" : 0, + "period" : 0, + "createdDate" : 1554245879354, + "config" : { } + } ], + "disableableCredentialTypes" : [ "password" ], + "requiredActions" : [ ], + "realmRoles" : [ "admin", "user" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "eb4123a3-b722-4798-9af5-8957f823657a", + "username" : "alice", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "type" : "password", + "hashedSaltedValue" : "A3okqV2T/ybXTVEgKfosoSjP8Yc9IZbFP/SY4cEd6hag7TABQrQ6nUSuwagGt96l8cw1DTijO75PqX6uiTXMzw==", + "salt" : "sl4mXx6T9FypPH/s9TngfQ==", + "hashIterations" : 27500, + "counter" : 0, + "algorithm" : "pbkdf2-sha256", + "digits" : 0, + "period" : 0, + "createdDate" : 1554245879116, + "config" : { } + } ], + "disableableCredentialTypes" : [ "password" ], + "requiredActions" : [ ], + "realmRoles" : [ "user" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "1eed6a8e-a853-4597-b4c6-c4c2533546a0", + "username" : "jdoe", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "credentials" : [ { + "type" : "password", + "hashedSaltedValue" : "JV3DUNLjqOadjbBOtC4rvacQI553CGaDGAzBS8MR5ReCr7SwF3E6CsW3T7/XO8ITZAsch8+A/6loeuCoVLLJrg==", + "salt" : "uCbOH7HZtyDtMd0E9DG/nw==", + "hashIterations" : 27500, + "counter" : 0, + "algorithm" : "pbkdf2-sha256", + "digits" : 0, + "period" : 0, + "createdDate" : 1554245879227, + "config" : { } + } ], + "disableableCredentialTypes" : [ "password" ], + "requiredActions" : [ ], + "realmRoles" : [ "confidential", "user" ], + "notBefore" : 0, + "groups" : [ ] + }, { + "id" : "948c59ec-46ed-4d99-aa43-02900029b930", + "createdTimestamp" : 1554245880023, + "username" : "service-account-backend-service", + "enabled" : true, + "totp" : false, + "emailVerified" : false, + "email" : "service-account-backend-service@placeholder.org", + "serviceAccountClientId" : "backend-service", + "credentials" : [ ], + "disableableCredentialTypes" : [ ], + "requiredActions" : [ ], + "realmRoles" : [ "offline_access" ], + "clientRoles" : { + "backend-service" : [ "uma_protection" ], + "account" : [ "view-profile", "manage-account" ] + }, + "notBefore" : 0, + "groups" : [ ] + } ], + "keycloakVersion" : "6.0.0", + "userManagedAccessAllowed" : false +} diff --git a/integration/quarkus-keycloak-authorization/docker-compose.yaml b/integration/quarkus-keycloak-authorization/docker-compose.yaml new file mode 100644 index 0000000..d80cf0e --- /dev/null +++ b/integration/quarkus-keycloak-authorization/docker-compose.yaml @@ -0,0 +1,18 @@ +version: "3" + +services: + postgresdb: + image: docker.io/bitnami/postgresql:14 + container_name: postgresdb + environment: + POSTGRES_HOST_AUTH_METHOD: trust + POSTGRES_USER: demo + POSTGRES_PASSWORD: demo + POSTGRES_DB: demo + ports: + - "5432:5432" + networks: + - demo + +networks: + demo: \ No newline at end of file diff --git a/integration/quarkus-keycloak-authorization/mvnw b/integration/quarkus-keycloak-authorization/mvnw new file mode 100644 index 0000000..5643201 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/mvnw @@ -0,0 +1,316 @@ +#!/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. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + 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 + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/integration/quarkus-keycloak-authorization/mvnw.cmd b/integration/quarkus-keycloak-authorization/mvnw.cmd new file mode 100644 index 0000000..8a15b7f --- /dev/null +++ b/integration/quarkus-keycloak-authorization/mvnw.cmd @@ -0,0 +1,188 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/integration/quarkus-keycloak-authorization/pom.xml b/integration/quarkus-keycloak-authorization/pom.xml new file mode 100644 index 0000000..d4e0958 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/pom.xml @@ -0,0 +1,312 @@ + + + 4.0.0 + + com.devonfw.quarkus + quarkus-keycloak-authorization + 1.0.0-SNAPSHOT + + + quarkus-bom + io.quarkus + 2.12.2.Final +2.12.2.Final +3.10.1 + 3.0.0-M7 + 11 + 11 + UTF-8 + 1.4.2.Final + + + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + + + + + + + io.quarkus + quarkus-smallrye-jwt + + + io.quarkus + quarkus-smallrye-jwt-build + + + + + io.quarkus + quarkus-keycloak-authorization + + + io.quarkus + quarkus-oidc + + + io.quarkus + quarkus-resteasy-reactive-jackson + + + + + io.quarkus + quarkus-smallrye-openapi + + + + + + + io.quarkus + quarkus-jdbc-postgresql + + + + org.hibernate + hibernate-jpamodelgen + + + io.quarkus + quarkus-spring-data-jpa + + + + + io.quarkus + quarkus-flyway + + + + com.querydsl + querydsl-jpa + 4.3.1 + + + com.querydsl + querydsl-apt + provided + 4.3.1 + + + + + io.quarkus + quarkus-logging-json + + + + + org.projectlombok + lombok + 1.18.18 + provided + + + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + provided + + + org.mapstruct + mapstruct + ${mapstruct.version} + provided + + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + provided + + + + + + io.rest-assured + rest-assured + test + + + io.quarkus + quarkus-junit5 + test + + + io.quarkus + quarkus-test-keycloak-server + test + + + + + + + src/main/resources + + + config + + + + + + + io.quarkus + quarkus-maven-plugin + ${quarkus-plugin.version} + true + + + + build + generate-code + generate-code-tests + + + + + + maven-compiler-plugin + ${compiler-plugin.version} + + true + + + -Amapstruct.defaultComponentModel=cdi + -Amapstruct.defaultInjectionStrategy=CONSTRUCTOR + + + + + + maven-surefire-plugin + ${surefire.version} + + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + ${quarkus.platform.group-id} + quarkus-maven-plugin + ${quarkus.platform.version} + + + + build + + + + + + + com.mysema.maven + apt-maven-plugin + 1.1.3 + + + generate-sources + + process + + + target/generated-sources/annotations + com.querydsl.apt.jpa.JPAAnnotationProcessor + + + + + + + + + + + native + + + native + + + + native + true + + + + + maven-failsafe-plugin + ${surefire.version} + + + + integration-test + verify + + + + + ${project.build.directory}/${project.build.finalName}-runner + + + org.jboss.logmanager.LogManager + + ${maven.home} + + + + + + + + + + docker + + + start-containers + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.0.0 + + + docker-prune + generate-resources + + exec + + + ${basedir}/../.github/docker-prune.sh + + + + + + + + + diff --git a/integration/quarkus-keycloak-authorization/src/main/docker/Dockerfile.jvm b/integration/quarkus-keycloak-authorization/src/main/docker/Dockerfile.jvm new file mode 100644 index 0000000..1d54df5 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/docker/Dockerfile.jvm @@ -0,0 +1,54 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode +# +# Before building the container image run: +# +# ./mvnw package +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/security-keycloak-authorization-jvm . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/security-keycloak-authorization-jvm +# +# If you want to include the debug port into your docker image +# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 +# +# Then run the container using : +# +# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/security-keycloak-authorization-jvm +# +### +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 + +ARG JAVA_PACKAGE=java-11-openjdk-headless +ARG RUN_JAVA_VERSION=1.3.8 +ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' +# Install java and the run-java script +# Also set up permissions for user `1001` +RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ + && microdnf update \ + && microdnf clean all \ + && mkdir /deployments \ + && chown 1001 /deployments \ + && chmod "g+rwX" /deployments \ + && chown 1001:root /deployments \ + && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ + && chown 1001 /deployments/run-java.sh \ + && chmod 540 /deployments/run-java.sh \ + && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security + +# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. +ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +# We make four distinct layers so if there are application changes the library layers can be re-used +COPY --chown=1001 target/quarkus-app/lib/ /deployments/lib/ +COPY --chown=1001 target/quarkus-app/*.jar /deployments/ +COPY --chown=1001 target/quarkus-app/app/ /deployments/app/ +COPY --chown=1001 target/quarkus-app/quarkus/ /deployments/quarkus/ + +EXPOSE 8080 +USER 1001 + +ENTRYPOINT [ "/deployments/run-java.sh" ] diff --git a/integration/quarkus-keycloak-authorization/src/main/docker/Dockerfile.legacy-jar b/integration/quarkus-keycloak-authorization/src/main/docker/Dockerfile.legacy-jar new file mode 100644 index 0000000..fdb0863 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/docker/Dockerfile.legacy-jar @@ -0,0 +1,51 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode +# +# Before building the container image run: +# +# ./mvnw package -Dquarkus.package.type=legacy-jar +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.legacy-jar -t quarkus/security-keycloak-authorization-legacy-jar . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/security-keycloak-authorization-legacy-jar +# +# If you want to include the debug port into your docker image +# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050 +# +# Then run the container using : +# +# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/security-keycloak-authorization-legacy-jar +# +### +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 + +ARG JAVA_PACKAGE=java-11-openjdk-headless +ARG RUN_JAVA_VERSION=1.3.8 +ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' +# Install java and the run-java script +# Also set up permissions for user `1001` +RUN microdnf install curl ca-certificates ${JAVA_PACKAGE} \ + && microdnf update \ + && microdnf clean all \ + && mkdir /deployments \ + && chown 1001 /deployments \ + && chmod "g+rwX" /deployments \ + && chown 1001:root /deployments \ + && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \ + && chown 1001 /deployments/run-java.sh \ + && chmod 540 /deployments/run-java.sh \ + && echo "securerandom.source=file:/dev/urandom" >> /etc/alternatives/jre/lib/security/java.security + +# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size. +ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" +COPY target/lib/* /deployments/lib/ +COPY target/*-runner.jar /deployments/app.jar + +EXPOSE 8080 +USER 1001 + +ENTRYPOINT [ "/deployments/run-java.sh" ] diff --git a/integration/quarkus-keycloak-authorization/src/main/docker/Dockerfile.native b/integration/quarkus-keycloak-authorization/src/main/docker/Dockerfile.native new file mode 100644 index 0000000..aa62636 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/docker/Dockerfile.native @@ -0,0 +1,27 @@ +#### +# This Dockerfile is used in order to build a container that runs the Quarkus application in native (no JVM) mode +# +# Before building the container image run: +# +# ./mvnw package -Pnative +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.native -t quarkus/security-keycloak-authorization . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/security-keycloak-authorization +# +### +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3 +WORKDIR /work/ +RUN chown 1001 /work \ + && chmod "g+rwX" /work \ + && chown 1001:root /work +COPY --chown=1001:root target/*-runner /work/application + +EXPOSE 8080 +USER 1001 + +CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] diff --git a/integration/quarkus-keycloak-authorization/src/main/docker/Dockerfile.native-micro b/integration/quarkus-keycloak-authorization/src/main/docker/Dockerfile.native-micro new file mode 100644 index 0000000..663b8d2 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/docker/Dockerfile.native-micro @@ -0,0 +1,23 @@ +#### +# This Dockerfile is used in order to build a distroless container that runs the Quarkus application in native (no JVM) mode +# +# Before building the container image run: +# +# ./mvnw package -Pnative +# +# Then, build the image with: +# +# docker build -f src/main/docker/Dockerfile.native-micro -t quarkus/security-keycloak-authorization . +# +# Then run the container using: +# +# docker run -i --rm -p 8080:8080 quarkus/security-keycloak-authorization +# +### +FROM quay.io/quarkus/quarkus-micro-image:1.0 +COPY target/*-runner /application + +EXPOSE 8080 +USER 1001 + +CMD ["./application", "-Dquarkus.http.host=0.0.0.0"] diff --git a/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/DemoApplication.java b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/DemoApplication.java new file mode 100644 index 0000000..3acb3d1 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/DemoApplication.java @@ -0,0 +1,17 @@ +package com.devonfw.quarkus; + +import javax.ws.rs.core.Application; + +import org.eclipse.microprofile.openapi.annotations.OpenAPIDefinition; +import org.eclipse.microprofile.openapi.annotations.info.Contact; +import org.eclipse.microprofile.openapi.annotations.info.Info; +import org.eclipse.microprofile.openapi.annotations.tags.Tag; + +@OpenAPIDefinition(tags = { +@Tag(name = "product", description = "Product API.") }, info = @Info(title = "Quarkus Keycloak AuthN AuthZ demo", version = "1.0.0", contact = @Contact(name = "API Support", email = "support@devonfw.com"))) +/** + * JaxRS application is not required in quarkus, but it is useful to place central API docs somewhere. We could also use + * package-info.java for this. + */ +public class DemoApplication extends Application { +} \ No newline at end of file diff --git a/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/general/domain/model/ApplicationPersistenceEntity.java b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/general/domain/model/ApplicationPersistenceEntity.java new file mode 100644 index 0000000..51e7550 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/general/domain/model/ApplicationPersistenceEntity.java @@ -0,0 +1,79 @@ +package com.devonfw.quarkus.general.domain.model; + +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; +import javax.persistence.Transient; +import javax.persistence.Version; + +/** + * Abstract base class for all {@link PersistenceEntity persistence entities} with an {@link #getId() id} and a + * {@link #getModificationCounter() modificationCounter} (version) field. All persistence entities of this application + * should inherit from this class. It is using JPA annotations at the getters what has several advantages but also + * implies that you have to annotate transient getter methods with the {@link Transient} annotation. + */ +@MappedSuperclass +public abstract class ApplicationPersistenceEntity { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Version + private Integer modificationCounter; + + /** + * The constructor. + */ + public ApplicationPersistenceEntity() { + + super(); + } + + public Long getId() { + + return this.id; + } + + public void setId(Long id) { + + this.id = id; + } + + public Integer getModificationCounter() { + + return this.modificationCounter; + } + + public void setModificationCounter(Integer version) { + + this.modificationCounter = version; + } + + @Override + public String toString() { + + StringBuilder buffer = new StringBuilder(); + toString(buffer); + return buffer.toString(); + } + + /** + * Method to extend {@link #toString()} logic. + * + * @param buffer is the {@link StringBuilder} where to {@link StringBuilder#append(Object) append} the string + * representation. + */ + protected void toString(StringBuilder buffer) { + + buffer.append(getClass().getSimpleName()); + if (this.id != null) { + buffer.append("[id="); + buffer.append(this.id); + buffer.append("]"); + } + } +} diff --git a/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/general/domain/model/ApplicationSearchCriteriaDto.java b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/general/domain/model/ApplicationSearchCriteriaDto.java new file mode 100644 index 0000000..160fa3d --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/general/domain/model/ApplicationSearchCriteriaDto.java @@ -0,0 +1,23 @@ +package com.devonfw.quarkus.general.domain.model; + +import org.eclipse.microprofile.openapi.annotations.media.Schema; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +public class ApplicationSearchCriteriaDto { + + @Schema(description = "Page Number", defaultValue = "0") + private int pageNumber = 0; + + @Schema(description = "Page Size", defaultValue = "10") + private int pageSize = 10; + + @Schema(description = "determine total") + private boolean determineTotal = false; + +} diff --git a/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/domain/model/ProductEntity.java b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/domain/model/ProductEntity.java new file mode 100644 index 0000000..b7b22ac --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/domain/model/ProductEntity.java @@ -0,0 +1,26 @@ +package com.devonfw.quarkus.productmanagement.domain.model; + +import java.math.BigDecimal; + +import javax.persistence.Entity; +import javax.persistence.Table; + +import com.devonfw.quarkus.general.domain.model.ApplicationPersistenceEntity; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Entity +@Table(name = "Product") +// A JPA entity requires at least 2 things @Entity annotation and an ID +// by default, the DB table will have the same name as our class +public class ProductEntity extends ApplicationPersistenceEntity { + + private String title; + + private String description; + + private BigDecimal price; +} diff --git a/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/domain/repo/ProductRepository.java b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/domain/repo/ProductRepository.java new file mode 100644 index 0000000..32d312d --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/domain/repo/ProductRepository.java @@ -0,0 +1,16 @@ +package com.devonfw.quarkus.productmanagement.domain.repo; + +import org.springframework.data.domain.Page; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; + +import com.devonfw.quarkus.productmanagement.domain.model.ProductEntity; + +public interface ProductRepository extends CrudRepository { + + @Query("select a from ProductEntity a where title = :title") + ProductEntity findByTitle(@Param("title") String title); + + Page findAllByOrderByTitle(); +} \ No newline at end of file diff --git a/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/ProductReadService.java b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/ProductReadService.java new file mode 100644 index 0000000..2c3ff79 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/ProductReadService.java @@ -0,0 +1,85 @@ +package com.devonfw.quarkus.productmanagement.rest.v1; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +import javax.inject.Inject; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +import org.eclipse.microprofile.jwt.JsonWebToken; +import org.eclipse.microprofile.openapi.annotations.enums.SecuritySchemeType; +import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.security.SecurityRequirement; +import org.eclipse.microprofile.openapi.annotations.security.SecurityScheme; +import org.jose4j.json.internal.json_simple.JSONObject; +import org.springframework.data.domain.Page; + +import com.devonfw.quarkus.productmanagement.domain.model.ProductEntity; +import com.devonfw.quarkus.productmanagement.domain.repo.ProductRepository; +import com.devonfw.quarkus.productmanagement.rest.v1.mapper.ProductMapper; +import com.devonfw.quarkus.productmanagement.rest.v1.model.ProductDto; + +@Path("/product/v1/users") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +@SecurityScheme(securitySchemeName = "jwt", type = SecuritySchemeType.HTTP, scheme = "bearer", bearerFormat = "jwt") +public class ProductReadService { + + @Inject + JsonWebToken jwt; + + @Inject + ProductRepository productRepository; + + @Inject + ProductMapper productMapper; + + @GET + @Path("claims") + @SecurityRequirement(name = "jwt", scopes = {}) + public String getClaims() { + + Map claims = new HashMap<>(); + this.jwt.getClaimNames().stream() + .forEach(claimName -> claims.put(claimName, this.jwt.getClaim(claimName).toString())); + return new JSONObject(claims).toJSONString(); + } + + @GET + @SecurityRequirement(name = "jwt", scopes = {}) + public Page getProducts() { + + Page products = this.productRepository.findAllByOrderByTitle(); + if (products != null) { + return this.productMapper.map(products); + } + return null; + } + + @GET + @Path("{id}") + @SecurityRequirement(name = "jwt", scopes = {}) + public ProductDto getProductById(@Parameter(description = "Product unique id") @PathParam("id") String id) { + + Optional product = this.productRepository.findById(Long.valueOf(id)); + if (product.isPresent()) { + return this.productMapper.map(product.get()); + } + return null; + } + + @GET + @Path("title/{title}") + @SecurityRequirement(name = "jwt", scopes = {}) + public ProductDto getProductByTitle(@PathParam("title") String title) { + + return this.productMapper.map(this.productRepository.findByTitle(title)); + } + +} diff --git a/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/ProductWriteService.java b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/ProductWriteService.java new file mode 100644 index 0000000..bf6072d --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/ProductWriteService.java @@ -0,0 +1,81 @@ +package com.devonfw.quarkus.productmanagement.rest.v1; + +import static com.devonfw.quarkus.productmanagement.utils.StringUtils.isEmpty; +import static javax.ws.rs.core.Response.created; +import static javax.ws.rs.core.Response.status; + +import javax.inject.Inject; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; + +import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.security.SecurityRequirement; + +import com.devonfw.quarkus.productmanagement.domain.model.ProductEntity; +import com.devonfw.quarkus.productmanagement.domain.repo.ProductRepository; +import com.devonfw.quarkus.productmanagement.rest.v1.mapper.ProductMapper; +import com.devonfw.quarkus.productmanagement.rest.v1.model.ProductDto; +import com.devonfw.quarkus.productmanagement.rest.v1.model.User; + +import io.quarkus.security.identity.SecurityIdentity; + +@Path("/product/v1/admin") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class ProductWriteService { + + @Context + UriInfo uriInfo; + + @Inject + ProductRepository productRepository; + + @Inject + ProductMapper productMapper; + + @Inject + SecurityIdentity keycloakSecurityContext; + + @GET + @SecurityRequirement(name = "jwt", scopes = {}) + public User manage() { + + return new User(this.keycloakSecurityContext); + } + + @POST + @SecurityRequirement(name = "jwt", scopes = {}) + public Response createNewProduct(ProductDto product) { + + if (isEmpty(product.getTitle())) { + throw new WebApplicationException("Title was not set on request.", 400); + } + + ProductEntity productEntity = this.productRepository.save(this.productMapper.map(product)); + + UriBuilder uriBuilder = this.uriInfo.getAbsolutePathBuilder().path(Long.toString(productEntity.getId())); + return created(uriBuilder.build()).build(); + } + + @DELETE + @Path("{id}") + @SecurityRequirement(name = "jwt", scopes = {}) + public Response deleteProductById(@Parameter(description = "Product unique id") @PathParam("id") String id) { + + this.productRepository.deleteById(Long.valueOf(id)); + return status(Status.NO_CONTENT.getStatusCode()).build(); + } + +} diff --git a/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/mapper/ProductMapper.java b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/mapper/ProductMapper.java new file mode 100644 index 0000000..9c36b77 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/mapper/ProductMapper.java @@ -0,0 +1,26 @@ +package com.devonfw.quarkus.productmanagement.rest.v1.mapper; + +import java.util.List; + +import org.mapstruct.Mapper; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; + +import com.devonfw.quarkus.productmanagement.domain.model.ProductEntity; +import com.devonfw.quarkus.productmanagement.rest.v1.model.ProductDto; + +@Mapper +public interface ProductMapper { + + ProductDto map(ProductEntity model); + + ProductEntity map(ProductDto dto); + + List map(List Products); + + default Page map(Page products) { + + List productsDto = this.map(products.getContent()); + return new PageImpl<>(productsDto, products.getPageable(), products.getTotalElements()); + } +} diff --git a/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/model/AbstractDto.java b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/model/AbstractDto.java new file mode 100644 index 0000000..dd920a2 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/model/AbstractDto.java @@ -0,0 +1,14 @@ +package com.devonfw.quarkus.productmanagement.rest.v1.model; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +public abstract class AbstractDto { + private int modificationCounter; + + private Long id; +} diff --git a/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/model/ProductDto.java b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/model/ProductDto.java new file mode 100644 index 0000000..1f11e7c --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/model/ProductDto.java @@ -0,0 +1,29 @@ +package com.devonfw.quarkus.productmanagement.rest.v1.model; + +import java.math.BigDecimal; + +import org.eclipse.microprofile.openapi.annotations.media.Schema; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductDto extends AbstractDto { + + @Schema(nullable = false, description = "Product title", minLength = 3, maxLength = 500) + private String title; + + @Schema(description = "Product description", minLength = 3, maxLength = 500) + private String description; + + @Schema(description = "Product price") + private BigDecimal price; + +} diff --git a/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/model/ProductSearchCriteriaDto.java b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/model/ProductSearchCriteriaDto.java new file mode 100644 index 0000000..7486174 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/model/ProductSearchCriteriaDto.java @@ -0,0 +1,25 @@ +package com.devonfw.quarkus.productmanagement.rest.v1.model; + +import java.math.BigDecimal; + +import org.eclipse.microprofile.openapi.annotations.media.Schema; + +import com.devonfw.quarkus.general.domain.model.ApplicationSearchCriteriaDto; + +import lombok.Data; + +@Data +public class ProductSearchCriteriaDto extends ApplicationSearchCriteriaDto { + + @Schema(description = "Product title") + private String title; + + @Schema(description = "Product Min price") + private BigDecimal priceMin; + + @Schema(description = "Product Max price") + private BigDecimal priceMax; + + @Schema(description = "Product price") + private BigDecimal price; +} diff --git a/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/model/User.java b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/model/User.java new file mode 100644 index 0000000..4e50315 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/rest/v1/model/User.java @@ -0,0 +1,18 @@ +package com.devonfw.quarkus.productmanagement.rest.v1.model; + +import io.quarkus.security.identity.SecurityIdentity; + +public class User { + + private final String userName; + + public User(SecurityIdentity securityContext) { + + this.userName = securityContext.getPrincipal().getName(); + } + + public String getUserName() { + + return this.userName; + } +} \ No newline at end of file diff --git a/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/utils/QueryUtil.java b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/utils/QueryUtil.java new file mode 100644 index 0000000..24ec6d0 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/utils/QueryUtil.java @@ -0,0 +1,32 @@ +package com.devonfw.quarkus.productmanagement.utils; + +import java.util.List; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; + +import com.querydsl.jpa.impl.JPAQuery; + +public class QueryUtil { + + public static Page findPaginated(Pageable pageable, JPAQuery query, boolean determineTotal) { + + long total = -1; + if (determineTotal) { + total = query.clone().fetchCount(); + } + long offset = 0; + if (pageable != null) { + offset = pageable.getOffset(); + query.offset(offset); + query.limit(pageable.getPageSize()); + // applySort(query, pageable.getSort()); + } + List hits = query.fetch(); + if (total == -1) { + total = offset + hits.size(); + } + return new PageImpl<>(hits, pageable, total); + } +} diff --git a/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/utils/StringUtils.java b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/utils/StringUtils.java new file mode 100644 index 0000000..effc93c --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/java/com/devonfw/quarkus/productmanagement/utils/StringUtils.java @@ -0,0 +1,8 @@ +package com.devonfw.quarkus.productmanagement.utils; + +public class StringUtils { + public static boolean isEmpty(String str) { + + return (str == null || "".equals(str)); + } +} diff --git a/integration/quarkus-keycloak-authorization/src/main/resources/application.properties b/integration/quarkus-keycloak-authorization/src/main/resources/application.properties new file mode 100644 index 0000000..603fd16 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/resources/application.properties @@ -0,0 +1,26 @@ +# Configuration file +%prod.quarkus.oidc.auth-server-url=https://localhost:8543/realms/quarkus +quarkus.oidc.client-id=backend-service +quarkus.oidc.credentials.secret=secret +quarkus.oidc.tls.verification=none +quarkus.keycloak.devservices.realm-path=quarkus-realm.json +quarkus.oidc.token.issuer=any + +# Enable Policy Enforcement +quarkus.keycloak.policy-enforcer.enable=true +quarkus.keycloak.policy-enforcer.lazy-load-paths=false + +# Disables policy enforcement for a path +quarkus.keycloak.policy-enforcer.paths.1.path=/api/public +quarkus.keycloak.policy-enforcer.paths.1.enforcement-mode=DISABLED + +# Datasource configuration +quarkus.datasource.db-kind=postgresql +quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/demo +quarkus.datasource.username=demo +quarkus.datasource.password=demo + +# Flyway minimal config properties +quarkus.flyway.migrate-at-start=true +quarkus.flyway.baseline-on-migrate=true +quarkus.flyway.baseline-version=0 \ No newline at end of file diff --git a/integration/quarkus-keycloak-authorization/src/main/resources/db/migration/V001__Create_schema.sql b/integration/quarkus-keycloak-authorization/src/main/resources/db/migration/V001__Create_schema.sql new file mode 100644 index 0000000..00b5a31 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/resources/db/migration/V001__Create_schema.sql @@ -0,0 +1,15 @@ + +CREATE SEQUENCE HIBERNATE_SEQUENCE START WITH 1000000; + +-- *** Product catalog *** + +CREATE TABLE Product +( + id BIGSERIAL, + modificationCounter INTEGER DEFAULT 0 NOT NULL, + title VARCHAR (255) NOT NULL, + description VARCHAR (4000), + price DECIMAL (16,2) NOT NULL, + CONSTRAINT PK_Product PRIMARY KEY(id) +); + diff --git a/integration/quarkus-keycloak-authorization/src/main/resources/db/migration/V002__Master_data.sql b/integration/quarkus-keycloak-authorization/src/main/resources/db/migration/V002__Master_data.sql new file mode 100644 index 0000000..e8eacc2 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/main/resources/db/migration/V002__Master_data.sql @@ -0,0 +1,352 @@ +-- Products 350 entries from https://github.com/etano/productner/blob/master/Product%20Dataset.csv +-- Original source: Justifying recommendations using distantly-labeled reviews and fined-grained aspects, Jianmo Ni, Jiacheng Li, Julian McAuley, Empirical Methods in Natural Language Processing (EMNLP), 2019ss +INSERT INTO Product( title, description, price) VALUES ( 'Bose Acoustimass 5 Series III Speaker System - AM53BK', 'Bose Acoustimass 5 Series III Speaker System - AM53BK/ 2 Dual Cube Speakers With Two 2-1/2'' Wide-range Drivers In Each Speaker/ Powerful Bass Module With Two 5-1/2'' Woofers/ 200 Watts Max Power/ Black Finish', 399.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Switcher - SBV40S', 'Sony Switcher - SBV40S/ Eliminates Disconnecting And Reconnecting Cables/ Compact Design/ 4 A/V Inputs With S-Video Jacks/ 1 A/V Output With S-Video (Y/C)Jack/ 2 Audio Output', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'Bose 27028 161 Bookshelf Pair Speakers In White - 161WH', 'Bose 161 Bookshelf Speakers In White - 161WH/ Articulated Array Speaker Design/ High-Excursion Twiddler Drivers/ Magnetically Shielded/ Priced Per Pair/ White Finish', 158.00); +INSERT INTO Product( title, description, price) VALUES ( 'Denon Stereo Tuner - TU1500RD', 'Denon Stereo Tuner - TU1500RD/ RDS Radio Data System/ AM-FM 40 Station Random Memory/ Rotary Tuning Knob/ Dot Matrix FL Display/ Optional Remote', 375.00); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic Integrated Telephone System - KXTS108W', 'Panasonic Integrated Telephone System - KXTS108W/ 16 Digit LCD With Clock/ Hands Free Speakerphone/ Built-In Data Port/ 10-Station One-Touch Dialing/ 3-Step Ringer Volume/ White Finish', 44.00); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic Hands-Free Headset - KXTCA86', 'Panasonic Hands-Free Headset - KXTCA86/ Comfort Fit And Fold Design/ Noise Cancelling Microphone/ Standard 2.5mm Connection', 14.95); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic Hands Free Headset - KXTCA92', 'Panasonic Hands Free Headset - KXTCA92/ Comfort Fit With Fold Design/ Noise Cancelling Microphone/ Volume Control/ Mute/ Standard 2.5mm Connection', 25.00); +INSERT INTO Product( title, description, price) VALUES ( 'Cuisinart Convection-Oven-Toaster-Broiler With Exact Heat Sensor - TOB165WH', 'Cuisinart Convection-Oven-Toaster-Broiler With Exact Heat Sensor - TOB165WH/ 0.5 Cubic Foot Oven Capacity/ LED Indicators/ Individual Or Combination Settings/ Always Even Shade Control/ 4 Hour Automatic Shut Off/ Slide-Out Crumb Tray/ Includes Broiling Pan/ White Finish', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'Frigidaire 24'' White Built-In Dishwasher - FDB130WH', 'Frigidaire 24'' FDB130RGS White Built-In Dishwasher - FDB130WH/ Convection Drying System/ QuietSound Sound Insulation Package/ 2 Wash Levels/ Adjustable Rinse Aid Dispenser/ Self Cleaning Filter/ White Finish', 229.00); +INSERT INTO Product( title, description, price) VALUES ( 'Cuisinart Cordless Electric Kettle - KUA17', 'Cuisinart Cordless Electric Kettle - KUA17/ 1-3/4 Quart Capacity/ Automatic Shut-Off/ Indicator Light/ Splash Guard Spout/ Cord Storage In Base/ Chrome Finish', 70.00); +INSERT INTO Product( title, description, price) VALUES ( 'Omnimount Wall Speaker Mount - 20WLBK', 'Omnimount Wall Speaker Mount - 20WLBK/ Stainless Steel Shafts And All Necessary Hardware Included/ Supports Speakers Up To 20 lbs./ Sold As Single / Black Finish', 39.95); +INSERT INTO Product( title, description, price) VALUES ( 'Omnimount Wall Speaker Mount - 20WLWH', 'Omnimount Wall Speaker Mount - 20WLWH/ Stainless Steel Shafts And All Necessary Hardware Included/ Supports Speakers Up To 20 lbs./ Sold as each / White Finish (Photo Showing Black)', 40.00); +INSERT INTO Product( title, description, price) VALUES ( 'Denon Semi-Automatic Turntable - Black Finish - DP29F', 'Denon Semi-Automatic Turntable - DP29F/ Metal Platter/ Built-In RIAA Equalizer/ DC Servo Motor/ 2 Speed 33 + 45 RPM/ Built-In Phono PreAmp', 150.00); +INSERT INTO Product( title, description, price) VALUES ( 'Escort Passport Radar And Laser Detector - Black Finish - 8500', 'Escort Passport X50 Radar And Laser Detector - 8500/ X-Band, K-Band, Ka-Band Operating Bands/ AlGaAs 280 LED Matrix/Text Display Type/ 3-Level Dimming, Plus Dark Mode/ Auto Mute/ City Mode Sensitivity/ Compact Size/ Red Display', 313.95); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Compact Disc Player/Recorder - RCDW500C', 'Sony Compact Disc Player/Recorder - RCDW500C/ 5-CD/Dual Deck With 4x High Speed Dubbing/ CD, CD-R, CD-RW, MP3 Playback Capable/ Super Bit Mapping Recording/ High Speed Finalizing', 299.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus WMS3B Black Weather Resistant Small Speaker Wall Mount - WMS3B', 'Sanus WMS3B Black Small Speaker Wall Mount - WMS3B/ Holds Up To An 8 Pound Speaker/ Multiple Pivot Points/ Weather Resistant For Indoor/Outdoor Use/ Black Finish/ Priced Per Pair', 29.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus WMS3S Silver Weather Resistant Small Speaker Wall Mount - WMS3S', 'Sanus WMS3S Silver Small Speaker Wall Mount - WMS3S/ Holds Up To An 8 Pound Speaker/ Multiple Pivot Points/ Weather Resistant For Indoor/Outdoor Use/ Silver Finish/ Priced Per Pair', 29.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus Euro Foundations Satellite Speaker Stand - EFSATB', 'Sanus Euro Foundations Satellite Speaker Stand - EFSATB/ Sturdy Base/ Adjustable Pillar And Floor Spikes/ Includes Three Different Speaker Mounting Methods/ Contemporary European Design/ Satin Powder-Coated Black Finish/ Priced Per Pair', 79.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus Euro Foundations Satellite Speaker Stand - EFSATS', 'Sanus Euro Foundations Satellite Speaker Stand - EFSATS/ Sturdy Base/ Adjustable Pillar And Floor Spikes/ Includes Three Different Speaker Mounting Methods/ Contemporary European Design/ Satin Powder-Coated Silver Finish/ Priced Per Pair', 79.99); +INSERT INTO Product( title, description, price) VALUES ( 'Escort Cordless Solo Radar Detector - S2E', 'Escort Cordless Solo Radar Detector - S2E/ S2/ 10 Programmable Features/ High-Efficiency Power Management/ Ultra-Performance Laser Protection/ AutoSensitivity Mode/ High Resolution Graphic LCD Display/ Built-In Earphone Jack', 343.95); +INSERT INTO Product( title, description, price) VALUES ( 'Kenwood 6-Disc CD Changer - KDCC669', 'Kenwood 6-Disc CD Changer - KDCC669/ 3-Angle Mounting/ CD, CD-R And CD-RW Playback/ Anti-Vibration Disc Transport/ Compatible With All Kenwood Units With Changer Control', 129.00); +INSERT INTO Product( title, description, price) VALUES ( 'Cuisinart Automatic Brew And Serve Coffeemaker - DTC975BK', 'Cuisinart Automatic Brew And Serve Coffeemaker - DTC975BK/ 12-Cup Double-Wall Insulated Stainless Steel Carafe/ Fully Automatic With 24-Hour Programmability/ Patented Brew-Through And Pour-Through Lid/ Brew Pause Feature/ Automatic Shutoff/ Black And Stainless Steel Finish', 99.95); +INSERT INTO Product( title, description, price) VALUES ( 'Sharp Over The Counter Microwave Oven - R1214SS', 'Sharp Over The Counter Microwave Oven - R1214SS/ 1.5 Cubic Foot Capacity/ 1100 Watts/ 24 Automatic Settings/ 2-Color Lighted LCD/ Smart And Easy Sensor Settings/ Auto-Touch Control Panel/ Stainless Steel Finish', 429.00); +INSERT INTO Product( title, description, price) VALUES ( 'Toshiba Rechargeable 5-Hour Battery Pack - MEDB05LX', 'Toshiba Rechargeable 5-Hour Battery Pack - MEDB05LX/ Works With SDP2500 And SDP2600 Portable DVD Players', 149.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Super Audio CD Player - SCDCE595', 'Sony Super Audio CD Player - SCDCE595/ Multi-Channel Super Audio CD Playback Capability/ CD/CD-R/CD-RW Playback Capability/ Multi-Channel Direct Stream Digitial Decoder/ Multi-Channel Management System/ SACD Text/CD Text Capability/ ETA LATE JANUARY 2009', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'Delonghi Twenty Four Seven Coffee Maker In Black - DC50B', 'Delonghi Twenty Four Seven Coffee Maker - DC50B/ 4-Cup Capacity/ Easy-Access, Washable Filter Basket/ Black Finish', 22.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus Silver LCD Television Turntable - TVLCDS', 'Sanus Silver LCD Television Turntable - TVLCDS/ Holds 13''-30'' Size Televisions/ 360 Degree Rotation/ Silver Finish', 29.99); +INSERT INTO Product( title, description, price) VALUES ( 'Delonghi Twenty Four Seven Coffee Maker - DC50W', 'Delonghi Twenty Four Seven Coffee Maker - DC50W/ 4-Cup Capacity/ Easy-Access, Washable Filter Basket/ White Finish', 22.00); +INSERT INTO Product( title, description, price) VALUES ( 'Universal IR/RF Remote - MX350', 'Universal IR/RF Remote - MX350/ Controls Up To 10 Components/ Extensive Macro Programming/ Memory Back-Up/ One Hand Ergonomics', 149.95); +INSERT INTO Product( title, description, price) VALUES ( 'Universal IR/RF Aeros Remote Control- MX850 - MX850', 'Universal IR/RF Aeros Remote Control- MX850/ Laser Etched Buttons/ Centrally Located Joystick/ Memory Back-Up/ One Hand Ergonomics/ Controls Up To 20 Components', 399.95); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic 5-Pack DVD-RAM Discs - LMAF120LU5', 'Panasonic 5-Pack DVD-RAM Discs - LMAF120LU5/ Slim Cases/ 2-3x Speed/ Single-Sided/ 120 Minute (4.7GB/Non-Cartridge)/ For Video Recording/ 5 Pack', 15.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus 13'' - 30'' VisionMount Flat Panel TV Silver Wall Mount - VMFS', 'Sanus 13'' - 30'' VisionMount Flat Panel TV Silver Wall Mount - VMFS/ Supports Up To 40 lbs/ Easy To Install/ Fingertip Virtual Axis Tilting System/ Silver Finish', 39.99); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Performer 22-1/2'' Charcoal Grill - 841001', 'Weber Performer 22-1/2'' Charcoal Grill - 841001/ Push-Button Igniter/ Porcelain-Enameled Bowl And Lid/ Dual-Purpose Themometer/ Crackproof All-Weather Wheels/ Black Lid Finish/ Assembly Required', 329.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus 13'' - 30'' Flat Panel TV Black Wall Mount - VM1B', 'Sanus 13'' - 30'' Flat Panel TV Black Wall Mount - VM1B/ Tilt And Swivel Motion/ Rigid Extruded Aluminum Construction/ Supports Up To 50 Lbs/ Black Finish', 69.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus 15'' - 40'' Flat Panel TV Silver Wall Mount - VM400S', 'Sanus 15'' - 40'' Flat Panel TV Silver Wall Mount - VM400S/ Virtual Axis Tilt Adjustment System/ Hinged Arm Extend From 3.5'' To 20''/ Durable Powder Coated Silver Finish', 219.99); +INSERT INTO Product( title, description, price) VALUES ( 'Delonghi Oil Filters - FK8', 'Delonghi Oil Filters - FK8/ Made For Use With D895UX/ 3 Pack', 18.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Performer 22-1/2'' Charcoal Grill - 848001', 'Weber Performer 22-1/2'' Charcoal Grill - 848001/ Push-Button Igniter/ Porcelain-Enameled Bowl And Lid/ Dual-Purpose Themometer/ Crackproof All-Weather Wheels/ Blue Lid Finish/ Assembly Required', 329.00); +INSERT INTO Product( title, description, price) VALUES ( 'Whirlpool 24'' Built-In Dishwasher - DU1055BK', 'Whirlpool 24'' Built-In Dishwasher - DU1055BK/ 14-Five Piece Place Setting Super Capacity Tub/ 5 Level Direct Feed SheerClean Wash System/ 4 Cycles/ AnyWare Plus Silverware Basket/ Quiet Partner I Sound Package/ Energy Star Qualified/ Black Finish', 397.00); +INSERT INTO Product( title, description, price) VALUES ( 'Whirlpool 24'' Built-In Dishwasher - DU1055SS', 'Whirlpool 24'' Built-In Dishwasher - DU1055SS/ 14-Five Piece Place Setting Super Capacity Tub/ 5 Level Direct Feed SheerClean Wash System/ 4 Cycles/ Soak And Scour Option/ AnyWare Plus Silverware Basket/ Quiet Partner I Sound Package/ Energy Star Qualified/ Black On Stainless Finish', 491.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Soft Cyber-Shot Carrying Case - LCSCST', 'Sony Soft Cyber-Shot Carrying Case - LCSCST/ Sturdy Nylon Construction/ Compact And Very Lightweight/ Stylish Black Design', 14.00); +INSERT INTO Product( title, description, price) VALUES ( 'Pioneer XM Digital Satellite Tuner for Pioneer Headunits - GEXP920XM', 'Pioneer XM Digital Satellite Tuner For Pioneer Headunits - GEXP920XM/ SAT Radio Ready/ XM Ready/ Built-In FM Modulator/ 18- Station/ 6- Button Presets/ Magne Mount Installation', 98.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus Universal Projector Ceiling Mount - Black Finish - VMPR1B', 'Sanus Universal Projector Ceiling Mount - VMPR1B/ Designed For DLP And LCD Projectors/ Quick Release Mechanism/ 50 Lbs Capacity/ Black Finish', 129.99); +INSERT INTO Product( title, description, price) VALUES ( 'Kenwood iPod Mobile Interface - KCAIP500', 'Kenwood iPod Mobile Interface - KCAIP500/ Compatible With Most Kenwood Receivers/ Text Display, Multiple Search Mode/ Powers And Charges iPod', 49.99); +INSERT INTO Product( title, description, price) VALUES ( 'Pioneer Wired Marine Remote Control Display - CDMR80D', 'Pioneer Wired Marine Remote Control Display - CDMR80D/ Compatible With Pioneer Headunits/ Satellite Radio Text Indications/ ATT (Volume Attenuator) Button', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'Bose Second Zone Remote - PMC2', 'Bose Second Zone Remote - PMC2/ Controls Lifestyle 38 Or 48 Media Center/ TV, VCR, Cable Box, Satellite Receiver/ Accesses Digitally Stored CDs In UMusic System', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony DVD-R Recordable Camcorder Media - 3DMR30L1H', 'Sony DVD-R Recordable Camcorder Media 3 Pack - 3DMR30L1H/ 30 Minute, 1.4 GB/ Accucore Technology/ Store Digital Video, Audio And Multimedia Files/ 3 Pack', 9.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sony VAIO Neoprene Laptop Carrying Case - Black Finish - VGPAMC3', 'Sony VAIO Neoprene Laptop Carrying Case - VGPAMC3/ Compatible With VAIO A Series 15'' And FS Series 15.4'' Widescreen Notebooks/ Helps Protect Your Notebook From Scratches, Spills And Dings/ Neoprene Offers Durable And Water-Resistant Protection', 22.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Color Ink Tank - CL41CL', 'Canon Color Ink Tank - CL41CL/ Compatible With The Pixma iP1600, MP170 Printers', 24.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Cyan Ink Tank - Cyan - CLI8C', 'Canon Cyan Ink Tank - CLI8C/ Compatible With The Pixma iP4200, iP5200, iP5200R, iP6600D, MP500, MP800 Printers', 16.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Magenta Ink Tank - Magenta - CLI8M', 'Canon Magenta Ink Tank - CLI8M/ Compatible With The Pixma iP4200, iP5200, iP5200R, iP6600D, MP500, MP800 Printers', 16.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Cyan Photo Ink Cartridge - Cyan - CLI8PC', 'Canon Cyan Photo Ink Cartridge - CLI8PC/ Compatible With The Pixma iP6600D Printer', 16.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Magenta Photo Ink Cartridge - Magenta - CLI8PM', 'Canon Magenta Photo Ink Cartridge - CLI8PM/ Compatible With The Pixma iP6600D Printer', 16.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Yellow Ink Cartridge - Yellow - CLI8Y', 'Canon Yellow Ink Cartridge - CLI8Y/ Compatible With The Pixma iP4200, iP5200, iP5200R, iP6600D, MP500, MP800 Printers', 16.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Black Ink Cartridge - Black - PG40BK', 'Canon Black Ink Cartridge - PG40BK/ Compatible With The Pixma iP1600, MP170 Printers', 19.00); +INSERT INTO Product( title, description, price) VALUES ( 'Pioneer Voice Command Pack - Black Finish - CDVC1', 'Pioneer Voice Command Pack - CDVC1/ Microphone And Steering Wheel Remote Control/ Use Your Voice To Control Navigation, Audio, And Video Functions/ Compatible With AVICN2 And AVICN1', 48.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony VAIO Neoprene Notebook With AC Adapter Case - Black Finish - VGPAMC2', 'Sony VAIO Neoprene Notebook With AC Adapter Case - VGPAMC2/ Helps Protect Your Notebook From Scratches, Spills And Dings/ Neoprene Offers Durable, Water-Resistant Protection/ Fits 17'' Widescreen Notebooks', 24.00); +INSERT INTO Product( title, description, price) VALUES ( 'NetGear ProSafe 24 Port Smart Switch - FS726TP', 'NetGear ProSafe 24 Port Smart Switch - FS726TP/ Two Gigabit Ports Plus Easy Browser/ ProSafe Network Management Software/ Web Based Smart Management Features', 605.00); +INSERT INTO Product( title, description, price) VALUES ( 'Garmin StreetPilot C330 Dash Mount - Black Finish - 0101061300', 'Garmin StreetPilot C330 Dash Mount - 0101061300/ Non-Skid Mount Design/ Fully Portable/ Includes 12/24 Volt Cigarette Lighter Adapter/ Black Finish', 57.00); +INSERT INTO Product( title, description, price) VALUES ( 'Yamaha High Performance Subwoofer - Black Finish - YSTFSW100BK', 'Yamaha High Performance Subwoofer - YSTFSW100BK/ 130 Watts Dynamic Power/ Advanced YST II (Yamaha Active Servo Technology)/ Half Pipe Port/ Powerful 6.5? Multi-Range Driver/ Magnetically Shielded/ 16Hz Ultra Low Frequency Reproduction/ Slim Design/ Black Finish', 150.00); +INSERT INTO Product( title, description, price) VALUES ( 'Netgear ProSafe 16 Port 10/100 Desktop Switch - Purple Finish - FS116P', 'Netgear ProSafe 16 Port 10/100 Desktop Switch - FS116P/ 16 Auto Speed-Sensing 10/100 RJ-45 Ports/ 96 KB Embedded Memory Per Unit', 299.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon High Capacity Color Ink Cartridge - Color Ink - CL51', 'Canon High Capacity Color Ink Cartridge - CL51/ Compatible With Pixma iP6210D, iP6220D, MP150, MP170 And MP450 Printers', 35.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Photo Ink Cartridge - CL52', 'Canon Photo Ink Cartridge - CL52/ Compatible With Pixma iP6210D And iP6220D Printers', 25.00); +INSERT INTO Product( title, description, price) VALUES ( 'Cuisinart Programmable Coffeemaker - Stainless Steel Finish - DCC2000', 'Cuisinart 12-Cup Programmable Coffeemaker - DCC2000/ Fully Programmable/ Removable Coffee Reservoir/ Easy-To-Read Coffee Gauge/ Visible Water Level Indicator/ Removable Drip Tray/ Charcoal Water Filter/ Stainless Steel Finish', 100.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus Center Channel Speaker Mount - Black Finish - VMCC1B', 'Sanus Center Channel Speaker Mount - VMCC1B/ Works With Sanus Models VMSA, VMAA18, VMAA26, VMDD26 And VMCM1/ Easy To Install/ Mounting Hardware Included/ Black Finish', 99.99); +INSERT INTO Product( title, description, price) VALUES ( 'Netgear RangeMax Wireless Access Point - White Finish - WPN802NA', 'Netgear RangeMax Wireless Access Point - WPN802NA/ Improves Performance Of Existing Legacy 802.11b And 802.11g Wireless Devices Up To 50 Percent/ Wired Equivalent Privacy (WEP) 64-Bit,128-Bit Encryption/ Wi-Fi Protected Access (WPA, Pre-Shared Key)', 130.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Q 300 Liquid Propane Outdoor Grill - 426001', 'Weber Q 300 Liquid Propane Outdoor Grill - 426001/ Liquid Propane Fuel Type/ Two Burners For Direct And Indirect Cooking/ Thermometer Built Into The Lid/ Regulator Hose/ 12-Pound Turkey Capacity/ Cart Included/ Cast Aluminum Finish/ Assembly Required', 349.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Lightweight Tripod - Black Finish - VCTR100', 'Sony Lightweight Tripod - VCTR100/ Lightweight And Portable/ Expands From 14'' To 39''/ 3-Way Panhead Function/ Black Finish', 34.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus VMAV Black VisionMount Component Wall Shelf VMAVB In Black - VMAVB', 'Sanus VMAV Black VisionMount Component Wall Shelf - VMAVB/ Single Wall Mount Shelf For Audio-Video Component/ Metal V Arm/ Black Finish', 34.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sony PlayStation 2 DUALSHOCK 2 Analog Controller - Emerald Finish - 711719706205', 'Sony PlayStation 2 DUALSHOCK 2 Analog Controller - 711719706205/ Analog Pressure Sensitivity On All Action Buttons/ Built-In DUALSHOCK Vibration Function/ Twin Analog Control Sticks/ Intelligent Self-Calibrating Analog System/ Emerald Finish', 24.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sony PlayStation 2 8MB Memory Card - Black Finish - 711719702702', 'Sony PlayStation 2 8MB Memory Card - 711719702702/ Save And Load High Scores, Positions And Replays/ MagicGate Encryption/ Black Finish', 24.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sony PlayStation 2 8MB Memory Card (2 Pack) - Red/Blue Finish - 711719706700', 'Sony PlayStation 2 8MB Memory Card (2 Pack) - 711719706700/ Save And Load High Scores, Positions And Replays/ MagicGate Encryption/ Red/Blue Finish', 34.99); +INSERT INTO Product( title, description, price) VALUES ( 'Universal RF Series MasterControl Remote Control - RF20', 'Universal RF Series MasterControl Remote Control ? RF20/ Control Up To 10 Components/ 432 MacroPower Buttons/ Customizable LCD Screen/ Pre-Programmed Codes/ Learning Capable/ SimpleSound/ Fully Backlit Keypad/ DVD Guide', 79.99); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic Network Camera - White Finish - BLC1A', 'Panasonic Network Camera - BLC1A/ Automatic Network Configuration/ Built-In Calendar Timer/ Auto Time Adjustment With NTP/ Up To 10x Digital Zoom/ Multi-Language Interface/ White Finish', 99.00); +INSERT INTO Product( title, description, price) VALUES ( 'Pioneer 6.5'' 2-Way Marine White Speakers - TSMR1640', 'Pioneer 6.5'' 2-Way Marine Speakers - TSMR1640/ 160 Watts Maximum Power Handling (30 Watts Nominal)/ 1-1/8'' Poly-Ether Imide Dome Tweeter With Magnetic Fluid And Equalizer/ Tinsel Lead Wire And Terminals Are Gold-Plated For Extra Protection', 120.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple USB Modem - White Finish - MA034ZA', 'Apple USB Modem - MA034ZA/ Supports Caller Wake On Ring, Telephone Answering (V.253), Modem On Hold/ V.92 Software Support', 54.00); +INSERT INTO Product( title, description, price) VALUES ( 'Linksys EtherFast 4124 24-Port Ethernet Switch - EF4124', 'Linksys EtherFast 4124 24-Port Ethernet Switch - EF4124/ 24 Autosensing 10/100 Full Duplex, Auto MDI/MDI-X Ports/ Up To 200Mbps/ Address Learning, Aging And Data Flow Control/ Compact Size', 119.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony DVD Remote Control For PS2 - Black Finish - 711719707608', 'Sony DVD Remote Control For PS2 - 711719707608/ Works As A Full-Featured Standard Controller/ Performs Audio Track Selection, Subtitle Display And Multiangle Options/ Designed To Match The Sleek Look Of PlayStation 2', 19.00); +INSERT INTO Product( title, description, price) VALUES ( 'Nikon 55-200MM Zoom-Nikkor Lens Accessory - 2156', 'Nikon 55-200MM Zoom-Nikkor Lens Accessory - 2156/ 3.6X Zoom/ 55 - 200MM/ Silent Wave Motor/ Two ED Glass Elements/ Focus Mode Switch', 199.00); +INSERT INTO Product( title, description, price) VALUES ( 'Waring Professional Cool-Touch Deep Fryer - Black/Stainless Steel Finish - DF100', 'Waring Professional Cool-Touch Deep Fryer - DF100/ Large Frying Basket/ 60-Minute Timer/ Removable Control Panel/ Unique Heating Element/ Breakaway Cord/ LED Power Indicators', 70.00); +INSERT INTO Product( title, description, price) VALUES ( 'Denon Fully Automatic Analog Turntable - DP300F', 'Denon Fully Automatic Analog Turntable - DP300F/ Removable Headshell/ Automatic Startup/ Built-In Phono Equalizer/ DC Servo Motor And Belt Drive System/ MM Cartridge', 329.00); +INSERT INTO Product( title, description, price) VALUES ( 'Terk Mini Tuner Cartridge For XM Ready Home Products - CNP2000', 'Terk Mini Tuner Cartridge For XM Ready Home Products - CNP2000/ Connects To Any Home Or Portable Audio Product With The XM Ready Logo', 29.00); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic Plain Paper Fax/Copier With Cordless Phone Answering System - Grey Finish - KXFG2451', 'Panasonic Plain Paper Fax/Copier With Cordless Phone Answering System - KXFG2451/ Automatic Fax/Phone Switching/ 2.4GHz GigaRange Cordless Handset With Handset Speakerphone/ Voice Enhancer Technology/ All-Digital Answering System (18 Min)/ Navigator Key With 2-Line Display', 119.00); +INSERT INTO Product( title, description, price) VALUES ( 'Omnimount Moda 2 Shelf Wall Furniture - MWFS', 'Omnimount Moda 2 Shelf Wall Furniture - MWFS/ Modular Design/ Integrated Cable Management/ Tempered Glass Shelves', 299.00); +INSERT INTO Product( title, description, price) VALUES ( 'Terk Mini Tuner Home Dock For XM Ready Home Products - Black Finish - CNP2000H', 'Terk Mini Tuner Home Dock For XM Ready Home Products - CNP2000H/ Comes Complete With The Docking Station, Protective Cover And A Window Sill Mount Antenna/ Interfaces To Existing And Future XM Ready Products', 30.00); +INSERT INTO Product( title, description, price) VALUES ( 'Denon 5-Disc CD Auto Changer - Black Finish - DCM290', 'Denon 5-Disc CD Auto Changer - DCM290/ CD-R/RW Playback/ Advanced Multilevel Noise Shaping DAC/ Digital Filter/ 3-Mode Random Playback/ Intelligent Disc Scan/ Music Calendar Display/ Black Finish', 249.00); +INSERT INTO Product( title, description, price) VALUES ( 'Denon 5 Disc CD Player - Black Finish - DCM390', 'Denon 5 Disc CD Player - DCM390/ CD-R/RW Playback/ MP3, WMA And HDCD Decoding/ Advanced Multilevel Noise Shaping DAC/ 8 Times Oversampling Digital Filter/ 3 Mode Random Playback/ Intelligent Disc Scan/ 20 Selection Music Calendar Display/ Black Finish', 349.00); +INSERT INTO Product( title, description, price) VALUES ( 'Denon Progressive Scan Universal DVD Player - DVD2930CI', 'Denon Progressive Scan Universal DVD Player - DVD2930CI/ AC 120 Volts/ 60 Hertz/ 45 Watts/ Infrared Pulse Remote Control', 849.00); +INSERT INTO Product( title, description, price) VALUES ( 'Netgear Prosafe 16 Port 10/100 Rackmount Switch - Black Finish - JFS516NA', 'Netgear Prosafe 16 Port 10/100 Rackmount Switch - JFS516NA/ Sixteen Switched Ports Provide Private Bandwidth For PCs, Servers Or Hubs/ Store-And-Forward Packet Switching/ Compatible With All Major Network Software/ Auto Detects Speed And Duplex/ Black Finish', 131.00); +INSERT INTO Product( title, description, price) VALUES ( 'Terk XM Outdoor Home Antenna - Grey Finish - XM6', 'Terk XM Outdoor Home Antenna - XM6/ Universal Mounting Roof, Wall Or Mast/ For Use With Single-Input Receivers/ Connects RG6 Cable For Easy Routing Up To 100 Ft. (Optimal Disatnce 75 Ft.)', 80.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus 9'' - 17'' VisionMount Series Under Cabinet Flat Panel TV Silver Wall Mount - VMUC1S', 'Sanus 9'' - 17'' VisionMount Series Under Cabinet Flat Panel TV Silver Wall Mount - VMUC1S/ Tilting Motion/ Swivels Left And Right/ Universal Mounting Bracket/ Easy To Install/ Silver Finish', 99.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus 15'' - 40'' VisionMount Flat Panel TV Black Wall Mount - MT25B1', 'Sanus 15'' - 40'' VisionMount Flat Panel TV Black Wall Mount - MT25B1/ Solid Heavy-Gauge Steel Construction/ Durable Powder-Coated Finish/ Virtual Axis Tilt Adjustment System/ Up to 100 Lbs Support/ Black Finish', 99.99); +INSERT INTO Product( title, description, price) VALUES ( 'Garmin GPS Carrying Case - Black Finish - 0101070400', 'Garmin GPS Carrying Case - 0101070400/ Protect Your GPS By Absorbing The Impact From Routine Drops/ Prevent Damage From Scratches And Spills', 30.00); +INSERT INTO Product( title, description, price) VALUES ( 'Tech Craft Avalon Series TV Stand - Black Finish - ABS32', 'Tech Craft Avalon Series TV Stand - ABS32/ 32'' Wide ''Tall Boy'' For Smaller Screen Flat Panels/ Molded Top Gives It An Elegant Appearance/ Framed Doors To Conceal Components/ Black Finish', 249.00); +INSERT INTO Product( title, description, price) VALUES ( 'Tech Craft Avalon Series TV Stand - SWP48', 'Tech Craft Avalon Series TV Stand - SWP48/ 48'' Wide Credenza For Flat Panel TVs And DLPs/ 260 Lbs TV Weight Capacity/ 50 Lbs Shelf Weight Capacity/ Wood Veneer Finish', 299.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus 15'' - 40'' VisionMount Flat Panel TV Black Wall Mount - MF110B', 'Sanus 15'' - 40'' VisionMount Flat Panel TV Black Wall Mount - MF110B/ Mounts Within 2.5'' Of Wall/ Holds Up To 100 Lbs/ Powder Coated Black Finish', 179.99); +INSERT INTO Product( title, description, price) VALUES ( 'Garmin Nuvi 360 010-10815-00 Black Replacement Vehicle Suction Cup Mount - 0101081500', 'Garmin Nuvi 360 010-10815-00 Black Replacement Vehicle Suction Cup Mount - 0101081500/ Compatible With The Nuvi 360/ It Is A Replacement/ Black Finish', 39.00); +INSERT INTO Product( title, description, price) VALUES ( 'Garmin Nuvi 360 010-10723-06 Black 12 Volt Adapter Cable - 0101072306', 'Garmin Nuvi 360 010-10723-06 Black 12 Volt Adapter Cable - 0101072306/ Compatible With The Nuvi 350 And 360/ It Is A Replacement/ Black Finish', 47.00); +INSERT INTO Product( title, description, price) VALUES ( 'Garmin Nuvi 660 010-10747-03 Black 12 Volt Adapter Cable - 0101074703', 'Garmin Nuvi 660 010-10747-03 Black 12 Volt Adapter Cable - 0101074703/ Compatible With The Nuvi 660/ Black Finish', 39.00); +INSERT INTO Product( title, description, price) VALUES ( 'Garmin 010-10702-00 Black GA 25MCX Remote GPS Antenna - 0101070200', 'Garmin 010-10702-00 Black GA 25MCX Remote GPS Antenna - 0101070200/ Built-In Magnetic Mount/ Includes A Cable Over 8 Feet Long And MCX Connector', 30.00); +INSERT INTO Product( title, description, price) VALUES ( 'Garmin 010-10823-00 Black Nuvi 660 Vehicle Suction Cup Mount - 0101082300', 'Garmin 010-10823-00 Black Nuvi 660 Vehicle Suction Cup Mount - 0101082300/ Replacement Suction Cup Mount/ Compatible With Nuvi 660/ Black Finish', 46.00); +INSERT INTO Product( title, description, price) VALUES ( 'Universal MRF-350 RF Black Base Station - MRF350', 'Universal MRF-350 RF Black Base Station - MRF350/ No More Pointing/ RF Addressable/ IR Routing/ Expand Operating Range Up To 100 Feet/ Compatible With MX-3000, TX-1000, MX-950 And MX-900 Only/ Black Finish', 250.00); +INSERT INTO Product( title, description, price) VALUES ( 'Bose In-Ear Black Headphones - BOSEIE', 'Bose In-Ear Black Headphones - BOSEIE/ Comfortable In-Ear Design/ TriPort Acoustic Headphone Structure/ S, M And L Removable Silicone Tips/ Carrying Case/ Black Finish', 99.95); +INSERT INTO Product( title, description, price) VALUES ( 'Nyko PlayStation 3 Dual Charger AC - 743840830153', 'Nyko PlayStation 3 Dual Charger AC - 743840830153/ Charge 2 Wireless PS3 Controllers From A Standard Wall Outlet/ Collapsable Prongs For Easy Storage/ Charges Other Mini USB Devices', 24.99); +INSERT INTO Product( title, description, price) VALUES ( 'Nyko PlayStation 3 ChargeLink USB Charging Cable - 743840830009', 'Nyko PlayStation 3 ChargeLink USB Charging Cable - 743840830009/ Charge And Play At The Same Time/ Unique Woven Cable Shielding Improves Cable Durability/ 10 Ft Cable', 14.99); +INSERT INTO Product( title, description, price) VALUES ( 'Linksys Wireless-G VPN Broadband Silver Router - WRV54G', 'Linksys Wireless-G VPN Broadband Silver Router - WRV54G/ Built-In VPN Endpoint Capability/ Securely Connect Up To 50 Remote Or Traveling Users To Your Office Network Via VPN/ Hotspot Ready With Subscriber Registration, Authorization And Authentication Functions/ Silver Finish', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'Bose SL2 Wireless Black Surround Link - SL2WIRELESS', 'Bose SL2 Wireless Black Surround Link - SL2WIRELESS/ Transmitter And Receiver Work On A Radio Frequency Signal Effective From Up To 30 Feet In The Same Room/ Compatible With All Lifestyle Systems, CD-Based Models And All 5.1-Channel Acoustimass Home Entertainment Systems/ Black Finish', 249.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Digital Photo Printer Paper 120 Pack - SVMF120P', 'Sony Digital Photo Printer Paper 120 Pack - SVMF120P/ 4'' x 6'' Print Paper With Snap-Off Edges/ Super Coat 2 Protective Lamination/ Water Damage And Fingerprint Resistant Prints/ 120 Sheets Of Paper And Print Ribbon/ For DPPF Series Digital Photo Printers Only', 35.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon PGI-5BK Black Ink Tank Cartridge - PGI5BK', 'Canon PGI-5BK Black Ink Tank Cartridge - PGI5BK/ Smudge Resistant/ Resists Smearing Caused By Highlighters/ Smudge Resistant/ Pigment Ink Formulation For Long Lasting Prints', 16.00); +INSERT INTO Product( title, description, price) VALUES ( 'Lowepro SlingShot 200 AW Digital Camera Back Pack - SLINGSHOT200AW', 'Lowepro SlingShot 200 AW Digital Camera Back Pack - SLINGSHOT200AW/ Holds A SLR With Attached Compact Zoom Lens Plus 3-4 Extra Lenses Or Flash Unit/ Water-Resistant Micro Fiber/ Ripstop Nylon/ Includes A Built-In Memory Card Puch, Micro Fiber LCD Cloth And Two Organizer Pockets', 89.95); +INSERT INTO Product( title, description, price) VALUES ( 'Tech Craft ABS48 Antique Black Avalon Series 48'' TV Stand - ABS48', 'Tech Craft ABS48 Antique Black Avalon Series 48'' TV Stand - ABS48/ For Flat Panels And DLP TV?s/ Molded Top And Shaped Skirt/ Framed Doors/ Antique Black Distressed Finish', 299.00); +INSERT INTO Product( title, description, price) VALUES ( 'Garmin 010-10723-03 Nuvi Suction Cup Mount - 0101072303', 'Garmin 010-10723-03 Nuvi Suction Cup Mount - 0101072303/ Replacement Suction Cup Mount/ Compatible With Garmin Nuvi 300/310/350/360 GPS System/ Black Finish', 39.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Stainless Steel Summit S-650 Liquid Propane Grill - 1780001', 'Weber Stainless Steel Summit S-650 Liquid Propane Grill - 1780001/ 6 Stainless Steel Burners/ 60,000 BTU-Per-Hour Input/ 12,000 BTU-Per-Hour Input Side Burner/ 10,600 BTU-Per-Hour Rotisserie Burner/ 8,000 BTU-Per-Hour Input Smoker Burner/ Snap-Jet Individual Burner Ignition System/ 3/8-Inch Diameter Stainless Steel Rod Cooking Grates/ Stainless Steel Flavorizer Bars/ Stainless Steel Finish/ Liquid Propane Model (LP Tank Not Included)/ Assembly Required', 1999.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Stainless Steel Genesis S-310 Liquid Propane Grill - 3770001', 'Weber Stainless Steel Genesis S-310 Liquid Propane Grill - 3770001/ 3 Stainless Steel Burners/ 42,000 BTU-Per-Hour Input/ Electronic Crossover Ignition System/ 7MM Diameter Stainless Steel Rod Cooking Grates/ Stainless Steel Flavorizer Bars/ Stainless Steel Finish/ Liquid Propane Model (LP Tank Not Included)/ Assembly Required', 899.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Stainless Steel Genesis S320 LP Grill - 3780001', 'Weber 3780001 Stainless Steel Genesis S-320 Liquid Propane Grill - 3780001/ 3 Stainless Steel Burners/ 42,000 BTU-Per-Hour Input/ 12,000 BTU-Per-Hour Input Side Burner/ Electronic Crossover Ignition System/ 7MM Diameter Stainless Steel Rod Cooking Grates/ Stainless Steel Flavorizer Bars/ Stainless Steel Finish/ Liquid Propane Model (LP Tank Not Included)/ Assembly Required', 949.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Stainless Steel Genesis S320 Natural Gas Grill - 3880001', 'Weber Stainless Steel Genesis S-320 Natural Gas Grill - 3880001/ 3 Stainless Steel Burners/ 42,000 BTU-Per-Hour Input/ 12,000 BTU-Per-Hour Input Side Burner/ Electronic Crossover Ignition System/ 7MM Diameter Stainless Steel Rod Cooking Grates/ Stainless Steel Flavorizer Bars/ Stainless Steel Finish/ Natural Gas Model/ Assembly Required', 969.00); +INSERT INTO Product( title, description, price) VALUES ( 'Kenwood KCA-IP300V iPod Video Direct Cable - KCAIP300V', 'Kenwood KCA-IP300V iPod Video Direct Cable - KCAIP300V/ iPod Video Direct Cable For DNX7100, DDX7019 And KVT719DVD Indash Monitors', 49.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sony SCPH-98046 PlayStation 3 Blu-Ray DVD Remote Control - 711719804604', 'Sony SCPH-98046 PlayStation 3 Blu-Ray DVD Remote Control - 711719804604/ Full Access To The PlayStation 3 Systems Disc Features/ Can Be Used Without Having To Point Directly At The System', 24.99); +INSERT INTO Product( title, description, price) VALUES ( 'Tripp-Lite PV375 PowerVerter 375-Watt Ultra-Compact Inverter - PV375', 'Tripp-Lite PV375 PowerVerter 375-Watt Ultra-Compact Inverter - PV375/ 12V DC Input/ 120V AC Output/ 2 Outlets/ 375 Watts Continuous Output/ 600 Watts Peak Output/ Convenient Cigarette Lighter Plug', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sirius FMDA25 Wired FM Modulation Relay - FMDA25', 'Sirius FMDA25 Wired FM Modulation Relay - FMDA25/ 2 Ft FM Antenna Cable/ 19 Ft 4 In Mini-Jack Cable', 20.00); +INSERT INTO Product( title, description, price) VALUES ( 'Electrolux Oxygen 3 Canister HEPA H12 Filter - EL012A', 'Electrolux Oxygen 3 Canister HEPA H12 Filter - EL012A/ Retains 99.5% Of Dust And Other Irritants/ 1 Filter Per Package', 19.99); +INSERT INTO Product( title, description, price) VALUES ( 'Fellowes Confetti Cut Shredder - W11C', 'Fellowes Confetti Cut Shredder - W11C/ Shreds Up To 11 Sheets Per Pass/ Safely Shreds Staples And Credit Cards/ 9'' Paper Entry Accepts Any Standard Or Legal Size Document/ Safety Interlock Switch Automatically Powers Off When Shredder Head Is Lifted', 79.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony VAIO VGP-PRSZ1 SZ Series Docking Station - VGPPRSZ1', 'Sony VAIO VGP-PRSZ1 SZ Series Docking Station - VGPPRSZ1/ Compatible With SZ Series Notebooks/ Expand Connectivity To Your Notebook/ 3 USB 2.0, Gigabit Ethernet, VGA, DVI-D And DC In/ Black Finish', 199.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Genesis E-310 Liquid Propane Black Outdoor Grill - 3741001', 'Weber Genesis E-310 Liquid Propane Black Outdoor Grill - 3741001/ 3 Stainless Steel Burners/ 42,000 BTU Per-Hour Input/ Electronic Crossover Ignition System/ Porcelain Enameled Cast Iron Cooking Grates/ 2 Stainless Steel Work Surfaces/ Center Mounted Thermometer/ Cast Aluminum End Caps/ Black Finish/ Liquid Propane Model (LP Tank Not Included)/ Assembly Required', 699.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Genesis S-310 Natural Gas Stainless Steel Outdoor Grill - 3870001', 'Weber Genesis S-310 Natural Gas Stainless Steel Outdoor Grill - 3870001/ 3 Stainless Steel Burners/ 42,000 BTU-Per-Hour Input/ Electronic Crossover Ignition System/ Center Mounted Thermometer/ Cast Aluminum End Caps/ 2 Heavy Duty Front Locking Casters/ Stainless Steel Finish/ Assembly Required', 919.00); +INSERT INTO Product( title, description, price) VALUES ( 'DeLonghi Magnifica Super-Automatic Espresso/Coffee Machine - ESAM3300', 'DeLonghi Magnifica Super-Automatic Espresso/Coffee Machine - ESAM3300/ Stainless-Steel Removable Double Boiler/ Instant Reheat/ Removable Water Tank And Bean Container/ Integrated Burr Grinder/ Cappuccino System/ Cup Tray/ Silver Finish', 799.95); +INSERT INTO Product( title, description, price) VALUES ( 'Yamaha Silver USB Powered Stereo Speaker - NXU10SIL', 'Yamaha NX-U10 Silver USB Powered Stereo Speaker - NXU10SIL/ 20 Watts Output Power/ PowerStorage Circuit/ SR-Bass (Swing Radiator Bass) Technology/ Magnetic Shielding/ Mac And Windows Compatible/ Silver Finish', 180.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon FAX-JX200 Inkjet Fax Machine - FAXJX200', 'Canon FAX-JX200 Inkjet Fax Machine - FAXJX200/ Automatic Document Feeder/ Produce B&W Copies With Clear, Sharp Text/ One-Touch Dialing/ Ultra-High Quality (UHQ) Image Processing Technology/ 600 x 600 Dpi Copy Resolution/ White Finish', 78.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Genesis E-310 Natural Gas Black Outdoor Grill - 3841001', 'Weber Genesis E-310 Natural Gas Black Outdoor Grill - 3841001/ 3 Stainless Steel Burners/ 42,000 BTU Per-Hour Input/ Electronic Crossover Ignition System/ Porcelain Enameled Cast Iron Cooking Grates/ 2 Stainless Steel Work Surfaces/ Center Mounted Thermometer/ Cast Aluminum End Caps/ Black Finish/ Assembly Required', 719.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber 3758301 Blue Genesis EP-320 LP Gas Grill - 3758301', 'Weber 3758301 Blue Genesis EP-320 LP Gas Grill - 3758301/ 3 Seamless Stainless Steel Burners/ 42,000 BTU-Per-Hour Input/ Crossover Ignition System/ Stainless Steel Flavorizer Bars And Grates/ Cast Aluminum End Caps/ Centermounted Thermometer/ Blue Finish/ Liquid Propane Model (LP Tank Not Included)/ Assembly Required', 749.00); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic KX-TG6702B 5.8 GHz FHSS GigaRange Expandable Black Cordless Phone System - KXTG6702B', 'Panasonic KX-TG6702B 5.8 GHz FHSS GigaRange Expandable Black Cordless Phone System - KXTG6702B/ All-Digital Answering System/ LCD Call Counter/ Speakerphone/ Navigator Key/ Up To 8 Handsets With Just One Phone Jack/ Line Status Indicator/ Voice Scramble/ Handset Locator/ Volume Control/ Black Finish', 197.00); +INSERT INTO Product( title, description, price) VALUES ( 'Fellowes MicroShred Shredder - MS450CS', 'Fellowes MS-450CS MicroShred Shredder - MS450CS/ 4.5 Gallons Basket Capacity/ Can Shred Paper, CDs, Credit Cards, Staples, Paper Clips/ Motor Reverse/ Interlock Switch/ Safe Sense/ 7 Sheet Capacity', 189.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony MRW62E/S1/181 17-In-1 External USB Memory Card Reader - MRW62ES1181', 'Sony MRW62E/S1/181 17-In-1 External USB Memory Card Reader - MRW62ES1181/ Supports 17 Different Memory Card Formats/ Works With Macintosh And Windows Computers/ Easy Hi-Speed USB 2.0 Connection/ Black Finish', 29.00); +INSERT INTO Product( title, description, price) VALUES ( 'Griffin Elevator Brushed Aluminum Laptop Stand - 1093CURV2', 'Griffin Elevator Brushed Aluminum Laptop Stand - 1093CURV2/ Elevates Laptop Screen 5.5'' While Providing Valuable Desktop Real Estate For Your Keyboard And Mouse/ Keeps Laptop Cool With 360 Degrees Of Air Circulation/ Compatible With Mac Or PC Laptop', 39.00); +INSERT INTO Product( title, description, price) VALUES ( 'Escort Passport 9500I Radar And Laser Detector - 9500I', 'Escort Passport 9500I Radar And Laser Detector - 9500I/ 360-Degree Radar And Laser Detection/ Blistering All-Band Protection/ GPS-Powered Truelock Filter/ Immune To The VG-2 ''Detector-Detector''/ Built-In Earphone Jack/ Red Display', 449.95); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic Countertop Microwave Oven In Black - NNSN667BK', 'Panasonic NN-SN667B Countertop Microwave Oven In Black - NNSN667BK/ 1.2 Cubic Foot/ 1300 Watts High Power/ 10 Power Levels/ 5 Cooking Stages/ Quick Minute/ One-Touch Sensor Cooking/ Inverter Turbo Defrost/ Multi-Lingual Menu Action Screen/ Popcorn Key/ Black Finish', 129.00); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic Countertop Microwave Oven In White - NNSN667WH', 'Panasonic NN-SN667W Countertop Microwave Oven In White - NNSN667WH/ 1.2 Cubic Foot/ 1300 Watts High Power/ 10 Power Levels/ 5 Cooking Stages/ Quick Minute/ One-Touch Sensor Cooking/ Inverter Turbo Defrost/ Multi-Lingual Menu Action Screen/ Popcorn Key/ White Finish', 129.00); +INSERT INTO Product( title, description, price) VALUES ( 'Samsung DLP TV Stand In Black - TR72BX', 'Samsung DLP TV Stand In Black - TR72BX/ Designed To Fit Samsung HLT7288 HLT7288, HL72A650, and HL67A650 Television Sets/ Tempered 6mm Tinted Glass Shelves/ Wide Audio Storage Shelves To Accommodate 4 Or More Components/ Wire Management System/ Easy To Assemble/ High Gloss Black Finish', 369.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Black Active Speaker System - SRSA212BK', 'Sony Black Active Speaker System - SRSA212BK/ Designed For Your Portable Audio Or PC/ Built-In Mega Bass/ On/Off Switch With Volume Control/ Magnetically Shielded/ Black Finish', 29.00); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic Expandable Digital Cordless DECT 6.0 Handset In Silver - KXTGA101S', 'Panasonic Expandable Digital Cordless DECT 6.0 Handset In Silver - KXTGA101S/ Expansion Handset And Charger Select 1000 Series Phone Systems/ Big Buttons/ Built-In Clock With Alarm/ Silver Finish', 39.00); +INSERT INTO Product( title, description, price) VALUES ( 'Tech Craft Dark Cherry Veneto Series TV Stand - SWP60', 'Tech Craft Dark Cherry Veneto Series TV Stand - SWP60/ 60'' Wide Credenza For Flat Panel TV?s And DLP?s/ Center Channel Compartment And Storage/ 260 Lbs TV Capacity/ 50 Lbs Shelf Capacity/ Dark Cherry Wood Veneer Finish', 399.00); +INSERT INTO Product( title, description, price) VALUES ( 'Haier 13'' Silver Tube TV - HTR13', 'Haier 13'' Silver Tube TV - HTR13/ Built-In Atsc/Ntsc Tuner/ Video Noise Reduction/ Multi Picture Modes/ Multilingual Display/ Digital Comb Filter/ Component Video Input/ Front AV Jacks/ Silver Finish', 124.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Memory Stick USB Adaptor - MSACUS40', 'Sony Memory Stick USB Adaptor - MSACUS40/ Quickly Transfer Image And Data To A PC/ Transfer Speed Up To 80Mbps/ Compatible With All Memory Stick Media', 29.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Clip-On Black Headphones - MDRQ68LW', 'Sony Clip-On Black Headphones - MDRQ68LW/ Lightweight And Thin Body For Stable Fitting/ Retractable Silent Cord/ 3.3 Ft. Cord/ Gold Plated Mini-Plug/ Black Finish', 29.00); +INSERT INTO Product( title, description, price) VALUES ( 'Netgear ProSafe 24-Port Smart Switch - GS724TP', 'Netgear ProSafe 24-Port Smart Switch - GS724TP/ 24 10/100/1000 Ports That Support 802.3af PoE/ 2 Combo Gigabit Copper/SFP Slots/ Web-Based Configuration/ Password Access Control/ Purple Finish', 780.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sharp Over The Counter White Microwave Oven - R1211WH', 'Sharp Over The Counter White Microwave Oven - R1211WH/ 1.5 Cu. Ft. Capacity/ 1100 Watts/ 19 Automatic Settings/ 2-Color Lighted LCD/ Smart And Easy Sensor Settings/ Auto-Touch Control Panel/ White Finish', 269.00); +INSERT INTO Product( title, description, price) VALUES ( 'Monster iFreePlay Cordless Headphones For iPod Shuffle - AISHHPHONE', 'Monster iFreePlay Cordless Headphones For iPod Shuffle - AISHHPHONE/ Wrap-Around Design With No Need For Clips, Armbands Or Pockets/ Easy Access To All iPod Shuffle Controls/ Folds For Compact Storage/ Black With Silver Finish', 48.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Black Ink Cartridge - PG50', 'Canon Black Ink Cartridge - PG50/ Pigment Ink Formulation For Long Lasting Prints/ Resists Smearing Caused By Highlighters/ Smudge Resistant/ Ink Remaining Notification Technology/ Crisp Laser Text-Quality Text/ Black Ink', 29.00); +INSERT INTO Product( title, description, price) VALUES ( 'Audiovox Xpress XM Satellite Radio FM Direct Adapter - XMFM1', 'Audiovox Xpress XM Satellite Radio FM Direct Adapter - XMFM1/ Switches Between FM Radio Antenna And Your XM Satellite Radio Receiver', 25.00); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic NNSD797S Stainless Steel Countertop Microwave Oven - NNSD797SS', 'Panasonic NNSD797S Stainless Steel Countertop Microwave Oven - NNSD797SS/ 1.6 Cu. Ft. Capacity/ 1250W Output Power/ 10 Power Levels/ 5 Cooking Stages/ One-Touch Sensor Cooking Or Heating/ Timer/ Stainless Steel Finish', 199.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple Mac Mini 1.83GHz Intel Core 2 Duo Computer - MB138LLA', 'Apple Mac Mini 1.83GHz Intel Core 2 Duo Computer - MB138LLA/ 1.83GHz Intel Core 2 Duo/ 1GB Memory/ 80GB Hard Drive/ 24x Combo Drive/ Built-In Speakers/ Four USB 2.0 Ports And One FireWire 400 Port/ Mac OS X v10.5 Leopard', 599.00); +INSERT INTO Product( title, description, price) VALUES ( 'Denon 7.1 Channel Home Theater MultiMedia A/V Receiver With Networking And WiFi - AVR4308CI', 'Denon 7.1 Channel Home Theater MultiMedia AV Receiver With Networking And WiFi In Black - AVR4308CI/ 140 Watts x 7 Channels/ Wi-Fi And Network Capable/ Worlds First Vista Certified Receiver/ HD Radio And XM Ready Tuning/ Dolby TrueHD And DTS-HD Master Audio/ DDSC-HD Digital Dynamic Discrete Surround Circuitry/ Expanded HDMI v1.3a Ports/ Dual Remotes/ Black Finish', 2699.00); +INSERT INTO Product( title, description, price) VALUES ( 'Denon 7.1 Channel Home Theater MultiMedia A/V Receiver With Networking In Black - AVR3808CI', 'Denon 7.1 Channel Home Theater MultiMedia AV Receiver With Networking In Black - AVR3808CI/ 130 Watts x 7 Channels/ Fully Assignable Channels For Bi-Amping/ Rear Panel RS-232C And Ethernet Ports/ Network Capable/ XM Ready Tuning/ Dolby TrueHD And DTS-HD Master Audio/ Expanded HDMI v1.3a Ports/ Dual Remotes/ Black Finish', 1699.99); +INSERT INTO Product( title, description, price) VALUES ( 'Denon X-Space Surround Bar Home Theatre System In Black - DHTFS3', 'Denon X-Space Surround Bar Home Theatre System In Black - DHTFS3/ 22 Watts x 5 (6 Ohms)/ Supports All Audio Formats (Dolby Digital, DTS, Dolby Pro Logic II)/ Slim Design/ Includes Dolby Headphones/ Included Subwoofer Features One-Touch Connection/ Remote Control/ Black Finish', 1199.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple Wireless Mighty Mouse - MB111LLA', 'Apple Wireless Mighty Mouse - MB111LLA/ Bluetooth Technology/ Laser Tracking Engine/ 360-Degree Innovative Scroll Ball And Button/ Touch-Sensitive Top Shell/ Force-Sensing Side Buttons/ Customizable/ White Finish', 69.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony PSP 2000 Playstation Portable Gaming System Core 98510 In Piano Black - 711719851004', 'Sony PSP 2000 Playstation Portable Gaming System Core 98510 In Piano Black - 711719851004/ Play Games, Watch Movies On UMD Discs, And Listen To Music All In One Device/ 4.3'' LCD Screen (16:9)/ 480 x 272 Pixel/ Wi-Fi (IEEE 802.11b) For Wireless Networking With Other PSP Owners/ Memory Stick PRO Duo/ 333MHz System Clock Frequency/ Piano Black Finish', 185.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple Mini-DVI To DVI Adapter - M9321GB', 'Apple Mini-DVI To DVI Adapter - M9321GB/ Compatible With iMac (Intel Core Duo), MacBook And 12'' PowerBook G4/ Connects To An External DVI Monitor Or Projector/ White Finish', 19.00); +INSERT INTO Product( title, description, price) VALUES ( 'Olympus DS40 Digital Voice Recorder - DS40R', 'Olympus DS40 Digital Voice Recorder - DS40R/ 136 Hours 15 Minutes Recording Time In LP Mode/ High-Sensitivity Detachable Stereo Microphone/ Voice Guidance/ Three Modes Of Microphone Sensitivity/ Built-In Variable Control Voice Actuator (VCVA) Function/ Up To 32 Hours Of Continuous Operation', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'Bose Lifestyle 48 Series IV 43479 Home Entertainment System - LS48IVWH', 'Bose Lifestyle 48 Series IV Home Entertainment System - LS48IVWH/ ADAPTiQ Audio Calibration System/ Acoustimass Module/ Jewel Cube Speakers/ Direct/Reflecting Speaker Technology/ VS-2 Video Enhancer/ Proprietary Videostage 5 Decoding Circuitry/ Digital 5.1 Decoding/ Control Integration/ White Finish', 3999.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Black DVD Recorder And VHS Combo Player - RDRVXD655', 'Sony Black DVD Recorder And VHS Combo Player - RDRVXD655/ Multiformat DVD Compatible/ HDMI Output And 720p/1080i Upscaling/ HDTV Tuner/ 4 Video Head Stereo VHS With 19 Micron Heads/ Variable Bit Rate Recording (7 Speeds)/ Progressive Scan Playback/ Dolby Digital And DTS Decoding Playback Compatible/ TV Virtual Surround/ Black Finish', 319.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple 1GB Silver iPod Shuffle - MB225LLA', 'Apple 1GB Silver 2nd Generation iPod Shuffle - MB225LLA/ Holds Up To 240 Songs/ 12 Hours Of Continuous Playback/ Skip-Free Playback/ Battery Indicator/ Shuffle Switch/ Built-In Clip/ Mac And Windows Compatible/ MB226LLA/ Silver Finish', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'GE 24'' GSD2400NWW White Built-In Dishwasher - GSD2400WH', 'GE 24'' GSD2400NWW White Built-In Dishwasher - GSD2400WH/ 4-Level PowerScrub Wash System/ HotStart Option/ Piranha Hard Food Disposer/ Heated Dry Option/ Self-Cleaning Filter System/ White Finish', 259.00); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic Expandable Digital Cordless DECT 6.0 Phone System - KXTG1032S', 'Panasonic Expandable Digital Cordless DECT 6.0 Phone System - KXTG1032S/ Up To 17 Hours Of Talk Time/ Expandable Up To 6 Handsets/ Up To 3-Way Conference Capability/ Light-Up Indicator With Ringer/Message Alert/ Backlit LCD On Handset/ Digital Speakerphone/ 16-Minute All-Digital Answering System/ Silver Finish', 69.00); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic 2 Line Integrated Corded Phone System - KXTSC14B', 'Panasonic 2 Line Integrated Corded Phone System - KXTSC14B/ 3-Line LCD Display/ Automatic Line Selection/ Call Waiting Caller ID/ 3-Way Conferencing/ Speakerphone/ Navigator Key/ Black Finish', 74.00); +INSERT INTO Product( title, description, price) VALUES ( 'Audiovox XpressEZ XM Satellite Radio Receiver - XMCK5P', 'Audiovox XpressEZ XM Satellite Radio Receiver - XMCK5P/ 10 Programmable Channels/ Universal Connector/ 3-Line Screen Display/ Plug & Play Dock/ Black Finish', 69.99); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic Integrated White Telephone System With All-Digital Answering System - KXTS620W', 'Panasonic Integrated White Telephone System With All-Digital Answering System - KXTS620W/ 2-Way Recording/ Call Waiting Caller ID/ Speakerphone/ 3-Line LCD/ Data Port/ Ringer Indicator Lamp/ Programmable Tone/Pulse/ Wall Mountable/ White Finish', 69.00); +INSERT INTO Product( title, description, price) VALUES ( 'Tech Craft Veneto Series Black TV Stand - ABS60BK', 'Tech Craft Veneto Series Black TV Stand - ABS60BK/ Supports Up To A 60'' Flat Panel TV/ Molded Top Gives It An Elegant Appearance/ Framed Doors To Conceal Components/ 200 Lbs Top Shelf Capacity/ Black Finish', 399.00); +INSERT INTO Product( title, description, price) VALUES ( 'Skagen Premium Steel Slimline Mesh Womens Watch - 233XSGG', 'Skagen Premium Steel Slimline Mesh Womens Watch - 233XSGG/ Stainless Steel Mesh Band/ Elegant Round Case/ Mother-Of-Pearl Dial/ Chrome Indicators', 110.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Color Image Silver Scanner - 8800F', 'Canon Color Image Silver Scanner - 8800F/ Resolution Of Up To 4800 x 9600 Color Dpi/ Enhance Old Photos/ Auto-Image Fix/ USB 2.0 Interface/ Multi-Image Scanning/ Windows And Mac Compatible/ Silver Finish', 199.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Black LocationFree Base Station - LFV30', 'Sony Black LocationFree Base Station - LFV30/ Watch TV Wherever You Are/ Compatible With PC Or PSP System/ Programmable On-Screen Home Remote/ Stream Outside Your Home/ User-Friendly/ Black Finish', 199.00); +INSERT INTO Product( title, description, price) VALUES ( 'Linksys Wireless-G Broadband Router - WRT54GL', 'Linksys Wireless-G Broadband Router - WRT54GL/ All-In-One Internet-Sharing Router/ 4-Port Switch/ Push Button Setup Feature/ TKIP And AES Encryption/ Wireless MAC Address Filtering/ Powerful SPI Firewall/ 54Mbps Wireless-G (802.11g) Access Point', 79.00); +INSERT INTO Product( title, description, price) VALUES ( 'Universal RF Base Station - MRF260', 'Universal RF Base Station - MRF260/ Extends The Reception Range Up To 100 Feet Away Through Walls, Floors, Doors, Indoors Or Outdoors/ Programmed To Operate Equipment At Up To 15 Locations/ Black Finish', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'Chestnut Hill Sound George iPod Music System In White - CHS4001', 'Chestnut Hill Sound George iPod Music System In White - CHS4001/ Playback System For The iPod/ Full Feature Wireless Remote/ Charging Stand Kit/ Bandless AM/FM Radio/ Easy Set Alarm/ Detachable Front Panel/ White Finish/ iPod Sold Separately', 499.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Universal Remote Control - RMEZ4', 'Sony Universal Remote Control - RMEZ4/ Easy-To-Use Simplified Functions/ Controls TV And Cable Box/ Compatible With Most Of Major Brands/ Large Buttons For Easy Operation/ 3-Minute Memory Backup/ Comfortable Ergonomic Design/ Silver Finish', 16.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sirius SiriusConnect Home Tuner - SCH1', 'Sirius SiriusConnect Home Tuner - SCH1/ Compact Size/ Analog And Digital Audio Outputs/ Display Indicators/ Connects To Any Sirius-Ready Home Audio Component', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus 15'' - 32'' Flat Panel TV Black Wall Mount - MF209B1', 'Sanus 15'' - 32'' Flat Panel TV Black Wall Mount - MF209B1 - MF209B1/ Supports Up To 60 lbs/ Easy To Install/ Virtual Axis 3D Tilting System/ Black Finish', 96.00); +INSERT INTO Product( title, description, price) VALUES ( 'Yamaha High Performance Subwoofer In Black - YSTFSW150BK', 'Yamaha High Performance Subwoofer In Black - YSTFSW150BK/ 130 Watts Dynamic Power/ Advanced YST II (Yamaha Active Servo Technology)/ Linear Port/ Powerful 6.5? Multi-Range Driver/ Magnetically Shielded/ 30 -150 Hz Low Frequency Response/ Down-Firing Active Design/ Best Matching For Front Surround Systems And Micro Component Systems/ Black Finish', 279.00); +INSERT INTO Product( title, description, price) VALUES ( 'Kenwood Sirius Radio Translator For In-Dash Head Units - KCASR50', 'Kenwood Sirius Radio Translator For In-Dash Head Units - KCASR50/ Provides Full Control Of The SIRIUS Radio/ Displays Text On The Stereo And Supplies Power To The Satellite Radio', 60.00); +INSERT INTO Product( title, description, price) VALUES ( 'Linksys Wireless-G PrintServer - WPSM54G', 'Linksys Wireless-G PrintServer - WPSM54G/ Share A Multifunction Printer With Everyone On Your Network (Works With Most USB Printers)/ Allows Full Access To Printing, Faxing, Scanning And Copying Functions/ Connects Your Printer Directly To The Network By 10/100 Wired Ethernet Or 54Mbps Wireless-G', 99.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sirius STILETTO 2 Home Docking Kit - SLH2', 'Sirius STILETTO 2 Home Docking Kit - SLH2/ Stereo Audio Output Connects With Home Audio System Or Speakers/ Headphone Jack/ PC Sync/ Compatible With Stiletto 2 Radios/ Charges Stiletto 2 While Docked/ Black Finish', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'Microsoft Office Standard 2007 - 02107746', 'Microsoft Office Standard 2007 - 02107746/ Create Documents Faster, More Easily And More Intuitively/ Automatic Document Recovery Tool/ Document Inspector/ Online Tutorials With Step-By-Step Instructions/ Compatible With Windows Vista, Windows XP SP2 And Windows Server 2003 SP1', 399.00); +INSERT INTO Product( title, description, price) VALUES ( 'Jabra Black Bluetooth Headset - BT5010', 'Jabra Black Bluetooth Headset - BT5010/ Up To 10 Hours Of Talk Time And 300 Hours Of Stand-By/ Wind-Noise Reduction Technology/ Vibrating And Visual Alerts/ Colored LED Indicator/ Up To 33-Foot Wireless Range/ Black Finish', 79.00); +INSERT INTO Product( title, description, price) VALUES ( 'Kensington Orbit Optical Trackball Mouse - 64327', 'Kensington Orbit Optical Trackball Mouse - 64327/ DiamondEye Optical Technology For Precise Tracking And Cursor Control/ USB And PS/2 Connectivity For Greater Compatibility/ Windows And Mac Compatible/ Metallic Silver And Black Finish', 38.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sirius Stiletto 2 Vehicle Kit - SLV2', 'Sirius Stiletto 2 Vehicle Kit - SLV2/ Designed For Use With The Sirius Stiletto 2/ Get Direct One-Touch Access To Traffic And Weather/ Built-In FM Transmitter To Play Satellite Radio Through Your Cars Audio System', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'Denon Networked Audio System With Built-In iPod Dock - S32', 'Denon Networked Audio System With Built-In iPod Dock - S32/ Stream Music Wirelessly/ Buit-In Dock For iPod On Top/ Ability To Decode MP3 And WMA Formats/ High Contrast Graphic LCD/ Multi-Task Jog Wheel On Top/ Built-In Speakers/ Clock With 2 Alarms With Auto Clock Set & Adjust Via Internet/ FM/AM Radio/ WiFi Certified/ Remote Control/ Black Finish', 499.00); +INSERT INTO Product( title, description, price) VALUES ( 'Motorola Portable Bluetooth Car Kit Speaker Phone - T305', 'Motorola Portable Bluetooth Car Kit Speaker Phone - T305/ 2.0 Bluetooth Wireless Technology/ Noise Cancellation Technology/ Loud Sound High Speaker Output/ Convenient Multi-Function Button/ Up To 14 Hours Of Talk Time And 14 Days Of Standby Time/ Mini-USB Connector/ Black Finish', 69.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony HD-Handycam 3 Meters (10 Feet) HDMI Mini Cable - VMC30MHD', 'Sony HD-Handycam 3 Meters (10 Feet) HDMI Mini Cable - VMC30MHD/ Gold Plating Plug/ HDMI-Compliant High Speed Category 2 Cable/ Support Full HD 1080p/ Digital Audio Transfer/ 3 Meters(10 Feet)/ Black Finish', 69.00); +INSERT INTO Product( title, description, price) VALUES ( 'Klipsch Black Wireless iPod Speaker - ROOMGROOVE', 'Klipsch Black Wireless iPod Speaker - ROOMGROOVE/ Wirelessly Sends CD-Quality Music To/From Other RoomGrooves/ Retractable Dock Charges iPods With 30-Pin Connectors/ Horn-Loaded Technology For Precise High Tones/ Dual High-Output Woofers Deliver Room-Filling Bass/ Black Finish', 299.00); +INSERT INTO Product( title, description, price) VALUES ( 'Logitech QuickCam Communicate STX - 961464', 'Logitech QuickCam Communicate STX - 961464/ 640 x 480 Video Capture/ 1.3 Megapixel Still Image Capture/ Built-In Microphone With RightSound Technology/ 30 Frames Per Second/ Adjustable Base Fits Any Monitor Or Notebook/ USB 2.0 Certified', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sirius Plug And Play Universal Home Kit - SUPH1', 'Sirius Plug And Play Universal Home Kit - SUPH1/ Compatible With All Of The Newest SIRIUS Plug & Play Radios/ Stereo Audio Output For Use Your Home Audio System Or Powered Speakers/ Sleek Compact Design/ High Gloss Black Finish', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'Belkin Hi-Speed USB 2.0 7-Port Hub - F5U237APLS', 'Belkin Hi-Speed USB 2.0 7-Port Hub - F5U237APLS/ Transfers Data Up To 480Mbps/ Installs Easily With Plug-And-Play Convenience/ Works Seamlessly With All USB 1.1 And USB 2.0 Devices/ Over-Current Detection And Safety/ Mac And PC Compatible/ Silver Finish', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'Netgear Wireless Access Point - WG102', 'Netgear Wireless Access Point - WG102/ High-Speed IEEE 802.11g, Up To 108 Mbps In Turbo Mode/ Wi-Fi Protected Access (WPA 802.11i-Ready Security)/ Integrated IEEE 802.3af Power Over Ethernet (PoE)/ Block SSID Broadcast/ VPN Pass-Through Support', 186.00); +INSERT INTO Product( title, description, price) VALUES ( 'Logitech diNovo Media Desktop Laser Keyboard And Mouse Combo - 967562', 'Logitech diNovo Media Desktop Laser Keyboard And Mouse Combo - 967562/ Unique Ultra-Flat Keyboard/ Detached Customizable MediaPad/ Precision Rechargeable Laser Mouse/ Tilt Wheel Plus Zoom/ Customizable Hotkeys/ Dedicated Search Buttons/ Bluetooth Wireless Technology Compatible/ Black And Gray Finish', 199.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple 500GB Time Capsule Wireless Hard Drive - MB276LLA', 'Apple 500GB Time Capsule Wireless Hard Drive - MB276LLA/ 500GB 7200-rpm Serial ATA Server-Grade Hard Disk Drive/ Up To 5x The Performance And 2x The Range With 802.11n/ Wi-Fi Protected Access (WPA/WPA2)/ Wireless Security (WEP) Configurable For 40-Bit And 128-Bit Encryption/ NAT Firewall/ AirPort Utility For Mac And Windows', 299.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple 1TB Time Capsule Wireless Hard Drive - MB277LLA', 'Apple 1TB Time Capsule Wireless Hard Drive - MB277LLA/ 1TB 7200-rpm Serial ATA Server-Grade Hard Disk Drive/ Up To 5x The Performance And 2x The Range With 802.11n/ Wi-Fi Protected Access (WPA/WPA2)/ Wireless Security (WEP) Configurable For 40-Bit And 128-Bit Encryption/ NAT Firewall/ AirPort Utility For Mac And Windows', 499.00); +INSERT INTO Product( title, description, price) VALUES ( 'Garmin Nuvi Portable Friction Mount - 0101090800', 'Garmin Nuvi Portable Friction Mount - 0101090800/ No Installation Required/ Securely Mounts Your GPS To A Surface In Your Car/ Works With All Garmin Nuvi Portable GPS Units/ Black Finish', 39.00); +INSERT INTO Product( title, description, price) VALUES ( 'Garmin Vehicle Suction Cup Mount - 0101093600', 'Garmin Vehicle Suction Cup Mount - 0101093600/ No Installation Required/ Securely Mounts Your GPS To Dash/ Black Finish', 25.00); +INSERT INTO Product( title, description, price) VALUES ( 'Garmin Suction Cup Mount And 12-Volt Adapter Kit - 0101097900', 'Garmin Suction Cup Mount And 12-Volt Adapter Kit - 0101097900/ Suction Cup Mount And 12-Volt Adapter Included', 30.00); +INSERT INTO Product( title, description, price) VALUES ( 'Pioneer Remote Control With DVD/Audio Controls - CDR55', 'Pioneer Remote Control With DVD/Audio Controls - CDR55/ Hands-Free Wireless Control/ Quick Access For Functions/ Compatible With AVH-P5000DVD, AVH-P4000DVD, AVIC-N4, AVIC-D3, AVH-P4900DVD And AVH-P5900DVD', 19.00); +INSERT INTO Product( title, description, price) VALUES ( 'Pioneer Sirius Bus Interface - CDSB10', 'Pioneer Sirius Bus Interface - CDSB10/ Sirius Connect'' Compatibility/ Replay Function/ Game Alert/ Game Zone', 68.00); +INSERT INTO Product( title, description, price) VALUES ( 'Pioneer HD Radio Tuner - GEXP10HD', 'Pioneer HD Radio Tuner - GEXP10HD/ Compatible With FH-P800BT, FH-P8000BT, DEH-P700BT, DEH-P7000BT, DEH-P600UB, DEH-P6000UB/ ''External Control'' Capable', 100.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sirius Dock And Play Universal Vehicle Kit - SUPV1', 'Sirius Dock And Play Universal Vehicle Kit - SUPV1/ Stereo Audio Output/ Use With Your Home Audio System Or Powered Speakers/ Compatible With Sportster 5, Sportster 4, Sportster 3, Starmate 4, Starmate 3, Stratus 4, Stratus', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'Electrolux Harmony Series Canister Vacuum - EL6985B', 'Electrolux Harmony Series Canister Vacuum - EL6985B/ Foot-Operated Switch On The Floor Nozel/ Ergonomic Handle Design/ Electronic Dust Bag Indicator/ HEPA H12 Filter/ Telescoping Wand', 299.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sennheiser Rechargeable Nickel-Metal Hydride Battery - BA151', 'Sennheiser Rechargeable Nickel-Metal Hydride Battery - BA151/ Rechargeable Battery For Wireless Sennheiser Headphones', 20.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Green Photo Ink Cartridge - CLI8G', 'Canon Green Photo Ink Cartridge - CLI8G/ FINE Technology For Exceptional Sharpness & Detail/ Compatible With Canon Pixma Pro9000', 16.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Red Photo Ink Cartridge - CLI8R', 'Canon Red Photo Ink Cartridge - CLI8R/ FINE Technology For Exceptional Sharpness & Detail/ Compatible With Canon Pixma Pro9000', 16.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Black Photo Ink Cartridge - CLI8B', 'Canon Black Photo Ink Cartridge - CLI8B/ FINE Technology For Exceptional Sharpness & Detail/ Compatible With Canon Pixma Printers', 16.00); +INSERT INTO Product( title, description, price) VALUES ( 'Netgear ProSafe 5 Port 10/100 Desktop Switch - FS105', 'Netgear ProSafe 5 Port 10/100 Desktop Switch - FS105/ 5 Auto Speed-Sensing 10/100 UTP Ports/ Embedded Memory', 40.00); +INSERT INTO Product( title, description, price) VALUES ( 'Pioneer Premier In-Dash CD/WMA/MP3/AAC Receiver - DEHP400UB', 'Pioneer Premier In-Dash CD/WMA/MP3/AAC Receiver - DEHP400UB/ 50W x 4 Built-In Speaker Power/ 3 RCA Hi-Volt Preouts/ Two-Way Crossover/ Supertuner IIID/ AUX-In Connection/ Rotary Commander Volume Control', 183.00); +INSERT INTO Product( title, description, price) VALUES ( 'Pioneer DEH-2000MP CD/MP3/WMA In-Dash Receiver - DEH2000MP', 'Pioneer DEH-2000MP CD/MP3/WMA In-Dash Receiver - DEH2000MP/ 50W x 4 Built-In Speaker Power/ LED Display/ Built-In Front Auxiliary Input/ Detachable Face Security/ Remote Control/ Rotary Volume Control', 98.00); +INSERT INTO Product( title, description, price) VALUES ( 'Pioneer Premier In-Dash CD/WMA/MP3/AAC Receiver - DEHP500UB', 'Pioneer Premier In-Dash CD/WMA/MP3/AAC Receiver - DEHP500UB/ 50W x 4 Built-In Speaker Power/ 3 RCA Hi-Volt Preouts/ Two-Way Crossover/ Supertuner IIID/ AUX-In Connection/ Rotary Commander Volume Control', 208.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony 7'' Digital Photo Frame In Black - DPFD70', 'Sony 7'' Digital Photo Frame - DPFD70/ 7'' LCD With 800 x 480 Resolution/ 15:9 Aspect Ratio/ 256MB Internal Memory/ Supports Most Memory Cards/ Variety Of Display Modes/ Auto Image Rotation Feature/ View Mode Button/ Fast Digital Picture Decoding/ Handles Large Data Files/ USB B-Type Connection/ Remote Control/ Black Finish', 139.00); +INSERT INTO Product( title, description, price) VALUES ( 'SIRIUS SiriusConnect Vehicle Kit In Black - SCVDOC1', 'SIRIUS SiriusConnect Vehicle Kit In Black - SCVDOC1/ Compact Design/ Compatible With The Next Generation Of SiriusConnect Interface Adapters/ 3 Interchangeable Adapter Plates/ Black Finish', 59.00); +INSERT INTO Product( title, description, price) VALUES ( 'Linksys Wireless-G Ethernet Bridge - WET54G', 'Linksys Wireless-G Ethernet Bridge - WET54G/ Converts Wired-Ethernet Devices To Wireless-G Network Connectivity/ For Windows, Macintosh, Linux, PlayStation Consoles, Xbox Consoles, Or Anything With An Ethernet Port/ Plug And Play, No Driver Installation Require', 89.00); +INSERT INTO Product( title, description, price) VALUES ( 'Yamaha RX-V363BL 5.1 Channel Digital Home Theater Receiver In Black - RXV363BK', 'Yamaha RX-V363BL 5.1 Channel Digital Home Theater Receiver In Black - RXV363BK/ 500 Watts Powerful Surround Sound (100W x 5)/ iPod And Bluetooth Audio Compatibility/ Dolby Digital, DTS And Dolby Pro Logic II Decoding/ Cinema DSP With 8 DSP Programs/ Compressed Music Enhancer/ 192kHz/24-Bit DACs For All Channels/ Remote Control/ Black Finish', 199.00); +INSERT INTO Product( title, description, price) VALUES ( 'Yamaha All-Weather Pair Speaker System - NSAW390WH', 'Yamaha NS-AW390WH All-Weather Speaker System - NSAW390WH/ 6.5'' High Compliance/ PP Mica Filled Woofers/ Unique Dual 1'' PEI Dome Tweeter Configuration/ Aluminum Speaker Grilles/ Wall Mountable/ White Finish/ Sold As A Pair', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'Yamaha NS-AW390BL All-Weather Pair Speaker System - NSAW390BK', 'Yamaha NS-AW390BL All-Weather Speaker System - NSAW390BK/ 6.5'' High Compliance/ PP Mica Filled Woofers/ Unique Dual 1'' PEI Dome Tweeter Configuration/ Aluminum Speaker Grilles/ Wall Mountable/ Black Finish/ Sold As A Pair', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'Yamaha NS-AW190BL All-Weather Pair Speaker System - NSAW190BK', 'Yamaha NS-AW190BL All-Weather Speaker System - NSAW190BK/ 5'' High Compliance/ PP Mica Filled Woofers/ Unique Dual 1/2'' PEI Dome Tweeter Configuration/ Aluminum Speaker Grilles/ Wall Mountable/ Black Finish/ Sold As A Pair', 99.00); +INSERT INTO Product( title, description, price) VALUES ( 'Yamaha 7.2 Channel Black Digital Home Theater Receiver - RXV663BK', 'Yamaha 7.2 Channel Black Digital Home Theater Receiver - RXV663BK/ 4 SCENE Buttons/ XM Ready With XM HD Surround/ SIRIUS Satellite Radio Ready/ YPAO/ iPod Compatibility/ Bluetooth Compatibility/ Multi-Zone Control Compatibility/ On-Screen Display/ Black Finish', 499.00); +INSERT INTO Product( title, description, price) VALUES ( 'Yamaha 7.2 Channel Black Digital Home Theater Receiver - RXV863BK', 'Yamaha 7.2 Channel Black Digital Home Theater Receiver - RXV863BK/ 4 SCENE Buttons/ XM Ready With XM HD Surround/ SIRIUS Satellite Radio Ready/ YPAO/ iPod Compatibility/ Bluetooth Compatibility/ Multi-Zone Control Compatibility/ On-Screen Display/ Black Finish/ CALL FOR LATEST PRICE', 899.00); +INSERT INTO Product( title, description, price) VALUES ( 'Yamaha 5.1 Channel Home Theater In A Box System In Black - YHT390BK', 'Yamaha 5.1 Channel Home Theater In A Box System In Black - YHT390BK/ New Scene, Compressed Music Enhancer/ iPod Compatibility/ 600W Powerful Surround Sound/ Silent Cinema/ 192kHz/24-Bit DACs For All Channels/ Black Finish', 399.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple MacBook Air SuperDrive - MB397GA', 'Apple MacBook Air SuperDrive - MB397GA/ Compact And Portable Slot-Loading 8x SuperDrive/ Connect To MacBook Air USB Slot/ Play And Burn Both CDs And DVDs/ Watch DVD Movie, Install Software, Or Create Backup Discs', 99.00); +INSERT INTO Product( title, description, price) VALUES ( 'Monster Mini-To-Mini iCable For Car - AICMINIIP3S', 'Monster Mini-To-Mini iCable For Car - AICMINIIP3S/ 3 Ft. Cable/ 1/8 Mini-Jack Input For Car Stereo/ Dual Balanced High-Purity Copper Conductors And 24k Gold/ Xtra Low Noise DoubleHelix Construction/ Compatible With Apple iPod, iPhone, And Portable MP3 Player/ White Finish', 15.00); +INSERT INTO Product( title, description, price) VALUES ( 'TomTom GPS Mount And USB Car Charger - 9N00101', 'TomTom GPS Mount And USB Car Charger - 9N00101/ Extra Holder And Car Charger Convenient For Multi-Vehicles User/ No Need To Transfer Holder From One Car To Another/ Easy Installation/ Compatible With TomTom ONE/ Black Finish', 39.00); +INSERT INTO Product( title, description, price) VALUES ( 'Denon Blu-ray Disc DVD/CD Player - DVD3800BDCI', 'Denon Blu-ray Disc DVD/CD Player - DVD3800BDCI/ 10-Bit Realta HQV Video Processor/ 1080p/24fps Output And Multi-Cadence Detection/ HDMI 1.3a Output With 36-Bit Deep Color Support/ Dual 32-Bit Floating Point DSP/ Multi-Layered Construction With Dual-Layered Top Shields And Triple-Layered Bottom/ Suppress Vibration Hybrid (S.V.H.) Loader/ Black Finish', 1999.00); +INSERT INTO Product( title, description, price) VALUES ( 'TomTom GPS Mount And USB Car Charger - 9S00006', 'TomTom GPS Mount And USB Car Charger - 9S00006/ Extra Holder And Car Charger Convenient For Multi-Vehicles User/ No Need To Transfer Holder From One Car To Another/ Easy Installation/ Compatible With TomTom ONE XL/ Black Finish', 28.00); +INSERT INTO Product( title, description, price) VALUES ( 'Bracketron iPod Docking Kit - IPM202BL', 'Bracketron iPod Docking Kit - IPM202BL/ Compatible With All Generation iPods Including iPod Mini, iPod Nano And Apple iPhone/ Wings Adjustable Up To 2.5''/ Black Finish', 14.95); +INSERT INTO Product( title, description, price) VALUES ( 'Boston Acoustics Solo AM/FM Large Display Clock Radio - HSOLOMDNT', 'Boston Acoustics Solo AM/FM Large Display Clock Radio - HSOLOMDNT/ Rotating Clock Face/ Precision Tuner/ 3 1/2? Full-Range Speaker/ Auxiliary Input/ High Contrast LCD Display/ 360� Snooze Bar/ Grey Finish', 99.00); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic 5.8 GHz Black Expandable Digital Cordless Phone System - KXTG4323B', 'Panasonic 5.8 GHz Black Expandable Digital Cordless Phone System - KXTG4323B/ Include 3 Handsets/ Expandable Up To 4 Handsets/ Digital Answering Machine System/ Ringer ID/ Call Waiting Caller ID/ Voicemail/ Hold/ Mute/ Clock/ Alarm/ LED Lighting/ Speakerphone/ Intercom/ 11 Days Standby/ 5 Hours Talk Time/ Black Finish', 79.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Silver Digital Voice Recorder - ICDB600', 'Sony Silver Digital Voice Recorder - ICDB600/ 512MB Built-In Flash Memory/ Up To 300 Hours Of Recording Time/ 3 Recording Modes/ 4 Message Folders/ Large LCD Display/ Voice Operated Recording/ 250mW Speaker Output/ Date and Time Stamp/ Silver Finish', 39.00); +INSERT INTO Product( title, description, price) VALUES ( 'Motorola MotoRokr Portable Bluetooth Car Kit Speaker Phone - T505', 'Motorola MotoRokr Portable Bluetooth Car Kit Speaker Phone - T505/ 2.0 Bluetooth Wireless Technology/ Noise Cancellation Technology/ Loud Sound High Speaker Output/ Audio CallerID/ StationFinder/ Convenient Multi-Function Button/ Long Battery Life/ Mini-USB Connector/ Black Finish', 129.00); +INSERT INTO Product( title, description, price) VALUES ( 'Samsung Hi Definition Conversion DVD Player - DVD1080P8', 'Samsung Hi Definition Conversion DVD Player - DVD1080P8/ Progressive Scan/ HD Upconversion/ Digital-To-Analog Converter/ Dolby Digital Surround Sound/ Child Protection/ HDMI Output/ Black Finish', 79.90); +INSERT INTO Product( title, description, price) VALUES ( 'Boston Acoustics Duo-I AM/FM Clock Radio With iPod Dock - HDUOIMDNT', 'Boston Acoustics Duo-I AM/FM Clock Radio With iPod Dock - HDUOIMDNT/ Integrated iPod Dock/ Precision AM/FM Stereo Tuner/ 3 1/2'' Dual High Performance Full-Range Speakers/ BassTrac Audio Processing/ 2 Auxiliary Inputs/ High Contrast Display/ 10 FM & 5 AM Station Presets/ 360� Snooze Bar/ Remote Control Included/ Grey Finish', 199.00); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic Black DVD Home Theater Sound System - SCPT660', 'Panasonic Black DVD Home Theater Sound System - SCPT660/ Kelton Subwoofer/ Bamboo Diaphragm Center Speakers/ 1080p Up-Conversion/ Integrated Universal Dock And On-Screen Display For iPod/ iPod Video Playback/ Whisper-Mode Surround/ Built-In Dolby Digital And DTS Decoder/ High Speed 5-DVD/CD Changer/ Black Finish', 289.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Summit E-620 Copper Liquid Propane Gas Outdoor Grill - 1752001', 'Weber Summit E-620 Copper Liquid Propane Gas Outdoor Grill - 1752001/ 6 Stainless Steel Burners/ 60,000 BTU-Per-Hour Input/ Snap-Jet Individual Burner Ignition System/ 838 Sq. In. Total Cooking Area/ Porcelain-Enameled Shroud/ Center-Mounted Thermometer/ Copper Finish/ Liquid Propane Model (LP Tank Not Included)/ Assembly Required', 1899.00); +INSERT INTO Product( title, description, price) VALUES ( 'Logitech Harmony One Advanced Universal Remote Control - HARMONY1', 'Logitech Harmony One Advanced Universal Remote Control - HARMONY1/ One-Touch Access To Your Entertainment/ Replaces Up To 15 Remotes/ Full-Color Touch Screen/ Sculpted, Backlighted Buttons In Logical Zones/ Ergonomic Design/ Rechargeable/ Guided Online Setup/ World?s Largest AV Control Database/915-000035', 249.00); +INSERT INTO Product( title, description, price) VALUES ( 'Z-Line Portland Black TV Stand - ZL2344MU', 'Z-Line Portland Black TV Stand - ZL2344MU/ Accommodates Most Flat Panel LCD/Plasma TVs Up To 50''/ Durable Black Glossy Powder Coat Metal Frame/ Tempered Black Safety Glass Shelves/ Chrome Cylinder Glass Supports/ Swivel Mount/ Wire Management/ Holds 65 lbs Per Shelf/ Distance Between Shelves- 8.25'' (Bottom to Middle) and 7'' (Middle to the bar below the top shelf)/ Black Finish', 399.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Black USB Stereo Turntable System - PSLX300USB', 'Sony Black USB Stereo Turntable System - PSLX300USB/ Transfer Classic Vinyl To PC, Walkman, Or MP3 Player/ USB And RCA Audio Output/ 45 Rpm Record Playback/ Belt Drive System/ Dust Cover/ Black Finish', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Digital SLR Camera With Lens Kit - DSLRA200W', 'Sony Alpha Digital SLR Camera With Lens Kit - DSLRA200W/ 10.2 Megapixels/ 2.7'' Clear Photo LCD Screen/ Super SteadyShot In-Camera Image Stabilization/ Continuous Burst Mode/ Bionz Image Processor/ ISO Sensitivity/ 9-Point Center Cross AF Sensor/ Scene Selection Modes/ DT 18-70mm f3.5 Zoom Lens And 75-300mm f4.5-5.6 Compact Super Telephoto Zoom Lens Included/ Black Finish', 849.99); +INSERT INTO Product( title, description, price) VALUES ( 'Nyko Charge Base 2 Charger For PlayStation 3 Controller - 743840830535', 'Nyko Charge Base 2 Charger For PlayStation 3 Controller - 743840830535/ Compact Design/ Rapidly Charges Two PS3 Controllers Simultaneously/ Includes Two USB Charge Adaptors', 34.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Remote Control Tripod - VCT60AV', 'Sony Remote Control Tripod - VCT60AV/ A/V Remote Connector/ 4 Stage Leg Extension/ Extends From 18.9'' To 57.6'' In Height/ Guide Frame Feature/ Available Vertical Position/ Supplied Carrying Case/ Black Finish', 99.00); +INSERT INTO Product( title, description, price) VALUES ( 'Klipsch Groove PM20 Computer Speakers - GROOVEPM20BK', 'Klipsch Groove PM20 Computer Speakers - GROOVEPM20BK/ 6 Ohms Nominal Impedance/ 3Full-Range 2.5? Fiber Composite Driver/ Overload Protection/ System-Specific Loudness Contour/ Black Finish', 99.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Gas Barbecue Rotisserie - 7519', 'Weber Gas Barbecue Rotisserie - 7519/ Fits Genesis E-300, S-300 Gas Grills/ Heavy-Duty Electric Motor/ Counterbalance For Smooth Turning', 80.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Cast Iron Griddle - 7531', 'Weber Cast Iron Griddle - 7531/ Heavy-Duty Cast Iron Griddle/ Fits Weber Genesis Silver A & Spirit 500 Gas Grills', 44.99); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Cast Iron Griddle - 7542', 'Weber Cast Iron Griddle - 7542/ Heavy-Duty Cast Iron Griddle/ Two-Sided For Cooking A Variety Of Foods/ Fits Several Weber Grills', 44.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sony 5.1 Channel Black A/V Receiver - STRDG520', 'Sony 5.1 Channel Black A/V Receiver - STRDG520/ 100 Watts X 5 Power/ 1080p HDMI Pass Through/ Accepts 1080/60p And 24p Video Signal Via HDMI/ Dolby Digital, Dolby Pro Logic, Dolby Pro Logic II, Digital Cinema Sound And Dts Decoding/ Black Finish', 199.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Alpha DSLR Black Camera Body With 18-70mm Zoom Lens - DSLRA300K', 'Sony Alpha DSLR Black Camera Body With 18-70mm Zoom Lens - DSLRA300K/ 10.2 MP Super HAD CCD/ Tiltable 2.7 Clear Photo LCD Plus Screen/ Smart Teleconverter 2X Zoom/ Expanded ISO Sensitivity/ Super SteadyShot In-Camera Image Stabilization/ Anti-Dust Technology/ 9-Point Center Cross AF Sensor/ Index and Slide Show Display/ Black Finish', 599.99); +INSERT INTO Product( title, description, price) VALUES ( 'Polk Audio CSI A4 Black Center Channel Loudspeaker - CSIA4BK', 'Polk Audio CSI A4 Black Center Channel Loudspeaker - CSIA4BK/ 1'' Silk/Polymer Dome Tweeter/ Dual 5-1/4'' Mid/Woofers/ Magnetic Shielding/ All-MDF Construction/ Acoustically Inert Stamped Driver Baskets/ Floating Anti-Diffraction Grilles/ Dual Bi-Ampable Gold-Plated 5-Way Binding Post Inputs/ Black Finish/ Sold As A Single', 279.95); +INSERT INTO Product( title, description, price) VALUES ( 'Polk Audio CSI A4 Cherry Center Channel Loudspeaker - CSIA4CH', 'Polk Audio CSI A4 Cherry Center Channel Loudspeaker - CSIA4CH/ 1'' Silk/Polymer Dome Tweeter/ Dual 5-1/4'' Mid/Woofers/ Magnetic Shielding/ All-MDF Construction/ Acoustically Inert Stamped Driver Baskets/ Floating Anti-Diffraction Grilles/ Dual Bi-Ampable Gold-Plated 5-Way Binding Post Inputs/ Cherry Finish/ Sold As A Single', 279.95); +INSERT INTO Product( title, description, price) VALUES ( 'Polk Audio CSI A6 Black Center Channel Loudspeaker - CSIA6BK', 'Polk Audio CSI A6 Black Center Channel Loudspeaker - CSIA6BK/ Dual 6-1/2'' Mid/Woofers/ 1'' Silk/Polymer Dome Tweeter/ Dual Rear PowerPort Bass Venting/ Magnetic Shielding/ Mylar Bypass Capacitors/ Acoustic Resonance Control (ARC Port) Technology/ Dual Bi-Ampable Gold-Plated 5-Way Binding Post Inputs/ Butyl Rubber Surrounds/ Floating Anti-Diffraction Grilles/ All-MDF Construction/ Black Finish/ Sold As A Single', 449.95); +INSERT INTO Product( title, description, price) VALUES ( 'Polk Audio 5.1 Channel Black Home Theater Speaker System - RM705BK', 'Polk Audio 5.1 Channel Black Home Theater Speaker System - RM705BK/ Heavy-Duty Non-Resonant Composite Enclosures/ Downward Firing Powered 8'' Subwoofer/ Built-In Subwoofer Power Amp With Active Crossover/ Three-Sided Cabinet Design/ Magnetically Shielded/ Black Finish', 499.95); +INSERT INTO Product( title, description, price) VALUES ( 'Sony 3.1 Channel Home Theater Surround System In Black - HTCT100', 'Sony 3.1 Channel Home Theater Surround System In Black - HTCT100/ HDMI Active Intelligence/ LPCM Playback/ 3.1 Channel/ S-Force Surround/ BRAVIA� Sync/ Digital Media Port/ Black Finish/ ETA MID JANUARY 2009', 299.00); +INSERT INTO Product( title, description, price) VALUES ( 'Polk Audio Black 10'' Powered Subwoofer - PSW110BK', 'Polk Audio PSW110 Black 10'' Powered Subwoofer - PSW110BK/ 100 Watts Continuous Average Output/ 200 Watts Dynamic Power Output/ 10'' Dynamic Balance Composite Woofer Driver/ Klippel Optimized Woofer/ High Current Class A/B Amplifiers/ Downward Firing Port/ Line And Speaker Level Inputs/ Non-Resonant MDF Construction/ Black Finish', 299.95); +INSERT INTO Product( title, description, price) VALUES ( 'Twenty20 VholdR Mount Adhesive - 2200MA', 'Twenty20 VholdR Mount Adhesive - 2200MA/ Removable/ Resists Water, Heat And Cold', 6.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Premium Black Grill Cover - 7550', 'Weber Premium Black Grill Cover - 7550/ Heavy-Duty Vinyl/ Compatible With Spirit E-200 Series, Spirit 500 And Genesis Silver A Gas Grills/ Black Finish', 40.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Black Earbud Style Headphones - MDREX55BK', 'Sony MDREX55BLK Black Earbud Style Headphones - MDREX55BK/ 9mm EX Driver Provides Comfort Fit And Deep Bass Sound/ Soft Fitting Silicon Housing/ 3 Sizes Earbuds/ Carrying Pouch/ Black Finish', 39.00); +INSERT INTO Product( title, description, price) VALUES ( 'Hoover EmPower Bagless Upright Vacuum - U5269', 'Hoover EmPower Bagless Upright Vacuum - U5269/ Hush Mode/ Power Boost/ No Assembly Required/ Folding Handle For Easy Storage/ Allergen Filter/ 12 Amp Motor/ Tools Included/ Green Finish', 99.00); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic DECT 6.0 Expandable Digital Cordless Phone With All-Digital Answering System - KXTG9344T', 'Panasonic DECT 6.0 Expandable Digital Cordless Phone With All-Digital Answering System - KXTG9344T/ 4 Handsets System/ Up To 6 Multi-Handset Capability/ Digital Answering Machine System/ Ringer ID/ Call Waiting Caller ID/ Voicemail/ Hold/ Voice Menu/ Marker Message/ Mute/ Clock/ Alarm/ LED Lighting/ Night Mode/ Call Block/ Speakerphone/ 11 Days Standby/ 5 Hours Talk Time/ Black Metallic Finish', 139.00); +INSERT INTO Product( title, description, price) VALUES ( 'LaCie 500GB d2 Quadra External Hard Drive - 301825U', 'LaCie 500GB d2 Quadra External Hard Drive - 301825U/ Quadruple Interface For Full PC And Mac Compatibility/ Interface Bandwidth Up To 3Gbits/s (eSATA)/ Advanced Aluminum Heat Sink Design Cooling System For Quiet Operation/ 7200 Rotational Speed (rpm)/ 16MB Cache/ Compatible With Time Machine', 159.00); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic DECT 6.0 Black Expandable Digital Cordless Phone - KXTG9361B', 'Panasonic DECT 6.0 Black Expandable Digital Cordless Phone - KXTG9361B/ Drop And Splash Resistant/ Multi-Handset Capability/ Ringer ID/ Call Waiting Caller ID/ Voicemail/ Hold/ Mute/ Clock/ Alarm/ LED Lighting/ Night Mode/ Call Block/ Speakerphone/ 11 Days Standby/ 5 Hours Talk Time/ Black Finish', 48.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony 1GB Memory Stick PRO Duo Mark 2 Media Card - MSMT1G', 'Sony 1GB Memory Stick PRO Duo Mark 2 Media Card - MSMT1G/ 160 Mbps Transfer Speed/ 940MB Actual Capacity', 19.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony 2GB Memory Stick PRO Duo Mark 2 Media Card - MSMT2G', 'Sony 2GB Memory Stick PRO Duo Mark 2 Media Card - MSMT2G/ 160 Mbps Transfer Speed/ 1.85GB Actual Capacity', 29.99); +INSERT INTO Product( title, description, price) VALUES ( 'Pioneer Black Premier Single CD Receiver - DEHP700BT', 'Pioneer Black Premier Single CD Receiver - DEHP700BT/ Built-In Bluetooth Solution/ USB Direct Control For iPod/ Advanced Sound Retriever/ 3 RCA Hi-Volt Preouts/ Two-Way Crossover/ Built-In MOSFET 50 W x 4 Amplifier/ Supertuner IIID/ Amplifier Off Mode/ Display Off Mode', 308.00); +INSERT INTO Product( title, description, price) VALUES ( 'TomTom ONE 130S Car GPS Navigation System - 1EE005202', 'TomTom ONE 130S Car GPS Navigation System - 1EE005202/ 3.5'' LCD Anti-Glare Touch Screen/ Pre-Installed Maps/ Internal Lithium-Ion Battery/ Car Speed Linked Volume/ Automatic Day/Night Mode/ QuickGPSfix/ Text-To-Speech Included', 246.95); +INSERT INTO Product( title, description, price) VALUES ( 'TomTom ONE XL 330 Car GPS Navigation System - 1EG005200', 'TomTom ONE XL 330 Car GPS Navigation System - 1EG005200/ 4.3'' LCD Anti-Glare Touch Screen/ Pre-Installed Maps/ Internal Lithium-Ion Battery/ Car Speed Linked Volume/ Automatic Day/Night Mode/ QuickGPSfix', 246.95); +INSERT INTO Product( title, description, price) VALUES ( 'TomTom ONE XL 330S Car GPS Navigation System - 1EG005201', 'TomTom ONE XL 330S Car GPS Navigation System - 1EG005201/ 4.3'' LCD Anti-Glare Touch Screen/ Pre-Installed Maps/ Internal Lithium-Ion Battery/ Car Speed Linked Volume/ Automatic Day/Night Mode/ QuickGPSfix/ Text-To-Speech Included', 296.95); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Black Camcorder Tripod - VCT80AV', 'Sony Black Camcorder Tripod - VCT80AV/ 3 Stage Leg Extension/ Extends From 24.88'' To 65.88'' In Height/ Guide Frame Feature/ Available Vertical Position/ For A/V Remote Connector/ Supplied Carrying Case/ Black Finish', 180.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony 7.1 Channel Black A/V Receiver - STRDG820', 'Sony 7.1 Channel Black A/V Receiver - STRDG820/ 770 Watts Total Power (110W x 7)/ Accepting Resolutions Up To 1080p Via HDMI/ Digital Cinema Auto Calibration/ BRAVIA Sync/ Digital Cinema Sound/ Dolby Digital, Dolby Digital EX, Dolby Pro Logic II, Dolby Pro Logic IIx, Dts, Dts-ES, Dts 96/24, Dts NEO:6 Decoding/ Black Finish', 399.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Splash Resistant Shower Radio - ICFS79W', 'Sony Multi Band Digital Tuner Shower Radio - ICFS79W/ Splash Resistant/ AM/FM/Weather Band Reception/ Easy One Button Weather Band Select/ Built-In Digital Clock/ Selectable Automatic-Off Timer/ Quartz Synthesized Tuner/ Built-In Antennas', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'Samsung Black Combo DVD/VHS Player - DVDV9800', 'Samsung Black Combo DVD/VHS Player - DVDV9800/ Progressive Scan/ 1080p Up-Conversion Via HDMI/ 10Bit / 54MHz Digital-To-Analog Converter/ 4-Head Hi-Fi VCR/ Black Finish/ No Tuner', 98.00); +INSERT INTO Product( title, description, price) VALUES ( 'Omnimount Stellar Series Audio Tower - G303DARK', 'Omnimount Stellar Series Audio Tower - G303DARK/ Designed For Large Audio Components/ Supports Tabletop Flat Panels/ Three ?Floating? Shelf Design/ Integrated Cable Management/ Black Finish', 299.00); +INSERT INTO Product( title, description, price) VALUES ( 'Weber Q 320 Liquid Propane Table And Outdoor Grill - 586002', 'Weber Q 320 Liquid Propane Table And Outdoor Grill - 586002/ 462 Sq. In. Total Cooking Area/ 21,700 BTU Stainless Steel Burners/ Porcelain-Enameled Cast-Iron Cooking Grate/ Cast-Aluminum Lid And Body/ Electronic Ignition/ Grill Out Handle Light/ Folding Work Tables With Tool Holders/ Removable Catch Pan/ Built-In Thermometer/ Stationary Cart Included/ Black And Aluminum Finish/ Assembly Required', 379.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Black Component Home Theater System - HT7200DH', 'Sony Black Component Home Theater System - HT7200DH/ 900 Watts/ 5.1 Channels/ HDMI 1080p Output DVD Player/ HDMI Active Intellegence AV Receiver/ 5 Satellite Speakers/ XM Ready/ Black Finish', 499.00); +INSERT INTO Product( title, description, price) VALUES ( 'TomTom Black Carry Case - 9UEA01700', 'TomTom Black Carry Case - 9UEA01700/ Specifically Designed For TomTom ONE 130 GPS/ Durable And Compact Protective Hardcover Material/ Wrist Strap/ Black Finish', 19.00); +INSERT INTO Product( title, description, price) VALUES ( 'Mitsubishi 835 Diamond Series 73'' 1080p DLP Rear Projection HDTV - WD73835', 'Mitsubishi 835 Diamond Series 73'' 1080p DLP Rear Projection HDTV - WD73835/ 1920 x 1080 Full HD Resolution/ 6-Color Processor/ Smooth 120Hz/ x.v.Color/ Plush1080p 12-Bit Digital Video Processing/ Color 4D Video Noise Reduction/ 3D Ready/ NetCommand/ DeepField Imager/ Black Finish', 3499.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Black DVD Recorder And VHS Combo Player - RDRVX560', 'Sony Black DVD Recorder And VHS Combo Player - RDRVX560/ Multiformat DVD Compatible/ HDMI Output With 1080p,1080i,720p Upscaling/ USB One Touch Dubbing/ 4 Video Head Stereo VHS With 19 Micron Heads/ Virtual Surround Sound For DVD With Stereo TV Speakers/ Black Finish', 219.00); +INSERT INTO Product( title, description, price) VALUES ( 'Uniden DECT 6.0 Digital Accessory Handset - DCX300', 'Uniden DECT 6.0 Digital Accessory Handset - DCX300/ DECT 6.0 Interference Free Cordless Frequency/ Large Color Display/ Blue Backlit Keypad/ Handset Speakerphone/ Intercom or Call Transfer Between Handsets/ Polyphonic Ring Tones/ Advanced Phonebook Features/ Last 5 Number Redial/ Piano Black Finish', 34.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony DVD Recorder In Black - RDRGX360', 'Sony DVD Recorder In Black - RDRGX360/ 1080p/1080i/720p Upscaling For DVD/ USB One Touch Dubbing/ Line Input Recording/ BRAVIA Sync/ DVD+R Double Layer Recording/ Dolby Digital Decoding Playback Compatible/ Black Finish', 179.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sennheisser Hi-Fi Wireless Headphone - RS130', 'Sennheisser Hi-Fi Wireless Headphone - RS130/ Switchable SRS Surround Sound Mode/ Intelligent Auto-Tuning/ Memory Function/ Self-Learning Automatic Level Control/ Black Finish', 159.95); +INSERT INTO Product( title, description, price) VALUES ( 'BlueAnt Black Bluetooth Headset - Z9I', 'BlueAnt Black Bluetooth Headset - Z9I/ Pairs With 5 Devices/ Bluetooth Version 2.0 Technology/ Dual Microphones For Pure Speech/ Revolutionary Voice Isolation Technology/ Automatic Connection And Reconnection With Notification/ Firmware Upgrade Via USB On Your PC/ Up To 5.5 Hours Talk Time/ 200 Hours Standby Time/ Gloss Black Finish', 99.00); +INSERT INTO Product( title, description, price) VALUES ( 'Escort Passport 9500CI Radar Detector - 9500CI', 'Escort Passport 9500CI Radar Detector - 9500CI/ 360 Degree Protection/ Completely Undetectable To All Detector Scanners/ Variable-Speed Radar Performance/ GPS-Powered Truelock Filter/ Adaptive Signal Processing/ Speed Alert/ Crystal-Clear Voice Alerts/ 280 LED Matrix Blue Display/ 5 Levels Of Brightness Control/ Black Finish/ Price Includes Installation', 1995.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Black 5.1 Channel Home Theater System - HTDDWG700', 'Sony Black 5.1 Channel Home Theater System - HTDDWG700/ 5.1 Channel/ 900 Watts Power/ Portable Audio Enhancer With Front Audio Input/ iPod Cradle/ Digital Cinema Auto Calibration/ BRAVIA Sync/ Digital Media Port/ Black Finish', 199.00); +INSERT INTO Product( title, description, price) VALUES ( 'Denon Multi-Channel Digital Surround Sound Speaker System - DHTFS5', 'Denon Multi-Channel Digital Surround Sound Speaker System - DHTFS5/ Multiple Amplifier Channels/ Dolby Pro Logic II, Dolby Digital And DTS Surround/ Balanced Loudspeaker Drivers/ X-Space Surround Technology/ Night Mode/ Remote Control Included/ Black Finish', 499.00); +INSERT INTO Product( title, description, price) VALUES ( 'Danby White Countertop Dishwasher - DDW497WH', 'Danby White Countertop Dishwasher - DDW497WH/ 4 Place Settings/ Quick Connect To Any Kitchen Tap/ Automatic Detergent And Rinse Agent Dispenser/ Quiet Operation/ 5 Wash Cycles/ Durable Stainless Steel Spray Arm And Interior/ White Finish', 222.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon KP-36IP Color Ink & Paper Set - 7737A001', 'Canon KP-36IP Color Ink & Paper Set - 7737A001/ 36 Sheets Of 4'' x 6'' Photo Paper/ Ink Cartridge For Compatible Canon Dye Sublimation Printer', 12.00); +INSERT INTO Product( title, description, price) VALUES ( 'Linksys Ultra RangePlus Wireless-N Broadband Router - WRT160N', 'Linksys Ultra RangePlus Wireless-N Broadband Router - WRT160N/ Internet-Sharing Router/ 4-Port Switch/ Enhanced Wireless Access Point/ MIMO Technology/ Faster Than Wireless-G/ Protected By Wireless Encryption/ Powerful SPI Firewall/ 2 Antennas/ Glossy Black Finish', 79.00); +INSERT INTO Product( title, description, price) VALUES ( 'Pioneer USB iPod Interface Cable - CDIU230V', 'Pioneer USB iPod Interface Cable - CDIU230V/ Compatible With AVIC-F700BT And AVIC-F900BT Navigation Receivers', 48.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon White Selphy CP760 Compact Photo Printer - 2565B001', 'Canon White Selphy CP760 Compact Photo Printer - 2565B001/ 2.5'' TFT Display/ Portrait Image Optimize/ Print Water-Resistant Photos/ Print Directly From Your Memory Cards Or Bluetooth-Enabled Devices/ Big Buttons/ Automatic Red-Eye Correction/ White Finish', 95.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony 2GB Memory Stick Micro (M2) - MSA2GU2', 'Sony MSA2GD 2GB Memory Stick Micro (M2) - MSA2GU2/ Ultra-Small Size/ 2GB Storage Capacity With 1.85GB Available/ Designed For Use In Compatible Small Devices Such As Mobile Phone/ Dual Operating Voltage/ M2 Duo Adaptor Included/ Black Finish', 29.99); +INSERT INTO Product( title, description, price) VALUES ( 'Panasonic DECT 6.0 Silver Digital Cordless Handset - KXTGA630S', 'Panasonic DECT 6.0 Silver Digital Cordless Handset - KXTGA630S/ For Use With Panasonic 6300 And 9300 Series Phone Systems/ DECT 6.0 Technology/ 60 Channels/ Call Waiting Caller ID/ 1.4'' Amber Backlit LCD Display/ Wall Mountable/ 11 Days Standby Time/ 5 Hours Talk Time/ Silver Finish', 29.99); +INSERT INTO Product( title, description, price) VALUES ( 'Polk Audio White Round Two-Way In-Wall Loudspeaker - TC60I', 'Polk Audio White Round Two-Way In-Wall Loudspeaker - TC60I/ Dynamic Balance Polymer Composite Driver/ Aimable 1'' Silk Dome Tweeter With Neodymium Magnet/ 15-Degree Offset Drive Unit/ Wide Dispersion Design/ Durable, Moisture Resistant Materials/ Infinite Baffle Tuning/ Paintable, Powder-Coated Aluminum Grilles/ Conveniently Accessible Front Panel Controls/ Each Speaker Sold Seperately/ White Finish', 299.95); +INSERT INTO Product( title, description, price) VALUES ( 'Toshiba Black DVD/VCR Combinaton Player - SDV296', 'Toshiba Black DVD/VCR Combinaton Player - SDV296/ Progressive Scan DVD Player/ One Touch Recording For The VCR/ ColorStream Pro Progressive Scan Component Video Outputs/ Simultaneous DVD Playback And VHS Record/ JPEG Viewer/ Black Finish', 89.00); +INSERT INTO Product( title, description, price) VALUES ( 'Samsung 19'' Black Flat Panel Series 6 LCD HDTV - LN19A650', 'Samsung 19'' Black Flat Panel Series 6 LCD HDTV - LN19A650/ 1440 x 900 True 720p Resolution/ 3,000:1 Dynamic Contrast Ratio/ SRS TruSurround XT/ Built-In Digital Tuner (ATSC/Clear QAM)/ Wide Color Enhancer/ 8ms Response Time/ Touch Of Color Design/ Black With Red Finish', 499.00); +INSERT INTO Product( title, description, price) VALUES ( 'Samsung 22'' Black Flat Panel Series 6 LCD HDTV - LN22A650', 'Samsung 22'' Black Flat Panel Series 6 LCD HDTV - LN22A650/ 1680 x 1050 True 720p Resolution/ 5,000:1 Dynamic Contrast Ratio/ SRS TruSurround XT/ Built-In Digital Tuner (ATSC/Clear QAM)/ Wide Color Enhancer/ 8ms Response Time/ Touch Of Color Design/ Black With Red Finish', 599.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Deluxe Burgundy Leather Case - 2350B001', 'Canon Deluxe Burgundy Leather Case - 2350B001/ Genuine Leather Case/ Designed For The PowerShot SD770 IS, SD1100 And SD1000/ Burgundy Finish', 18.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Deluxe Black Digital Camera Case - 2595B002', 'Canon Deluxe Black Digital Camera Case - 2595B002/ Soft Nylon Case/ Flip-Down Cover/ Belt Loop Attachment For Hands-Free Convenience/ Compatible With Canon PowerShot A Series/ Black Finish', 13.99); +INSERT INTO Product( title, description, price) VALUES ( 'Griffin iPod RoadTrip With SmartScan - 4040RDTRPB', 'Griffin iPod RoadTrip With SmartScan - 4040RDTRPB/ Play Music From Your iPod On Your Car?s Stereo System As It Charges/ Switch Quickly Between Pre-Sets/ SmartSound Plus Technology Delivers Clear Sound Under Real-World Conditions/ Flexible Steel Neck/ Black Finish', 89.00); +INSERT INTO Product( title, description, price) VALUES ( 'Denon Black Home Theater Surround Sound Receiver - AVR1709', 'Denon Black AVR-1709 Home Theater Surround Sound Receiver - AVR1709/ 80 Watts Per Channel/ 7 Channels/ HDMI V1.3A Video Switching/ Dolby Digital Surround EX, Dolby Pro Logic IIx, DTS ES 6.1, DTS Neo:6 Decoding/ Audyssey MultEQ, Dynamic Volume And Dynamic EQ/ Video Up-Conversion/ Black Finish', 449.99); +INSERT INTO Product( title, description, price) VALUES ( 'Denon Black AVR-1609 Home Theater Surround Sound Receiver - AVR1609', 'Denon Black AVR-1609 Home Theater Surround Sound Receiver - AVR1609/ 75 Watts Per Channel/ 7 Channels/ HDMI V1.3A Video Switching/ Dolby Digital Surround EX, Dolby Pro Logic IIx, DTS ES 6.1, DTS Neo:6 Decoding/ Audyssey MultEQ, Dynamic Volume And Dynamic EQ/ Sirius Satellite Radio Ready/ Network And Digital Media Connectivity/ Black Finish', 349.99); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Bud Style Headphones In Silver - MDRED12LPSLV', 'Sony Bud Style Headphones In Silver - MDRED12LPSLV/ 16mm Drivers/ Crisp Sound/ Neodymium Magnets Offer Powerful Sound Reproduction/ Convenient Cord Slider Reduces Tangles/ 3.9 Ft. Cord Length/ Frequency Response Of 8-22,000Hz/ Silver Finish', 14.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony Bud Style Headphones In Red - MDRED12LPRED', 'Sony Bud Style Headphones In Red - MDRED12LPRED/ 16mm Drivers/ Crisp Sound/ Neodymium Magnets Offer Powerful Sound Reproduction/ Convenient Cord Slider Reduces Tangles/ 3.9 Ft. Cord Length/ Frequency Response Of 8-22,000Hz/ Red Finish', 14.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony EX Ear Bud Headphones In Black - MDREX32LPBLK', 'Sony EX Ear Bud Headphones In Black - MDREX32LPBLK/ 9mm Drivers/ Deep Bass Sound/ Neodymium (400kJ/m3) Magnets Offer Powerful Bass Sound Reproduction/ 3.9 Ft. Cord Length/ Frequency Response Of 6-23,000Hz/ Black Finish', 24.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony EX Ear Bud Headphones In White - MDREX32LPWHI', 'Sony EX Ear Bud Headphones In White - MDREX32LPWHI/ 9mm Drivers/ Deep Bass Sound/ Neodymium (400kJ/m3) Magnets Offer Powerful Bass Sound Reproduction/ 3.9 Ft. Cord Length/ Frequency Response Of 6-23,000Hz/ White Finish', 24.00); +INSERT INTO Product( title, description, price) VALUES ( 'Griffin iPhone SmartTalk - 3016SMRTLKB', 'Griffin iPhone SmartTalk - 3016SMRTLKB/ Adds A Microphone And An iPhone Control Button To Your Favorite Earphones/ Play, Pause And Skip Through Your Tunes/ High-Sensitivity Microphone For Crystal-Clear Phone Conversations/ 30'' Cable Sheathed In Nylon Braiding', 19.00); +INSERT INTO Product( title, description, price) VALUES ( 'Logitech Driving Force Pro Steering Wheel With Pedals Set For Sony Playstation 2 - 9632930403', 'Logitech Driving Force Pro Steering Wheel With Pedals Set For Sony Playstation 2 - 9632930403/ Comfortable Soft Full Rubber Wheel/ Realistically Turn Through 2.5 Times Wheel Rotation/ 900 Degrees Of wheel Steering/ State-Of-The-Art Force Feedback Technology/ Stick Shifter/ Responsive Gas And Brake Pedals/ Black Finish', 129.00); +INSERT INTO Product( title, description, price) VALUES ( 'Monster iCarPlay Wireless 250 FM Transmitter With AutoScan for iPod And iPhone - AIPFMCH250', 'Monster iCarPlay Wireless 250 FM Transmitter With AutoScan For iPod And iPhone - AIPFMCH250/ Plays iPod Or iPhone Music Over Any Car Stereo/ Vibrant Sound/ Works With Any FM Car Radio/ 3 Programmable Presets/ FM Stations Range From 88.1 To 107.9/ Easy To Use/ Convenient Charging While You Drive/ Black Finish', 100.00); +INSERT INTO Product( title, description, price) VALUES ( 'D-Link Broadband Cable Modem - DCM202', 'D-Link Broadband Cable Modem - DCM202/ DOCSIS 2.0 CableLabs Certified/ High-Speed Internet Connectivity/ Always On And Always Connected/ Ethernet Or USB Connectivity/ Front Panel LED Indicator Lights/ Grey Finish', 79.00); +INSERT INTO Product( title, description, price) VALUES ( 'LaCie USB 2.0 Floppy Disk Drive - 706018', 'LaCie USB 2.0 Floppy Disk Drive - 706018/ Ultra-Thin Portable Design/ Compatible With Windows And Mac OS/ Plug And Play/ USB Powered/ 250 - 500 kbps Transfer Rate/ Silver Finish', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'Toshiba XDE Black 1080p Upconversion Extended Detail DVD Player - XDE500', 'Toshiba XDE Black 1080p Upconversion Extended Detail DVD Player - XDE500/ Full 1080p Upconversion With 24 Frames Per Second/ Detail Enhancement/ Intelligent Color/ Contrast Enhancement/ DivX Certified/ Black Finish', 99.00); +INSERT INTO Product( title, description, price) VALUES ( 'Griffin Black iPhone 3G Wave Case - 8227IP2WVB', 'Griffin Black iPhone 3G Wave Case - 8227IP2WVB/ Elegtant Wave-Shaped Closures/ Durable Polycarbonate Protection/ Rigid Touchscreen Protector/ Full Access To All Ports And Controls/ Black Finish', 24.00); +INSERT INTO Product( title, description, price) VALUES ( 'iHome iPod & iPhone Clock Radio & Audio System - IP99BR', 'iHome iP99 iPod & iPhone Clock Radio & Audio System - IP99BR/ Universal Dock For iPhone/ Auto-Set Clock/ Programmable Snooze/ Charges iPod Or iPhone While Docked/ Reason8 Speaker Chambers/ Line In Jack/ Full Function Remote Control Included/ Dual Alarm Clock/ Extra-Large LCD Display/ Black Finish (iPhone Not Included)', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'Transcend 8GB SDHC Card And Compact Card Reader - TS8GSDHC6S5W', 'Transcend 8GB SDHC Card And Compact Card Reader - TS8GSDHC6S5W/ SDHC Card Is Class 6 Compliant And Compatible With All SDHC-Labeled Host Devices/ Card Reader Is Fully Compatible With Hi Speed USB 2.0, Up To 480Mb/s And Supports SDHC Memory Cards', 26.30); +INSERT INTO Product( title, description, price) VALUES ( 'Denon 7.1 Channel AV Receiver With Network Client Compatible D-Dock Port In Black - AVR2809CI', 'Denon 7.1 Channel AV Home Theater Surround Receiver With Network Client Compatible D-Dock Port In Black - AVR2809CI/ 110 Watts x 7 Channels/ 1080p Upscaling/ PC Setup And Control Capability Via RS-232C/ Network Capable/ XM Satellite Radio Ready/ Dolby TrueHD And DTS-HD Master Audio/ HDMI 1.3a Repeater Inputs-Outputs/ Dual Remotes/ Black Finish', 1199.99); +INSERT INTO Product( title, description, price) VALUES ( 'LaCie Little Disk 320GB Black Portable Hard Drive - 301829', 'LaCie Little Disk 320GB Black Portable Hard Drive - 301829/ Compact, Thin And Lightweight Design/ Back Up, Synchronize And Secure Files And Settings/ Extractable Integrated USB Cable And Protective Cap/ Hi-Speed USB 2.0/ PC And Mac Compatible/ Black Finish', 119.00); +INSERT INTO Product( title, description, price) VALUES ( 'LaCie Little Disk 250GB Black Portable Hard Drive - 301278', 'LaCie Little Disk 250GB Black Portable Hard Drive - 301278/ Compact, Thin And Lightweight Design/ Back Up, Synchronize And Secure Files And Settings/ Extractable Integrated USB Cable And Protective Cap/ Hi-Speed USB 2.0/ PC And Mac Compatible/ Black Finish', 99.00); +INSERT INTO Product( title, description, price) VALUES ( 'AppleCare Protection Plan For iPod Touch Or iPod Classic - MB591LLA', 'AppleCare Protection Plan For iPod Touch Or iPod Classic - MB591LLA/ Extends Your Service Coverage To Up To Two Years/ Includes Both Phone And In Store Techinical Support', 59.00); +INSERT INTO Product( title, description, price) VALUES ( 'Nikon CoolPix S610 10 Megapixel Black Digital Camera - COOLPIXS610BK', 'Nikon CoolPix S610 10 Megapixel Black Digital Camera - COOLPIXS610BK/ 10.0 Megapixels/ 4x Zoom-NIKKOR Lens/ 3.0'' High-Resolution Wide-Viewing Angle LCD Monitor/ Scene Auto Selector/ Active Child Mode/ Smile And Food Mode/ Face-Priority AF/ In-Camera Red-Eye Fix/ D-Lighting/ Midnight Black Finish', 249.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony VAIO Black USB Docking Station - VGPUPR1', 'Sony VAIO Black USB Docking Station - VGPUPR1/ Perfect For The Constant Traveler Or Mobile Professional/ Easily Connect All Of Necessary Peripherals/ VGA Port/ 4 USB Ports/ Ethernet Port/ Headphone And Microphone Ports/ Compatible With VAIO CR Series, FZ Series, FW Series, NR Series And AR Series Notebooks/ Black Finish', 199.99); +INSERT INTO Product( title, description, price) VALUES ( 'Nikon SB-900 AF Speedlight In Black - SB900', 'Nikon AF Speedlight In Black - SB900/ Wireless Commander Mode/ Control Up To Three Remote/ 3 Light Distribution Patterns/ Flash Tube Overheat Protection/ Drip-Proof Mounting Foot Cover (Water Guard)/ Color Gel Filter Identification/ Black Finish', 499.00); +INSERT INTO Product( title, description, price) VALUES ( 'Denon D-M37 Black CD/AM/FM Micro System - DM37SBK', 'Denon D-M37 Black CD/AM/FM Micro System - DM37SBK/ 30 Watts x 2 Amplifier/ Precision Burr-Brown Audiophile Quality DACs/ MP3 And WMA Tracks Playback Capability/ European Engineered Loudspeakers/ 120mm Long-Throw D.D.L Double-Layered Cone Woofer/ 25mm Soft Dome Tweeter With Extended Response/ Triadic Noise Reduction Concept/ Portable Player Connectivity/ Black Finish', 399.00); +INSERT INTO Product( title, description, price) VALUES ( 'Griffin iPhone 3G Black Elan Form Hard-Shell Leather Case - 8223IP2EFRMB', 'Griffin iPhone 3G Black Elan Form Hard-Shell Leather Case - 8223IP2EFRMB/ Top-Grain Outer Shell Crafted From Hand-Matched Leather/ Protective Polycarbonate Inner Shell/ Easy Access To Controls/ Includes Stiff Polycarbonate Screen Protector & Premium Cleaning Cloth/ Black Finish (iPhone Not Included)', 24.00); +INSERT INTO Product( title, description, price) VALUES ( 'Speck Black ToughSkin Case For iPhone 3G - IPH3GBLKTS', 'Speck Black ToughSkin Case For iPhone 3G - IPH3GBLKTS/ Tough, Textured And Ruggedized Protection/ Bottom Hinges Open To Allow Docking/ Thicker Corners For Extra Protection/ Removable Rotating Belt Clip/ Lightweight Design/ Easy Access To All Ports & Controls/ Black Finish (iPhone Not Included)', 34.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon PIXMA iP2600 Photo Printer - IP2600', 'Canon PIXMA Photo Printer - IP2600/ 4800 x 1200 Color dpi/ Spectacular Resolution/ Fast Photo Printing/ FINE Technology/ 1,472 Precision Nozzles/ Auto Image Fix/ Easy-PhotoPrint EX Software/ 4 In 1 Or 2 In 1 Printing/ Energy Star Qualified/ Borderless 4'' x 6'' Print Approx. 55 Seconds/ Windows And Mac Compatible', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'Klipsch 5.25'' THX Ultra2 In-Ceiling White Loudspeaker - KS7502THX', 'Klipsch 5.25'' THX Ultra2 In-Ceiling White Loudspeaker - KS7502THX/ 100W Continuous/400W Peak Power Handling/ Dual 1'' Titanium Diaphragm Compression Drivers Mated To WDST Tractrix Horn Array/ Dual 5.25'' High-Output Cerametallic Cone Woofers/ MDF And Aluminum Motorboard/ABS Shell Enclosure/ White Finish/ Price Per Speaker', 1000.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon PIXMA Photo All-In-One Printer - MP620', 'Canon PIXMA Photo All-In-One Printer - MP620/ High Performance Printer And Copier, Scanner/ Easy Scroll Wheel/ Dual Paper Trays/ 2.5'' High Definition LCD Display/ Maximum 9600 x 2400 Color Dpi/ Automatic Image Optimization/ Quick Start/ Wi-Fi Ready/ Built-In Media Card Slot/ ENERGY STAR Qualified', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'TiVo HD XL Black Digital Video Recorder - TCD658000', 'TiVo HD XL Black Digital Video Recorder - TCD658000/ Search, Record And Watch Shows In HD/ Save Up To 150 Hours Of HD Programming At A Time/ Control Cable TV With Pause, Rewind, Fast-Forward, And Slow-Motion/ Record Two Shows At Once In HD/ Digital Transition Ready/ Backlit Remote Control/ Netflix Instant Streaming/ TiVo Service Required And Sold Separately', 599.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple 8GB Black 2nd Generation iPod Touch - MB528LLA', 'Apple 8GB Black 2nd Generation iPod Touch - MB528LLA/ Holds Up To 1,750 Songs In 128-Kbps AAC Format, 10,000 iPod-Viewable Photos And 10 Hours Of Video/ Wi-Fi (802.11b/g)/ Nike + iPod Support Built-In/ Maps Location-Based Service/ 3.5'' (Diagonal) Widescreen Multi-Touch Display/ 480x320-Pixel Resolution/ 480p And 576p Component TV Out/ Mac And Windows Compatible/ Black Finish', 229.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple 16GB Black 2nd Generation iPod Touch - MB531LLA', 'Apple 16GB Black 2nd Generation iPod Touch - MB531LLA/ Holds Up To 3,500 Songs In 128-Kbps AAC Format, 20,000 iPod-Viewable Photos And 20 Hours Of Video/ Wi-Fi (802.11b/g)/ Nike + iPod Support Built-In/ Maps Location-Based Service/ 3.5'' (Diagonal) Widescreen Multi-Touch Display/ 480x320-Pixel Resolution/ 480p And 576p Component TV Out/ Mac And Windows Compatible/ Black Finish', 299.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple 32GB Black 2nd Generation iPod Touch - MB533LLA', 'Apple 32GB Black 2nd Generation iPod Touch - MB533LLA/ Holds Up To 7,000 Songs In 128-Kbps AAC Format, 25,000 iPod-Viewable Photos And 40 Hours Of Video/ Wi-Fi (802.11b/g)/ Nike + iPod Support Built-In/ Maps Location-Based Service/ 3.5'' (Diagonal) Widescreen Multi-Touch Display/ 480x320-Pixel Resolution/ 480p And 576p Component TV Out/ Mac And Windows Compatible/ Black Finish', 399.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple 8GB Silver 4th Generation iPod Nano - MB598LLA', 'Apple 8GB Silver 4th Generation iPod Nano - MB598LLA/ Holds Up To 2,000 Songs In 128-Kbps AAC Format, 7,000 iPod-Viewable Photos And 8 Hours Of Video/ 2'' (Diagonal) Liquid Crystal Display With Blue-White LED Backlight/ 320-By-240-Pixel Resolution/ Give It A Shake To Shuffle Your Music/ Turn It Sideways To View Cover Flow/ Mac And Windows Compatible/ Silver Finish', 144.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple 8GB Blue 4th Generation iPod Nano - MB732LLA', 'Apple 8GB Blue 4th Generation iPod Nano - MB732LLA/ Holds Up To 2,000 Songs In 128-Kbps AAC Format, 7,000 iPod-Viewable Photos And 8 Hours Of Video/ 2'' (Diagonal) Liquid Crystal Display With Blue-White LED Backlight/ 320-By-240-Pixel Resolution/ Give It A Shake To Shuffle Your Music/ Turn It Sideways To View Cover Flow/ Mac And Windows Compatible/ Blue Finish', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple 8GB Pink 4th Generation iPod Nano - MB735LLA', 'Apple 8GB Pink 4th Generation iPod Nano - MB735LLA/ Holds Up To 2,000 Songs In 128-Kbps AAC Format, 7,000 iPod-Viewable Photos And 8 Hours Of Video/ 2'' (Diagonal) Liquid Crystal Display With Blue-White LED Backlight/ 320-By-240-Pixel Resolution/ Give It A Shake To Shuffle Your Music/ Turn It Sideways To View Cover Flow/ Mac And Windows Compatible/ Pink Finish', 144.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple 8GB Purple 4th Generation iPod Nano - MB739LLA', 'Apple 8GB Purple 4th Generation iPod Nano - MB739LLA/ Holds Up To 2,000 Songs In 128-Kbps AAC Format, 7,000 iPod-Viewable Photos And 8 Hours Of Video/ 2'' (Diagonal) Liquid Crystal Display With Blue-White LED Backlight/ 320-By-240-Pixel Resolution/ Give It A Shake To Shuffle Your Music/ Turn It Sideways To View Cover Flow/ Mac And Windows Compatible/ Purple Finish', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple 8GB Green 4th Generation iPod Nano - MB745LLA', 'Apple 8GB Green 4th Generation iPod Nano - MB745LLA/ Holds Up To 2,000 Songs In 128-Kbps AAC Format, 7,000 iPod-Viewable Photos And 8 Hours Of Video/ 2'' (Diagonal) Liquid Crystal Display With Blue-White LED Backlight/ 320-By-240-Pixel Resolution/ Give It A Shake To Shuffle Your Music/ Turn It Sideways To View Cover Flow/ Mac And Windows Compatible/ Green Finish', 149.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple 8GB Black 4th Generation iPod Nano - MB754LLA', 'Apple 8GB Black 4th Generation iPod Nano - MB754LLA/ Holds Up To 2,000 Songs In 128-Kbps AAC Format, 7,000 iPod-Viewable Photos And 8 Hours Of Video/ 2'' (Diagonal) Liquid Crystal Display With Blue-White LED Backlight/ 320-By-240-Pixel Resolution/ Give It A Shake To Shuffle Your Music/ Turn It Sideways To View Cover Flow/ Mac And Windows Compatible/ Black Finish', 144.00); +INSERT INTO Product( title, description, price) VALUES ( 'Apple 1GB Pink 2nd Generation iPod Shuffle - MB811LLA', 'Apple 1GB Pink 2nd Generation iPod Shuffle - MB811LLA/ Holds Up To 240 Songs In 128-Kbps AAC Format/ 12 Hours Of Continuous Playback/ Skip-Free Playback/ Battery Indicator/ Shuffle Switch/ Built-In Clip/ Mac And Windows Compatible/ Pink Finish', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sony BRAVIA Black SXRD 1080p Home Theater Front Projector - VPLHW10', 'Sony BRAVIA Black SXRD 1080p Home Theater Front Projector - VPLHW10/ SXRD 1920 x 1080p Full HD Panels/ 30,000:1 Dynamic Contrast Ratio/ Fully Digital Signal Processing/ 200Watts Ultra-High-Pressure Lamp/ Whisper-Quiet Fan Noise And Noise Reduction Function/ Two HDMI Inputs/ BRAVIA Theatre Sync/ Remote Commander/ Black Finish', 3499.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon PIXMA Black Photo Printer - IP4600', 'Canon PIXMA Black Photo Printer - IP4600/ Premium Printer With Individual Ink Tanks And Built-In Auto Duplex/ Print 4'' x 6'' Photo In 20 Seconds/ Dual Paper Trays/ Maximum 9600 x 2400 Color Dpi/ Automatic Image Optimization/ ENERGY STAR Qualified/ Black Finish', 99.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon PIXMA Photo All-In-One Printer - MP980', 'Canon PIXMA Photo All-In-One Printer - MP980/ High Performance Wireless Printer, Copier And Scanner/ Easy Scroll Wheel/ 3.5'' High Definition LCD Display/ Maximum 9600 x 2400 Color Dpi/ Six Individual Inks Tanks/ Auto Duplex Print/ Smart Copying/ Automatic Image Optimization/ No Warm-Up/ ENERGY STAR Qualified', 299.00); +INSERT INTO Product( title, description, price) VALUES ( 'Nintendo DS Lite Cobalt/Black Portable Gaming System - NDSUSGBMKB', 'Nintendo DS Lite Cobalt/Black Portable Gaming System - NDSUSGBMKB/ Dual 3'' TFT Color LCD Touchscreens/ Slimmer Design/ Dual Slot Compatibility (DS Lite/Game Boy Advance Game Paks)/ Twin Ultra Bright LCD Screens/ Up To 19 Hours Continuous Gameplay/ Nintendo Wi-Fi Connection/ Impressive 3D Graphics/ Dual Stereo Speakers/ Cobalt and Black Finish', 139.00); +INSERT INTO Product( title, description, price) VALUES ( 'Nintendo DS Lite Onyx Black Portable Gaming System - NDSUSGSKB', 'Nintendo DS Lite Onyx Black Portable Gaming System - NDSUSGSKB/ Dual 3'' TFT Color LCD Touchscreens/ Slimmer Design/ Dual Slot Compatibility (DS Lite/Game Boy Advance Game Paks)/ Twin Ultra Bright LCD Screens/ Up To 19 Hours Continuous Gameplay/ Nintendo Wi-Fi Connection/ Impressive 3D Graphics/ Dual Stereo Speakers/ Onyx Black Finish', 139.00); +INSERT INTO Product( title, description, price) VALUES ( 'Nintendo DS Lite Metallic Silver Portable Gaming System - NDSUSGSVB', 'Nintendo DS Lite Metallic Silver Portable Gaming System - NDSUSGSVB/ Dual 3'' TFT Color LCD Touchscreens/ Slimmer Design/ Dual Slot Compatibility (DS Lite/Game Boy Advance Game Paks)/ Twin Ultra Bright LCD Screens/ Up To 19 Hours Continuous Gameplay/ Nintendo Wi-Fi Connection/ Impressive 3D Graphics/ Dual Stereo Speakers/ Metallic Silver Finish', 139.00); +INSERT INTO Product( title, description, price) VALUES ( 'Nintendo DS Lite Metallic Rose Portable Gaming System - NDSUSGSZPB', 'Nintendo DS Lite Metallic Rose Portable Gaming System - NDSUSGSZPB/ Dual 3'' TFT Color LCD Touchscreens/ Slimmer Design/ Dual Slot Compatibility (DS Lite/Game Boy Advance Game Paks)/ Twin Ultra Bright LCD Screens/ Up To 19 Hours Continuous Gameplay/ Nintendo Wi-Fi Connection/ Impressive 3D Graphics/ Dual Stereo Speakers/ Metallic Rose Finish', 139.00); +INSERT INTO Product( title, description, price) VALUES ( 'Case Logic Vertical Universal Leather BlackBerry Case - CLP104BB', 'Case Logic Vertical Universal Leather BlackBerry Case - CLP104BB/ 360 Degree Swivel Belt Clip/ Magnetic Closure/ Soft Internal Lining/ Expandable Elastic Sides/ Compatible With Most BlackBerrys/ Leather Fabric/ Black Finish', 15.00); +INSERT INTO Product( title, description, price) VALUES ( 'Nintendo DS Lite Crimson/Black Portable Gaming System - NDSUSGSRMKB', 'Nintendo DS Lite Crimson/Black Portable Gaming System - NDSUSGSRMKB/ Dual 3'' TFT Color LCD Touchscreens/ Slimmer Design/ Dual Slot Compatibility (DS Lite/Game Boy Advance Game Paks)/ Twin Ultra Bright LCD Screens/ Up To 19 Hours Continuous Gameplay/ Nintendo Wi-Fi Connection/ Impressive 3D Graphics/ Dual Stereo Speakers/ Crimson/Black Finish', 139.00); +INSERT INTO Product( title, description, price) VALUES ( 'BlueAnt Bluetooth Voice Control Headset - V1', 'BlueAnt Bluetooth Voice Control Headset - V1/ Voice Control User Interface/ Voice Isolation Technology/ Dual Microphones/ Pairs With Up To 8 Bluetooth Devices/ Up To 5 Hours Talk-Time/ 3 Charging Options', 119.00); +INSERT INTO Product( title, description, price) VALUES ( 'Netgear Prosafe 5 Port Gigabit Ethernet Desktop Switch - GS105NA', 'Netgear Prosafe 5 Port Gigabit Ethernet Desktop Switch - GS105NA/ Auto-Switching Ethernet Connection/ Supports Windows And Macintosh Platforms/ Dual Color LEDs/ AutoUplink Technology/ Compact Metal Case/ Fanless Design/ Plug-And-Play Installation', 55.00); +INSERT INTO Product( title, description, price) VALUES ( 'Jabra Bluetooth Headset - BT2070', 'Jabra Bluetooth Headset - BT2070/ Up To 5.5 Hours Talk Time/ Up To 200 Hours Standby Time/ Earhook Included/ Bluetooth 2.0+ EDR & eSCO Technology/ Auto-Pairing/ Discreet Light/ Answer/End, Redial And Voice Dial Features/ USB Micro-B, 5-Pin Charging Plug', 49.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon Printer Ink Cartridge 4 Colors Pack - 2946B004', 'Canon Printer Ink Cartridge 4 Colors Pack - 2946B004/ FINE Technology For Exceptional Sharpness And Detail/ Compatible With PIXMA iP3600, PIXMA iP4600, PIXMA MP620 And PIXMA MP980/ Includes 4 Ink Tanks (Black, Cyan, Magenta, Yellow)', 47.00); +INSERT INTO Product( title, description, price) VALUES ( 'Canon PIXMA Photo All-In-One Printer - MP480', 'Canon PIXMA Photo All-In-One Printer - MP480/ High Performance Printer, Copier And Scanner/ 1.8'' TFT Display/ Maximum 2400 x 4800 Color Dpi/ Smart Scanning/ Quick Start/ Built-In Media Card Slot/ ENERGY STAR Qualified', 99.00); +INSERT INTO Product( title, description, price) VALUES ( 'Sanus 30'' - 58'' VisionMount Flat Panel TV Black Tilting Wall Mount - LT25B1', 'Sanus 30'' - 58'' VisionMount Flat Panel TV Black Tilting Wall Mount - LT25B1/ Lateral Shift Adjustment/ Virtual Axis/ Height and Level Adjustments/ ClickStand/ ClickFit System/ Open Wall Plate/ Black Finish', 199.00); diff --git a/integration/quarkus-keycloak-authorization/src/test/java/com/devonfw/quarkus/keycloak/authorization/NativePolicyEnforcerIT.java b/integration/quarkus-keycloak-authorization/src/test/java/com/devonfw/quarkus/keycloak/authorization/NativePolicyEnforcerIT.java new file mode 100644 index 0000000..71482c3 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/test/java/com/devonfw/quarkus/keycloak/authorization/NativePolicyEnforcerIT.java @@ -0,0 +1,10 @@ +package com.devonfw.quarkus.keycloak.authorization; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +/** + * @author Pedro Igor + */ +@QuarkusIntegrationTest +public class NativePolicyEnforcerIT extends PolicyEnforcerTest { +} diff --git a/integration/quarkus-keycloak-authorization/src/test/java/com/devonfw/quarkus/keycloak/authorization/PolicyEnforcerTest.java b/integration/quarkus-keycloak-authorization/src/test/java/com/devonfw/quarkus/keycloak/authorization/PolicyEnforcerTest.java new file mode 100644 index 0000000..7c0c7b3 --- /dev/null +++ b/integration/quarkus-keycloak-authorization/src/test/java/com/devonfw/quarkus/keycloak/authorization/PolicyEnforcerTest.java @@ -0,0 +1,40 @@ +package com.devonfw.quarkus.keycloak.authorization; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.keycloak.client.KeycloakTestClient; +import io.restassured.RestAssured; + +@QuarkusTest +public class PolicyEnforcerTest { + static { + RestAssured.useRelaxedHTTPSValidation(); + } + + KeycloakTestClient keycloakClient = new KeycloakTestClient(); + + @Test + public void testAccessUserResource() { + + RestAssured.given().auth().oauth2(getAccessToken("alice")).when().get("/product/v1/users").then().statusCode(200); + RestAssured.given().auth().oauth2(getAccessToken("jdoe")).when().get("/product/v1/users").then().statusCode(200); + } + + @Test + public void testAccessAdminResource() { + + RestAssured.given().auth().oauth2(getAccessToken("alice")).when().get("/product/v1/admin").then().statusCode(403); + RestAssured.given().auth().oauth2(getAccessToken("jdoe")).when().get("/product/v1/admin").then().statusCode(403); + RestAssured.given().auth().oauth2(getAccessToken("admin")).when().get("/product/v1/admin").then().statusCode(200); + } + + /* + * @Test public void testPublicResource() { RestAssured.given() .when().get("/api/public") .then() .statusCode(204); } + */ + + private String getAccessToken(String userName) { + + return this.keycloakClient.getAccessToken(userName); + } +} diff --git a/integration/spring_jpa/.gitignore b/integration/spring_jpa/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/integration/spring_jpa/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/integration/spring_jpa/.mvn/wrapper/maven-wrapper.jar b/integration/spring_jpa/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..c1dd12f Binary files /dev/null and b/integration/spring_jpa/.mvn/wrapper/maven-wrapper.jar differ diff --git a/integration/spring_jpa/.mvn/wrapper/maven-wrapper.properties b/integration/spring_jpa/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..b74bf7f --- /dev/null +++ b/integration/spring_jpa/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar diff --git a/integration/spring_jpa/README.adoc b/integration/spring_jpa/README.adoc new file mode 100644 index 0000000..1e1aa00 --- /dev/null +++ b/integration/spring_jpa/README.adoc @@ -0,0 +1,31 @@ += JPA Example + +Examples prepared to explain the below concepts. + +1. Use Lazy loading +2. Usage of java.time.localdate. +3. Enum usage with converter + + +=== Lazy loading + +Always advised to use lazy loading. Lazy loading fetches data only when it is really required. This example uses FetchType Lazy, the invited guests will be loaded only on demand. + +A `SELECT` query applied for fetching booking or bookings will not fetch any invited guests. The below statement fetches all guests for a particular booking. It executes a `SELECT` query with booking id as arguement. + `BookingEntity.getInvitedGuests()` + + +=== Enum + +Using Converter annotation convert an entity attribute to a database value and vice versa. In this example, enum defined as BOOKED("B"), and NOTBOOKED("N") and CANCELED ("C"). This helps to make sure the code is not broken by refactorings. + +The other two ways to deal with enums are by their `Ordinal` or by `name`. `Ordinal` may not be a good choice, if someone changes the places of the items in enum, wrong integer value may be stored. + +=== LocalDateTime + +java.time.LocalDateTime used instead of java.util.date, major benefits are: + +* LocalDateTime API has its own format/parse methods. +* Addition/subtraction operation are easier (minusMinutes,plusDays etc.) + + diff --git a/integration/spring_jpa/mvnw b/integration/spring_jpa/mvnw new file mode 100644 index 0000000..8a8fb22 --- /dev/null +++ b/integration/spring_jpa/mvnw @@ -0,0 +1,316 @@ +#!/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 +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + 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 + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`\\unset -f command; \\command -v java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/integration/spring_jpa/mvnw.cmd b/integration/spring_jpa/mvnw.cmd new file mode 100644 index 0000000..1d8ab01 --- /dev/null +++ b/integration/spring_jpa/mvnw.cmd @@ -0,0 +1,188 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/integration/spring_jpa/pom.xml b/integration/spring_jpa/pom.xml new file mode 100644 index 0000000..b62d5e0 --- /dev/null +++ b/integration/spring_jpa/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.3 + + + com.devonfw.examples.dataaccess.springjpa + spring_jpa + 0.0.1-SNAPSHOT + spring_jpa + devonfw jpa example (lazy loading, timestamp, enums) + + 11 + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + javax.persistence + javax.persistence-api + + + org.springframework.data + spring-data-jpa + + + + + com.h2database + h2 + + + + + org.flywaydb + flyway-core + + + + org.projectlombok + lombok + true + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + + diff --git a/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/SpringJpaApplication.java b/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/SpringJpaApplication.java new file mode 100644 index 0000000..63ea02d --- /dev/null +++ b/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/SpringJpaApplication.java @@ -0,0 +1,13 @@ +package com.devonfw.examples.dataaccess.springjpa; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringJpaApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringJpaApplication.class, args); + } + +} diff --git a/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/model/BookingEntity.java b/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/model/BookingEntity.java new file mode 100644 index 0000000..af2d139 --- /dev/null +++ b/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/model/BookingEntity.java @@ -0,0 +1,45 @@ +package com.devonfw.examples.dataaccess.springjpa.domain.model; + +import static javax.persistence.CascadeType.ALL; + +import java.time.LocalDateTime; +import java.util.Set; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import javax.persistence.Table; + +import org.hibernate.annotations.BatchSize; + +import com.devonfw.examples.dataaccess.springjpa.general.domain.model.ApplicationPersistenceEntity; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Setter +@Getter +@ToString(callSuper = true, includeFieldNames = true) +@Entity +@Table (name="booking") +public class BookingEntity extends ApplicationPersistenceEntity { + + private String name; + + private String bookingToken; + + private String comment; + + private LocalDateTime bookingDate; + + private String email; + + private BookingStatus bookingStatus; + + @OneToMany(cascade = ALL, fetch = FetchType.LAZY, orphanRemoval = true) + @JoinColumn(name = "id_booking") + @BatchSize(size = 2) + private Set invitedGuests; +} diff --git a/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/model/BookingStatus.java b/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/model/BookingStatus.java new file mode 100644 index 0000000..a5c5f57 --- /dev/null +++ b/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/model/BookingStatus.java @@ -0,0 +1,22 @@ +package com.devonfw.examples.dataaccess.springjpa.domain.model; + +/** + * BookingStatus enumerator helps to handle Status in a better way. Here the + * code associated with each enum is persisted to the database instead of the + * whole string, by the BookingStatusConverter. + */ +public enum BookingStatus { + BOOKED("B"), CANCELED("C"), NOTBOOKED("N"); + + private String code; + + BookingStatus(String code) { + + this.code = code; + } + + public String getCode() { + + return this.code; + } +} diff --git a/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/model/InvitedGuestEntity.java b/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/model/InvitedGuestEntity.java new file mode 100644 index 0000000..31f90c9 --- /dev/null +++ b/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/model/InvitedGuestEntity.java @@ -0,0 +1,22 @@ +package com.devonfw.examples.dataaccess.springjpa.domain.model; + +import javax.persistence.Entity; +import javax.persistence.Table; + +import com.devonfw.examples.dataaccess.springjpa.general.domain.model.ApplicationPersistenceEntity; + +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +@Setter +@Getter +@ToString(callSuper = true, includeFieldNames = true) +@Entity +@Table (name="Invited_Guest") +public class InvitedGuestEntity extends ApplicationPersistenceEntity { + + private String guestToken; + + private String email; + +} diff --git a/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/model/converter/BookingStatusConverter.java b/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/model/converter/BookingStatusConverter.java new file mode 100644 index 0000000..b3aeefe --- /dev/null +++ b/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/model/converter/BookingStatusConverter.java @@ -0,0 +1,46 @@ +package com.devonfw.examples.dataaccess.springjpa.domain.model.converter; + +import java.util.stream.Stream; + +import javax.persistence.AttributeConverter; +import javax.persistence.Converter; + +import com.devonfw.examples.dataaccess.springjpa.domain.model.BookingStatus; +/** + * BookingStatusConverter defines a mapping between BookinStatus enum and the + * database column booking_status at booking table. + * + */ +@Converter(autoApply = true) +public class BookingStatusConverter + implements + AttributeConverter { + + /** + * Converts BookingStatus to string 'code', eg: `BOOKED` to 'B'. + */ + @Override + public String convertToDatabaseColumn(BookingStatus status) { + + if (status == null) { + return null; + } + return status.getCode(); + } + + /** + * Converts the string 'code' to BookingStatus eg: 'B' to `BOOKED` + */ + @Override + public BookingStatus convertToEntityAttribute(final String code) { + + if (code == null) { + return null; + } + + return Stream.of(BookingStatus.values()) + .filter(c -> c.getCode().equals(code)).findFirst() + .orElseThrow(IllegalArgumentException::new); + } + +} diff --git a/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/repository/BookingRepository.java b/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/repository/BookingRepository.java new file mode 100644 index 0000000..9af33ce --- /dev/null +++ b/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/domain/repository/BookingRepository.java @@ -0,0 +1,11 @@ +package com.devonfw.examples.dataaccess.springjpa.domain.repository; + +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import com.devonfw.examples.dataaccess.springjpa.domain.model.BookingEntity; + +@Repository +public interface BookingRepository extends CrudRepository { + +} diff --git a/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/general/domain/model/ApplicationPersistenceEntity.java b/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/general/domain/model/ApplicationPersistenceEntity.java new file mode 100644 index 0000000..e4fa679 --- /dev/null +++ b/integration/spring_jpa/src/main/java/com/devonfw/examples/dataaccess/springjpa/general/domain/model/ApplicationPersistenceEntity.java @@ -0,0 +1,28 @@ +package com.devonfw.examples.dataaccess.springjpa.general.domain.model; + +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; +import javax.persistence.Version; + +import lombok.Getter; +import lombok.Setter; + +/** + * Abstract Entity for all Entities with an id and a version field. + * + */ + +@Setter +@Getter +@MappedSuperclass +public abstract class ApplicationPersistenceEntity { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + private Long id; + + @Version + private Integer modificationCounter; +} \ No newline at end of file diff --git a/integration/spring_jpa/src/main/resources/application.properties b/integration/spring_jpa/src/main/resources/application.properties new file mode 100644 index 0000000..8ae5125 --- /dev/null +++ b/integration/spring_jpa/src/main/resources/application.properties @@ -0,0 +1,11 @@ +logging.level.org.hibernate.SQL=DEBUG +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.format_sql=true +logging.level.org.hibernate.type=DEBUG + +logging.level.org.hibernate.type.descriptor.sql.BasicBinder=DEBUG + +# Flyway for Database Setup and Migrations +spring.flyway.enabled=true +spring.flyway.clean-on-validation-error=true +spring.flyway.locations=classpath:db/migration \ No newline at end of file diff --git a/integration/spring_jpa/src/main/resources/db/migration/V0001__R002_Create_schema.sql b/integration/spring_jpa/src/main/resources/db/migration/V0001__R002_Create_schema.sql new file mode 100644 index 0000000..45d28bb --- /dev/null +++ b/integration/spring_jpa/src/main/resources/db/migration/V0001__R002_Create_schema.sql @@ -0,0 +1,27 @@ +CREATE SEQUENCE HIBERNATE_SEQUENCE START WITH 100000; + + +CREATE TABLE Booking ( + id BIGINT NOT NULL AUTO_INCREMENT, + modification_counter INTEGER NOT NULL, + id_user BIGINT, + name VARCHAR (255) NOT NULL, + booking_token VARCHAR (255), + comment VARCHAR (4000), + email VARCHAR(255) NOT NULL, + booking_date TIMESTAMP NOT NULL, + expiration_date TIMESTAMP, + booking_status VARCHAR(1), + CONSTRAINT PK_Booking PRIMARY KEY(id) +); + +CREATE TABLE Invited_Guest ( + id BIGINT NOT NULL AUTO_INCREMENT, + modification_counter INTEGER NOT NULL, + id_booking BIGINT , + guest_token VARCHAR (255), + email VARCHAR (60), + accepted BOOLEAN, + CONSTRAINT PK_InvitedGuest PRIMARY KEY(id), + CONSTRAINT FK_InvitedGuest_idBooking FOREIGN KEY(id_booking) REFERENCES Booking(id) NOCHECK +); diff --git a/integration/spring_jpa/src/main/resources/db/migration/V0002__R002_Master_data.sql b/integration/spring_jpa/src/main/resources/db/migration/V0002__R002_Master_data.sql new file mode 100644 index 0000000..c9c3f80 --- /dev/null +++ b/integration/spring_jpa/src/main/resources/db/migration/V0002__R002_Master_data.sql @@ -0,0 +1,31 @@ +INSERT INTO booking( + id, modification_counter, id_user, + NAME, booking_token, comment, email, + booking_date, expiration_date, + booking_status +) +VALUES + ( + 0, 0, 0, + 'user0', 'CB_20170509_123502555Z', 'Booking Type CSR', 'user0@mail.com', + Dateadd('DAY', 5, CURRENT_TIMESTAMP), + Dateadd( + 'DAY', + 5, + Dateadd('HOUR', -1, CURRENT_TIMESTAMP) + ), + 'C' + ); +INSERT INTO Invited_Guest( + id, modification_counter, id_booking, + guest_token, email, accepted +) +VALUES + ( + 0, + 0, + 0, + 'GB_20170510_02350266501Z', + 'guest0@mail.com', + true + ); \ No newline at end of file diff --git a/integration/spring_jpa/src/test/java/com/devonfw/examples/dataaccess/springjpa/BookingRepositoryTest.java b/integration/spring_jpa/src/test/java/com/devonfw/examples/dataaccess/springjpa/BookingRepositoryTest.java new file mode 100644 index 0000000..947c71b --- /dev/null +++ b/integration/spring_jpa/src/test/java/com/devonfw/examples/dataaccess/springjpa/BookingRepositoryTest.java @@ -0,0 +1,111 @@ +package com.devonfw.examples.dataaccess.springjpa; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.time.LocalDateTime; +import java.util.HashSet; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; +import javax.transaction.Transactional; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import com.devonfw.examples.dataaccess.springjpa.domain.model.BookingEntity; +import com.devonfw.examples.dataaccess.springjpa.domain.model.BookingStatus; +import com.devonfw.examples.dataaccess.springjpa.domain.model.InvitedGuestEntity; +import com.devonfw.examples.dataaccess.springjpa.domain.repository.BookingRepository; + +/** + * Unit test prepared to test the following features: + * + * LocalDateTime - BookingDate is time.LocalDateTime instead of util.Date + * + * Enum (using converter) - BookingStatus is assigned BOOKED but + * the database stores only the code 'B'. To verify actual value (code) from the database, applying native + * query to retrieve row data. + * + * Lazy loading - Lazy loading verified by looking at queries applied against database from the logs. + * While applying findById executes query to fetch data from booking table not querying against invited + * guests. But when we verify `getInvitedGuests().size()` the invited guests query executes. + * + */ +@ExtendWith(SpringExtension.class) +@SpringBootTest +public class BookingRepositoryTest { + + @Autowired + private BookingRepository bookingRepository; + + @PersistenceContext + private EntityManager em; + + @Test + @Transactional + public void givenBooking_whenSave_thenGetOk() { + + // Booking + Invited Guests creation + BookingEntity newBooking = getBooking("booking1"); + BookingEntity booking = this.bookingRepository.save(newBooking); + + // Retrieving the booking: + Optional foundBooking = this.bookingRepository + .findById(booking.getId()); + if (foundBooking.isPresent()) { + booking = foundBooking.get(); + assertEquals(booking.getName(), newBooking.getName()); + assertEquals(booking.getBookingDate(), newBooking.getBookingDate()); + assertEquals(booking.getInvitedGuests().size(), 10); + } + + // Native query used here to get the exact Enum data from the DB. + + Query q = this.em.createNativeQuery( + "SELECT b.name,b.booking_status FROM Booking b where id=" + + booking.getId()); + List bookings = q.getResultList(); + assertEquals(bookings.size(), 1); + for (Object[] bookingObject : bookings) { + assertEquals(bookingObject[0], newBooking.getName()); + assertEquals(bookingObject[1], BookingStatus.BOOKED.getCode()); + } + + } + + private BookingEntity getBooking(String bookingName) { + + BookingEntity booking = new BookingEntity(); + booking.setName(bookingName); + booking.setBookingStatus(BookingStatus.BOOKED); + booking.setBookingDate(LocalDateTime.now()); + booking.setName(bookingName); + booking.setBookingToken("token"); + booking.setComment("comment"); + booking.setEmail(bookingName + "@gmail.com"); + booking.setInvitedGuests(getInvitedGuest(bookingName)); + return booking; + } + + private Set getInvitedGuest(String bookingName) { + + Set guests = new HashSet<>(); + for (int i = 0; i < 10; i++) { + InvitedGuestEntity guest = new InvitedGuestEntity(); + guest.setGuestToken( + String.format("%s-guest%stoken", bookingName, i)); + guest.setEmail( + String.format("%s.user%s@gmail.com", bookingName, i)); + guests.add(guest); + } + return guests; + } + +}