├── rcloud-gist-service ├── src │ ├── main │ │ ├── resources │ │ │ ├── META-INF │ │ │ │ └── spring │ │ │ │ │ └── .gitkeep │ │ │ ├── logback-spring.xml │ │ │ └── application.yml │ │ ├── pkg │ │ │ └── home │ │ │ │ ├── systemd.service │ │ │ │ ├── logback.xml │ │ │ │ ├── LICENSE │ │ │ │ ├── service.conf │ │ │ │ └── application.yml │ │ └── java │ │ │ └── com │ │ │ └── mangosolutions │ │ │ └── rcloud │ │ │ └── rawgist │ │ │ ├── repository │ │ │ ├── GistIdGenerator.java │ │ │ ├── GistRepositoryFactory.java │ │ │ ├── git │ │ │ │ ├── RepositoryStorageLocator.java │ │ │ │ ├── MetadataStore.java │ │ │ │ ├── FileContentCache.java │ │ │ │ ├── HistoryCache.java │ │ │ │ ├── CommentStore.java │ │ │ │ ├── UUIDGistIdGenerator.java │ │ │ │ ├── GitGistRepositoryFactory.java │ │ │ │ ├── SymetricFourPartRepositoryStorageLocator.java │ │ │ │ ├── DefaultFileContentCache.java │ │ │ │ ├── DefaultHistoryCache.java │ │ │ │ ├── AsymetricFourFolderRepositoryStorageLocator.java │ │ │ │ ├── CollaborationDataStore.java │ │ │ │ ├── GistMetadataStore.java │ │ │ │ ├── GistCommentStore.java │ │ │ │ ├── InitRepositoryLayoutOperation.java │ │ │ │ ├── GistMetadata.java │ │ │ │ └── BareRmCommand.java │ │ │ ├── GistErrorCode.java │ │ │ ├── GistRepositoryError.java │ │ │ ├── GistAccessDeniedException.java │ │ │ ├── GistRepositoryException.java │ │ │ ├── security │ │ │ │ ├── PermissiveGistSecurityManager.java │ │ │ │ ├── CollaborationGrantedAuthorityResolver.java │ │ │ │ ├── CollaborationGrantedAuthority.java │ │ │ │ └── SimpleGistSecurityManager.java │ │ │ ├── GistCommentRepository.java │ │ │ ├── GistSecurityManager.java │ │ │ ├── GistRepository.java │ │ │ ├── GistError.java │ │ │ └── GistRepositoryService.java │ │ │ ├── Application.java │ │ │ ├── GistUsersProperties.java │ │ │ ├── api │ │ │ ├── RedirectController.java │ │ │ ├── UserRestController.java │ │ │ └── ControllerUrlResolver.java │ │ │ ├── SessionKeyServerWebAuthenticationDetailsSource.java │ │ │ ├── model │ │ │ ├── GistComment.java │ │ │ ├── FileDefinition.java │ │ │ ├── GitChangeStatus.java │ │ │ ├── GistRequest.java │ │ │ ├── GistIdentity.java │ │ │ ├── GistCommentResponse.java │ │ │ ├── Fork.java │ │ │ └── GistHistory.java │ │ │ ├── CacheConfigurationProperties.java │ │ │ ├── GistServiceProperties.java │ │ │ ├── RequestParameterAuthenticationFilter.java │ │ │ ├── SessionKeyServerProperties.java │ │ │ ├── ContentNegotiationConfiguration.java │ │ │ └── ManagementSecurityConfiguration.java │ └── test │ │ ├── resources │ │ ├── logback.xml │ │ └── application-test.yml │ │ └── java │ │ └── com │ │ └── mangosolutions │ │ └── rcloud │ │ └── rawgist │ │ ├── ContextStartStopTest.java │ │ ├── repository │ │ └── GistErrorTest.java │ │ ├── GrantedAuthorityFactoryTest.java │ │ └── api │ │ ├── UserRestControllerTest.java │ │ └── GistTestHelper.java ├── build.gradle └── README.md ├── rcloud-gistproxy-service ├── src │ ├── main │ │ ├── resources │ │ │ ├── META-INF │ │ │ │ └── spring │ │ │ │ │ └── .gitkeep │ │ │ ├── application-github.yml │ │ │ ├── application-rcloudgist.yml │ │ │ ├── application.yml │ │ │ └── logback-spring.xml │ │ ├── pkg │ │ │ └── home │ │ │ │ ├── systemd.service │ │ │ │ ├── logback.xml │ │ │ │ ├── LICENSE │ │ │ │ ├── service.conf │ │ │ │ └── application.yml │ │ └── java │ │ │ └── com │ │ │ └── mangosolutions │ │ │ └── rcloud │ │ │ └── gists │ │ │ ├── Application.java │ │ │ ├── RCloudGistsServiceConfiguration.java │ │ │ ├── GistsServiceConfiguration.java │ │ │ └── filters │ │ │ ├── SessionTokenParameterToHeaderFilter.java │ │ │ ├── ZuulRequestUrlResolver.java │ │ │ ├── ZuulResponseContent.java │ │ │ ├── AcceptContentTypeReWritingFilter.java │ │ │ └── HeaderUrlRewritingFilter.java │ └── test │ │ ├── resources │ │ ├── application.yml │ │ └── logback.xml │ │ └── java │ │ └── com │ │ └── mangosolutions │ │ └── rcloud │ │ └── gists │ │ └── filters │ │ ├── ZuulResponseContentTest.java │ │ ├── HeaderUrlRewritingFilterTest.java │ │ └── JsonContentUrlRewritingFilterTest.java ├── build.gradle └── README.md ├── .gitattributes ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── salt └── roots │ ├── pillar │ ├── settings.sls │ └── top.sls │ └── salt │ ├── top.sls │ ├── base │ └── init.sls │ └── rcloud │ └── init.sls ├── settings.gradle ├── rcloud-sessionkey-lib ├── src │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── mangosolutions │ │ │ └── rcloud │ │ │ └── sessionkeyauth │ │ │ ├── SessionKeyServerResult.java │ │ │ ├── AuthorityResolver.java │ │ │ ├── AnonymousUserAuthorityResolver.java │ │ │ ├── AnonymousUser.java │ │ │ ├── UserAuthorityResolver.java │ │ │ ├── GrantedAuthorityFactory.java │ │ │ ├── SessionKeyServerAuthenticationDetails.java │ │ │ ├── SessionKeyServerResponse.java │ │ │ └── KeyServerConfiguration.java │ └── test │ │ └── java │ │ └── com │ │ └── mangosolutions │ │ └── rcloud │ │ └── sessionkeyauth │ │ └── GrantedAuthorityFactoryTest.java └── build.gradle ├── LICENSE ├── .travis.yml └── gradlew.bat /rcloud-gist-service/src/main/resources/META-INF/spring/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/resources/META-INF/spring/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | gradlew text eol=lf 2 | *.sh text eol=lf 3 | *.conf text eol=lf 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MangoTheCat/rcloud-gist-services/master/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build 3 | target 4 | .classpath 5 | .project 6 | .springBeans 7 | .settings/ 8 | 9 | .Rproj.user 10 | .Rbuildignore 11 | .Rhistory 12 | .Rproj 13 | .vagrant 14 | bin 15 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/pkg/home/systemd.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description="@summary@" 3 | After=syslog.target 4 | 5 | [Service] 6 | User=@user@ 7 | Group=@group@ 8 | ExecStart=@jarPath@ 9 | SuccessExitStatus=143 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/pkg/home/systemd.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description="@summary@" 3 | After=syslog.target 4 | 5 | [Service] 6 | User=@user@ 7 | Group=@group@ 8 | ExecStart=@jarPath@ 9 | SuccessExitStatus=143 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Feb 23 17:35:35 GMT 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-bin.zip 7 | -------------------------------------------------------------------------------- /salt/roots/pillar/settings.sls: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************/ 7 | rcloud: 8 | version: "1.7" 9 | -------------------------------------------------------------------------------- /salt/roots/pillar/top.sls: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************/ 7 | base: 8 | '*': 9 | - settings 10 | -------------------------------------------------------------------------------- /salt/roots/salt/top.sls: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************/ 7 | 8 | #sudo salt-call --local -l info state.highstate 9 | base: 10 | '*': 11 | - base 12 | - rcloud 13 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/resources/application-github.yml: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************* 7 | zuul: 8 | routes: 9 | default: 10 | path: /** 11 | url: ${github.api.url:https://api.github.com} 12 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | 8 | rootProject.name = 'rcloud-gist-service' 9 | 10 | include 'rcloud-gistproxy-service', 11 | 'rcloud-gist-service', 12 | 'rcloud-sessionkey-lib' 13 | -------------------------------------------------------------------------------- /salt/roots/salt/base/init.sls: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************/ 7 | system-uptodate: 8 | pkg.uptodate: 9 | - name: Ensure system is up to date. 10 | - refresh: True 11 | 12 | iptables: 13 | service.dead: 14 | - enable: False 15 | -------------------------------------------------------------------------------- /rcloud-sessionkey-lib/src/main/java/com/mangosolutions/rcloud/sessionkeyauth/SessionKeyServerResult.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.sessionkeyauth; 8 | 9 | public enum SessionKeyServerResult { 10 | YES, NO, SUPERCEDED 11 | } 12 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/GistIdGenerator.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository; 8 | 9 | public interface GistIdGenerator { 10 | 11 | String generateId(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/resources/application-rcloudgist.yml: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************* 7 | 8 | zuul: 9 | routes: 10 | default: 11 | path: /** 12 | url: ${github.api.url:https://api.github.com} 13 | gists: 14 | url: ${rcloud.gists.url:http://localhost:13020} 15 | stripPrefix: false 16 | 17 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/GistRepositoryFactory.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository; 8 | 9 | import java.io.File; 10 | 11 | public interface GistRepositoryFactory { 12 | 13 | GistRepository getRepository(File folder); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/RepositoryStorageLocator.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import java.io.File; 10 | 11 | public interface RepositoryStorageLocator { 12 | 13 | File getStoragePath(String gistId); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /rcloud-sessionkey-lib/src/main/java/com/mangosolutions/rcloud/sessionkeyauth/AuthorityResolver.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.sessionkeyauth; 8 | 9 | import org.springframework.security.core.GrantedAuthority; 10 | 11 | public interface AuthorityResolver { 12 | 13 | GrantedAuthority resolve(String username); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/MetadataStore.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import java.io.File; 10 | 11 | public interface MetadataStore { 12 | 13 | GistMetadata load(File store); 14 | 15 | GistMetadata save(File store, GistMetadata metadata); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************* 7 | spring: 8 | profiles: 9 | active: rcloudgist 10 | 11 | 12 | zuul: 13 | routes: 14 | default: 15 | path: /** 16 | url: ${github.api.url:https://api.github.com} 17 | gists: 18 | url: ${rcloud.gists.url:http://localhost:13020} 19 | stripPrefix: false 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/FileContentCache.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import com.mangosolutions.rcloud.rawgist.model.FileContent; 10 | 11 | public interface FileContentCache { 12 | 13 | FileContent load(String contentId, String path); 14 | 15 | FileContent save(String contentId, String path, FileContent content); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/HistoryCache.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import java.util.List; 10 | 11 | import com.mangosolutions.rcloud.rawgist.model.GistHistory; 12 | 13 | public interface HistoryCache { 14 | 15 | public List load(String commitId); 16 | 17 | public List save(String commitId, List history); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/CommentStore.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import java.io.File; 10 | import java.util.List; 11 | 12 | import com.mangosolutions.rcloud.rawgist.model.GistCommentResponse; 13 | 14 | public interface CommentStore { 15 | 16 | List load(File store); 17 | 18 | List save(File store, List comments); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************* 7 | server: 8 | port: 13010 9 | 10 | management: 11 | port: 13011 12 | security: 13 | enabled: true 14 | 15 | info: 16 | version: 0.1.0 17 | stage: dev 18 | 19 | spring: 20 | application: 21 | name: rcloud-gistproxy-service 22 | cloud: 23 | config: 24 | enabled: false 25 | profiles: 26 | active: rcloudgist 27 | 28 | security: 29 | user: 30 | name: admin 31 | basic: 32 | enabled: false 33 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/java/com/mangosolutions/rcloud/gists/Application.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.gists; 8 | 9 | import org.springframework.boot.SpringApplication; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 12 | 13 | @SpringBootApplication 14 | @EnableZuulProxy 15 | public class Application { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(Application.class, args); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/Application.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist; 8 | 9 | import org.springframework.boot.SpringApplication; 10 | import org.springframework.boot.autoconfigure.SpringBootApplication; 11 | import org.springframework.cache.annotation.EnableCaching; 12 | 13 | @SpringBootApplication 14 | @EnableCaching 15 | public class Application { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(Application.class, args); 19 | } 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/pkg/home/logback.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/pkg/home/logback.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/UUIDGistIdGenerator.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import java.util.UUID; 10 | 11 | import com.mangosolutions.rcloud.rawgist.repository.GistIdGenerator; 12 | 13 | public class UUIDGistIdGenerator implements GistIdGenerator { 14 | 15 | /* (non-Javadoc) 16 | * @see com.mangosolutions.rcloud.rawgist.api.GistIdGenerator#generateId() 17 | */ 18 | @Override 19 | public String generateId() { 20 | return UUID.randomUUID().toString().replace("-", ""); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/GistUsersProperties.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist; 8 | 9 | import java.util.HashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | public class GistUsersProperties { 14 | 15 | private Map> collaborations = new HashMap<>(); 16 | 17 | public Map> getCollaborations() { 18 | return collaborations; 19 | } 20 | 21 | public void setCollaborations(Map> collaborations) { 22 | this.collaborations = collaborations; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/test/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/GistErrorCode.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository; 8 | 9 | public enum GistErrorCode { 10 | 11 | ERR_METADATA_NOT_READABLE, 12 | ERR_METADATA_NOT_WRITEABLE, 13 | ERR_COMMENTS_NOT_READABLE, 14 | ERR_COMMENTS_NOT_WRITEABLE, 15 | ERR_GIST_UPDATE_FAILURE, 16 | ERR_GIST_FORK_FAILURE, 17 | ERR_GIST_CONTENT_NOT_READABLE, 18 | ERR_GIST_CONTENT_NOT_AVAILABLE, 19 | ERR_GIST_NOT_EXIST, 20 | ERR_COMMENT_NOT_EXIST, 21 | FATAL_GIST_INITIALISATION, 22 | ERR_ACL_WRITE_DENIED, 23 | ERR_ACL_CREATE_DENIED, 24 | ERR_ACL_READ_DENIED 25 | } 26 | -------------------------------------------------------------------------------- /rcloud-sessionkey-lib/src/main/java/com/mangosolutions/rcloud/sessionkeyauth/AnonymousUserAuthorityResolver.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.sessionkeyauth; 8 | 9 | import org.springframework.security.core.GrantedAuthority; 10 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 11 | 12 | public class AnonymousUserAuthorityResolver implements AuthorityResolver { 13 | 14 | public static final GrantedAuthority ANONYMOUS_AUTHORITY = new SimpleGrantedAuthority("ROLE_ANONYMOUS"); 15 | 16 | @Override 17 | public GrantedAuthority resolve(String username) { 18 | return ANONYMOUS_AUTHORITY; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/GistRepositoryError.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository; 8 | 9 | public class GistRepositoryError extends RuntimeException { 10 | 11 | private static final long serialVersionUID = 7221509801637802584L; 12 | 13 | private GistError error; 14 | 15 | public GistRepositoryError(GistError error, Throwable cause) { 16 | super(error.getFormattedMessage(), cause); 17 | this.error = error; 18 | } 19 | 20 | public GistRepositoryError(GistError error) { 21 | this(error, null); 22 | } 23 | 24 | public GistError getGistError() { 25 | return error; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/GistAccessDeniedException.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository; 8 | 9 | public class GistAccessDeniedException extends RuntimeException { 10 | 11 | private static final long serialVersionUID = -217812774457301300L; 12 | 13 | private GistError error; 14 | 15 | public GistAccessDeniedException(GistError error, Throwable cause) { 16 | super(error.getFormattedMessage(), cause); 17 | this.error = error; 18 | } 19 | 20 | public GistAccessDeniedException(GistError error) { 21 | this(error, null); 22 | } 23 | 24 | public GistError getGistError() { 25 | return error; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/GistRepositoryException.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository; 8 | 9 | public class GistRepositoryException extends RuntimeException { 10 | 11 | private static final long serialVersionUID = -3925461305121147713L; 12 | 13 | private GistError error; 14 | 15 | public GistRepositoryException(GistError error, Throwable cause) { 16 | super(error.getFormattedMessage(), cause); 17 | this.error = error; 18 | } 19 | 20 | public GistRepositoryException(GistError error) { 21 | this(error, null); 22 | } 23 | 24 | public GistError getGistError() { 25 | return error; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /rcloud-sessionkey-lib/src/main/java/com/mangosolutions/rcloud/sessionkeyauth/AnonymousUser.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.sessionkeyauth; 8 | 9 | import java.util.Collection; 10 | 11 | import org.springframework.security.core.GrantedAuthority; 12 | import org.springframework.security.core.userdetails.User; 13 | 14 | public final class AnonymousUser extends User { 15 | 16 | private static final long serialVersionUID = 4410141395566525064L; 17 | 18 | public static final String ANONYMOUS_USER_NAME = "anonymous"; 19 | 20 | public AnonymousUser(Collection authorities) { 21 | super(ANONYMOUS_USER_NAME, "", authorities); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /rcloud-sessionkey-lib/src/main/java/com/mangosolutions/rcloud/sessionkeyauth/UserAuthorityResolver.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.sessionkeyauth; 8 | 9 | import org.apache.commons.lang3.StringUtils; 10 | import org.springframework.security.core.GrantedAuthority; 11 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 12 | 13 | public class UserAuthorityResolver implements AuthorityResolver { 14 | 15 | public static final GrantedAuthority USER_AUTHORITY = new SimpleGrantedAuthority("ROLE_USER"); 16 | 17 | @Override 18 | public GrantedAuthority resolve(String username) { 19 | if(StringUtils.isNotBlank(username)) { 20 | return USER_AUTHORITY; 21 | } 22 | return null; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /rcloud-sessionkey-lib/build.gradle: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | 8 | project.description = "Spring security integration with RCloud Session Key Server." 9 | 10 | dependencies { 11 | compile 'org.springframework.security:spring-security-core' 12 | compile 'org.springframework.security:spring-security-web' 13 | 14 | compile 'commons-io:commons-io:2.5' 15 | 16 | compile 'org.apache.commons:commons-collections4:4.1' 17 | 18 | compile 'org.apache.commons:commons-lang3:3.5' 19 | 20 | 21 | compile 'org.slf4j:slf4j-api' 22 | 23 | 24 | runtime 'org.slf4j:jcl-over-slf4j' 25 | 26 | 27 | testCompile 'junit:junit:4.11' 28 | testCompile 'org.mockito:mockito-all:1.10.8' 29 | testCompile 'org.springframework.boot:spring-boot-starter-test' 30 | testCompile 'org.slf4j:slf4j-simple' 31 | 32 | } 33 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/GitGistRepositoryFactory.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import java.io.File; 10 | 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Component; 13 | 14 | import com.mangosolutions.rcloud.rawgist.repository.GistRepository; 15 | import com.mangosolutions.rcloud.rawgist.repository.GistRepositoryFactory; 16 | 17 | @Component 18 | public class GitGistRepositoryFactory implements GistRepositoryFactory { 19 | 20 | @Autowired 21 | private GistOperationFactory gistOperationFactory; 22 | 23 | public GistRepository getRepository(File folder) { 24 | return new GitGistRepository(folder, gistOperationFactory); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/SymetricFourPartRepositoryStorageLocator.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import java.io.File; 10 | 11 | import com.google.common.base.Splitter; 12 | 13 | public class SymetricFourPartRepositoryStorageLocator implements RepositoryStorageLocator { 14 | 15 | private static final Splitter REPOSITORYID_FOLDER_SPLITTER = Splitter.fixedLength(4); 16 | 17 | private File root; 18 | 19 | public SymetricFourPartRepositoryStorageLocator(File root) { 20 | this.root = root; 21 | } 22 | 23 | @Override 24 | public File getStoragePath(String gistId) { 25 | File folder = root; 26 | for (String path : REPOSITORYID_FOLDER_SPLITTER.split(gistId)) { 27 | folder = new File(folder, path); 28 | } 29 | return folder; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/security/PermissiveGistSecurityManager.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.security; 8 | 9 | import org.springframework.security.core.userdetails.UserDetails; 10 | 11 | import com.mangosolutions.rcloud.rawgist.repository.GistRepository; 12 | 13 | public class PermissiveGistSecurityManager extends SimpleGistSecurityManager { 14 | 15 | @Override 16 | public boolean canRead(GistRepository repository, UserDetails userDetails) { 17 | return true; 18 | } 19 | 20 | @Override 21 | public boolean canWrite(GistRepository repository, UserDetails userDetails) { 22 | return true; 23 | } 24 | 25 | @Override 26 | public GistAccessRight getAccessRight(GistRepository repository, UserDetails userDetails) { 27 | return GistAccessRight.WRITE; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 AT&T Intellectual Property 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/GistCommentRepository.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository; 8 | 9 | import java.util.List; 10 | 11 | import org.springframework.security.core.userdetails.UserDetails; 12 | 13 | import com.mangosolutions.rcloud.rawgist.model.GistComment; 14 | import com.mangosolutions.rcloud.rawgist.model.GistCommentResponse; 15 | 16 | public interface GistCommentRepository { 17 | 18 | List getComments(UserDetails userDetails); 19 | 20 | GistCommentResponse getComment(long commentId, UserDetails userDetails); 21 | 22 | GistCommentResponse createComment(GistComment comment, UserDetails user); 23 | 24 | GistCommentResponse editComment(long commentId, GistComment comment, UserDetails user); 25 | 26 | void deleteComment(long commentId, UserDetails userDetails); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/DefaultFileContentCache.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import org.springframework.cache.annotation.CachePut; 10 | import org.springframework.cache.annotation.Cacheable; 11 | import org.springframework.stereotype.Component; 12 | 13 | import com.mangosolutions.rcloud.rawgist.model.FileContent; 14 | 15 | @Component 16 | public class DefaultFileContentCache implements FileContentCache { 17 | 18 | @Override 19 | @Cacheable(value = "filecontentcache", key = "{#contentId, #path}") 20 | public FileContent load(String contentId, String path) { 21 | return null; 22 | } 23 | 24 | @Override 25 | @CachePut(cacheNames = "filecontentcache", key = "{#contentId, #path}") 26 | public FileContent save(String contentId, String path, FileContent content) { 27 | return content; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/pkg/home/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 AT&T Intellectual Property 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/pkg/home/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 AT&T Intellectual Property 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/DefaultHistoryCache.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import org.springframework.cache.annotation.CachePut; 13 | import org.springframework.cache.annotation.Cacheable; 14 | import org.springframework.stereotype.Component; 15 | 16 | import com.mangosolutions.rcloud.rawgist.model.GistHistory; 17 | 18 | @Component 19 | public class DefaultHistoryCache implements HistoryCache { 20 | 21 | @Override 22 | @Cacheable(value = "historystore", key = "#commitId") 23 | public List load(String commitId) { 24 | return new ArrayList(); 25 | } 26 | 27 | @Override 28 | @CachePut(cacheNames = "historystore", key = "#commitId") 29 | public List save(String commitId, List history) { 30 | return history; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/GistSecurityManager.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository; 8 | 9 | import java.util.Collection; 10 | 11 | import org.springframework.security.core.userdetails.UserDetails; 12 | 13 | public interface GistSecurityManager { 14 | 15 | public enum GistAccessRight { 16 | NONE, READ, WRITE 17 | } 18 | 19 | public enum GistRole { 20 | NONE, OWNER, COLLABORATOR 21 | } 22 | 23 | boolean canCreate(UserDetails userDetails); 24 | 25 | boolean canCreateAs(UserDetails userDetails, String otherUser); 26 | 27 | boolean canRead(GistRepository repository, UserDetails userDetails); 28 | 29 | boolean canWrite(GistRepository repository, UserDetails userDetails); 30 | 31 | GistAccessRight getAccessRight(GistRepository repository, UserDetails userDetails); 32 | 33 | boolean isOwner(GistRepository repository, UserDetails userDetails); 34 | 35 | GistRole getRole(GistRepository repository, UserDetails userDetails); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/AsymetricFourFolderRepositoryStorageLocator.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import java.io.File; 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | 13 | public class AsymetricFourFolderRepositoryStorageLocator implements RepositoryStorageLocator { 14 | 15 | private static final Pattern REPOSITORYID_FOLDER_PATTERN = Pattern.compile("(.)(.)(.)(.*)"); 16 | 17 | private File root; 18 | 19 | public AsymetricFourFolderRepositoryStorageLocator(File root) { 20 | this.root = root; 21 | } 22 | 23 | @Override 24 | public File getStoragePath(String gistId) { 25 | File path = null; 26 | Matcher matcher = REPOSITORYID_FOLDER_PATTERN.matcher(gistId); 27 | if(matcher.matches()) { 28 | int groups = matcher.groupCount(); 29 | path = root; 30 | for(int i = 1; i <= groups; i++) { 31 | path = new File(path, matcher.group(i)); 32 | } 33 | } 34 | return path; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/CollaborationDataStore.java: -------------------------------------------------------------------------------- 1 | package com.mangosolutions.rcloud.rawgist.repository.git; 2 | 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | import java.util.HashMap; 6 | import java.util.LinkedHashSet; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | public class CollaborationDataStore { 11 | 12 | private Map> collaborators = new HashMap<>(); 13 | 14 | public CollaborationDataStore() { 15 | 16 | } 17 | 18 | public CollaborationDataStore(Map> collaborators) { 19 | this.collaborators = collaborators; 20 | } 21 | 22 | public Collection getCollaborators(String user) { 23 | if (collaborators.containsKey(user) && collaborators.get(user) != null) { 24 | return new LinkedHashSet<>(collaborators.get(user)); 25 | } else { 26 | return Collections.emptySet(); 27 | } 28 | } 29 | 30 | public void updateCollaborators(Map> collaborators) { 31 | this.collaborators.clear(); 32 | for(Map.Entry> entry: collaborators.entrySet()) { 33 | this.collaborators.put(entry.getKey(), entry.getValue()); 34 | } 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | dist: trusty 3 | sudo: required 4 | jdk: 5 | - openjdk8 6 | deploy: 7 | provider: releases 8 | api_key: 9 | secure: HYh0fPSByuuJB/r7YKc+iHRBzo13lScGz1Kign/Uj3GnAcDL+NpnYCvEl1JCymd+v8vPyFDxWmFJ6mJSyAlQzhxIRoeHpOQhECVJXuuB9IUk+o2hb+MhUuPpOwGtlUDW2Rry9qnz73fX5boEBzrYHF3vwbbqdfqc+sugkPcPJubtwlsH49CWHA0kMila/esZyuB7KvXuEmVCy3BCHBPK9KZ9Wo8LlB3pQhUwJWkSJID5BJl/zYDqOrKo4kjXpu6p5xcwAi+HtpCmV3gAMgcHPTO8sXy2b9JKcko0C52/+nyHpQ39gmwS0y+q0lnGZJy38IF52JDzXLAq1DxIXm2hPvI/zMNlhYJ6ovCuT7xTXypKnktwetQJ5dT6hvtNmtBMxkXww43svAb/k9nr2bo9z65iOqKpqdFQYzFB/wltToMbX50xC9Yi+fYv219H3Fc6vioJw5bkRCoapC7ImmkhVjsv5YDEGbqv3dyEbGOWyI0phnJBd6+UjMFCSxX9pinu+RUhLU0uga9/765kiMYsQAH7svzyo5iYcN0HB4X1amAKjaLmp2so2AqKk4FKznVHhtY0Mm74Xgq6tmQTk7iuCwbvf2M1pCjhV4zDBio2XODHGGxJeIZAQTx0CIXz0F20o6K9XC2vDM6BWHt2YCN6qjR0buYP/NdsOPcjeSnCVMk= 10 | file_glob: true 11 | file: 12 | - "./rcloud-gist-service/build/distributions/*.deb" 13 | - "./rcloud-gist-service/build/distributions/*.rpm" 14 | - "./rcloud-gist-service/build/libs/*.jar" 15 | - "./rcloud-gistproxy-service/build/distributions/*.deb" 16 | - "./rcloud-gistproxy-service/build/distributions/*.rpm" 17 | - "./rcloud-gistproxy-service/build/libs/*.jar" 18 | skip_cleanup: true 19 | on: 20 | branch: master 21 | repo: MangoTheCat/rcloud-gist-services 22 | tags: true 23 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/java/com/mangosolutions/rcloud/gists/RCloudGistsServiceConfiguration.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.gists; 8 | 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.context.annotation.Profile; 12 | 13 | import com.mangosolutions.rcloud.gists.filters.AcceptContentTypeReWritingFilter; 14 | import com.mangosolutions.rcloud.gists.filters.SessionTokenParameterToHeaderFilter; 15 | import com.netflix.zuul.ZuulFilter; 16 | 17 | /** 18 | * Main Spring configuration 19 | * 20 | */ 21 | @Configuration 22 | @Profile("rcloudgist") 23 | public class RCloudGistsServiceConfiguration { 24 | 25 | private static final String GISTS_PATH = "/gists"; 26 | 27 | @Bean 28 | public ZuulFilter getAcceptContentTypeReWritingFilter() { 29 | return new AcceptContentTypeReWritingFilter(GISTS_PATH, 30); 30 | } 31 | 32 | @Bean 33 | public ZuulFilter getSessionTokenParameterToHeaderFilter() { 34 | return new SessionTokenParameterToHeaderFilter(GISTS_PATH, 40); 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/test/java/com/mangosolutions/rcloud/rawgist/ContextStartStopTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist; 8 | 9 | import org.junit.Test; 10 | import org.junit.runner.RunWith; 11 | import org.springframework.boot.test.context.SpringBootContextLoader; 12 | import org.springframework.boot.test.context.SpringBootTest; 13 | import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; 14 | import org.springframework.test.annotation.DirtiesContext; 15 | import org.springframework.test.annotation.DirtiesContext.ClassMode; 16 | import org.springframework.test.context.ActiveProfiles; 17 | import org.springframework.test.context.ContextConfiguration; 18 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 19 | 20 | @RunWith(SpringJUnit4ClassRunner.class) 21 | @SpringBootTest(classes = { Application.class }, webEnvironment=WebEnvironment.RANDOM_PORT) 22 | @ContextConfiguration(loader = SpringBootContextLoader.class) 23 | @DirtiesContext(classMode = ClassMode.AFTER_CLASS) 24 | @ActiveProfiles({"test", "default"}) 25 | public class ContextStartStopTest { 26 | 27 | @Test 28 | public void testContextStartStop() { 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /rcloud-sessionkey-lib/src/main/java/com/mangosolutions/rcloud/sessionkeyauth/GrantedAuthorityFactory.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.sessionkeyauth; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | import java.util.Collection; 12 | 13 | import org.springframework.security.core.GrantedAuthority; 14 | 15 | public class GrantedAuthorityFactory { 16 | 17 | private Collection authorityResolvers = Arrays.asList(new AnonymousUserAuthorityResolver(), 18 | new UserAuthorityResolver()); 19 | 20 | public Collection resolve(String username) { 21 | Collection authorities = new ArrayList<>(authorityResolvers.size()); 22 | for(AuthorityResolver resolver: authorityResolvers) { 23 | GrantedAuthority authority = resolver.resolve(username); 24 | if(authority != null) { 25 | authorities.add(authority); 26 | } 27 | } 28 | return authorities; 29 | } 30 | 31 | public void setAuthorityResolvers(Collection authorityResolvers) { 32 | this.authorityResolvers = authorityResolvers; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /salt/roots/salt/rcloud/init.sls: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************/ 7 | base: 8 | pkgrepo.managed: 9 | - humanname: MARutter PPA 10 | - name: ppa:marutter/rrutter 11 | 12 | rcloud-dependencies: 13 | pkg.installed: 14 | - pkgs: 15 | - libpam-dev 16 | - openjdk-7-jdk 17 | - gcc 18 | - g++ 19 | - gfortran 20 | - libcairo-dev 21 | - libreadline-dev 22 | - libxt-dev 23 | - libjpeg-dev 24 | - libicu-dev 25 | - libssl-dev 26 | - libcurl4-openssl-dev 27 | - subversion 28 | - git 29 | - automake 30 | - make 31 | - libtool 32 | - libtiff-dev 33 | - gettext 34 | - redis-server 35 | - rsync 36 | - r-base-dev 37 | # - nodejs 38 | # - npm 39 | 40 | rcloud-deploy: 41 | archive.extracted: 42 | - name: /opt/rcloud 43 | - source: https://github.com/att/rcloud/archive/1.7.tar.gz 44 | - source_hash: md5=643eff16f448bf1306cbcd08930cfb99 45 | - source_hash_update: True 46 | cmd.run: 47 | - name: ./scripts/bootstrapR.sh 48 | - cwd: /opt/rcloud/rcloud-1.7/ 49 | - creates: /opt/rcloud/rcloud-1.7/conf/rcloud.conf 50 | 51 | #TODO add in compilation of the SessionKeyServer 52 | #session-key-server: 53 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/java/com/mangosolutions/rcloud/gists/GistsServiceConfiguration.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.gists; 8 | 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.web.filter.CommonsRequestLoggingFilter; 12 | 13 | import com.mangosolutions.rcloud.gists.filters.HeaderUrlRewritingFilter; 14 | import com.mangosolutions.rcloud.gists.filters.JsonContentUrlRewritingFilter; 15 | import com.netflix.zuul.ZuulFilter; 16 | 17 | /** 18 | * Main Spring configuration 19 | * 20 | */ 21 | @Configuration 22 | public class GistsServiceConfiguration { 23 | 24 | @Bean 25 | public ZuulFilter getUrlRewritingFilter() { 26 | return new HeaderUrlRewritingFilter(10); 27 | } 28 | 29 | @Bean 30 | public ZuulFilter getJsonContentUrlRewritingFilter() { 31 | return new JsonContentUrlRewritingFilter(20); 32 | } 33 | 34 | @Bean 35 | public CommonsRequestLoggingFilter requestLoggingFilter() { 36 | CommonsRequestLoggingFilter crlf = new CommonsRequestLoggingFilter(); 37 | crlf.setIncludeClientInfo(true); 38 | crlf.setIncludeQueryString(true); 39 | crlf.setIncludePayload(true); 40 | return crlf; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/GistRepository.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository; 8 | 9 | import java.io.File; 10 | 11 | import org.springframework.security.core.userdetails.UserDetails; 12 | 13 | import com.mangosolutions.rcloud.rawgist.model.GistRequest; 14 | import com.mangosolutions.rcloud.rawgist.model.GistResponse; 15 | import com.mangosolutions.rcloud.rawgist.repository.git.GistMetadata; 16 | 17 | public interface GistRepository { 18 | 19 | File getGistRepositoryFolder(UserDetails userDetails); 20 | 21 | File getGistGitRepositoryFolder(UserDetails userDetails); 22 | 23 | GistResponse readGist(UserDetails userDetails); 24 | 25 | GistResponse readGist(String commitId, UserDetails userDetails); 26 | 27 | GistResponse createGist(GistRequest request, String gistId, UserDetails userDetails); 28 | 29 | GistResponse updateGist(GistRequest request, UserDetails userDetails); 30 | 31 | GistResponse forkGist(GistRepository forkedRepository, String gistId, UserDetails userDetails); 32 | 33 | String getId(); 34 | 35 | void registerFork(GistRepository forkedRepository); 36 | 37 | GistMetadata getMetadata(); 38 | 39 | GistCommentRepository getCommentRepository(); 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/test/java/com/mangosolutions/rcloud/rawgist/repository/GistErrorTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository; 8 | 9 | import org.junit.Assert; 10 | import org.junit.Test; 11 | 12 | 13 | public class GistErrorTest { 14 | 15 | 16 | @Test 17 | public void gistErrorFormattingTest() { 18 | 19 | GistError error = new GistError(GistErrorCode.ERR_COMMENT_NOT_EXIST, "This message should be {}", "happy"); 20 | Assert.assertEquals("This message should be {}", error.getMessage()); 21 | Assert.assertEquals("ERR_COMMENT_NOT_EXIST: This message should be happy", error.getFormattedMessage()); 22 | Assert.assertEquals("ERR_COMMENT_NOT_EXIST: This message should be happy", error.toString()); 23 | 24 | } 25 | 26 | @Test 27 | public void gistErrorFormattingNoParamsTest() { 28 | 29 | GistError error = new GistError(GistErrorCode.ERR_COMMENT_NOT_EXIST, "This has a token, but should not be replaced {}"); 30 | Assert.assertEquals("This has a token, but should not be replaced {}", error.getMessage()); 31 | Assert.assertEquals("ERR_COMMENT_NOT_EXIST: This has a token, but should not be replaced {}", error.getFormattedMessage()); 32 | Assert.assertEquals("ERR_COMMENT_NOT_EXIST: This has a token, but should not be replaced {}", error.toString()); 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/GistError.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository; 8 | 9 | import java.io.Serializable; 10 | 11 | import org.slf4j.helpers.MessageFormatter; 12 | import org.springframework.util.StringUtils; 13 | 14 | public class GistError { 15 | 16 | private static final String PREFIX_FORMAT = "{}: "; 17 | 18 | private GistErrorCode code; 19 | 20 | private String message; 21 | 22 | private Serializable[] params; 23 | 24 | public GistError(GistErrorCode code, String message, Serializable... params) { 25 | this.code = code; 26 | this.message = message; 27 | this.params = params; 28 | } 29 | 30 | public GistErrorCode getCode() { 31 | return code; 32 | } 33 | 34 | 35 | public String getMessage() { 36 | return this.message; 37 | } 38 | 39 | public Serializable[] getParams() { 40 | return this.params; 41 | } 42 | 43 | 44 | public String getFormattedMessage() { 45 | String prefix = ""; 46 | if(!StringUtils.isEmpty(code)) { 47 | prefix = this.format(PREFIX_FORMAT, code); 48 | } 49 | return prefix + this.format(message, (Object[]) params); 50 | } 51 | 52 | 53 | private String format(String format, Object... params) { 54 | return MessageFormatter.arrayFormat(format, params).getMessage(); 55 | } 56 | 57 | public String toString() { 58 | return this.getFormattedMessage(); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/api/RedirectController.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.api; 8 | 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.http.HttpStatus; 11 | import org.springframework.stereotype.Controller; 12 | import org.springframework.util.StringUtils; 13 | import org.springframework.web.bind.annotation.RequestMapping; 14 | import org.springframework.web.bind.annotation.RequestMethod; 15 | import org.springframework.web.servlet.mvc.support.RedirectAttributes; 16 | import org.springframework.web.servlet.view.RedirectView; 17 | 18 | 19 | @Controller 20 | @RequestMapping("${gists.route.redirect.from}") 21 | public class RedirectController { 22 | 23 | @Value("${gists.route.redirect.to}") 24 | private String redirectToUrl; 25 | 26 | @Value("${gists.route.redirect.copyparams:true}") 27 | private boolean propgateParams = true; 28 | 29 | @RequestMapping(method={RequestMethod.GET, RequestMethod.POST}) 30 | public RedirectView performRedirect(RedirectAttributes attributes) { 31 | RedirectView redirectView = new RedirectView(); 32 | if(StringUtils.isEmpty(redirectToUrl)) { 33 | redirectView.setStatusCode(HttpStatus.NOT_FOUND); 34 | } else { 35 | redirectView.setUrl(redirectToUrl); 36 | redirectView.setPropagateQueryParams(propgateParams); 37 | 38 | } 39 | return redirectView; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/SessionKeyServerWebAuthenticationDetailsSource.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | 11 | import org.springframework.security.authentication.AuthenticationDetailsSource; 12 | import org.springframework.util.StringUtils; 13 | 14 | import com.mangosolutions.rcloud.sessionkeyauth.SessionKeyServerAuthenticationDetails; 15 | 16 | public class SessionKeyServerWebAuthenticationDetailsSource implements AuthenticationDetailsSource{ 17 | 18 | private static final String DEFAULT_CLIENT_ID_PARAMETER = "client_id"; 19 | 20 | private String clientIdParameter = DEFAULT_CLIENT_ID_PARAMETER; 21 | 22 | public SessionKeyServerWebAuthenticationDetailsSource() { 23 | 24 | } 25 | 26 | public SessionKeyServerWebAuthenticationDetailsSource(String clientIdParameter) { 27 | if(!StringUtils.isEmpty(clientIdParameter)) { 28 | this.clientIdParameter = clientIdParameter.trim(); 29 | } 30 | } 31 | 32 | @Override 33 | public SessionKeyServerAuthenticationDetails buildDetails(HttpServletRequest context) { 34 | String clientId = getClientId(context); 35 | return new SessionKeyServerAuthenticationDetails(clientId); 36 | } 37 | 38 | private String getClientId(HttpServletRequest context) { 39 | return context.getParameter(clientIdParameter); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/model/GistComment.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.model; 8 | 9 | import java.io.Serializable; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 14 | import com.fasterxml.jackson.annotation.JsonAnySetter; 15 | import com.fasterxml.jackson.annotation.JsonIgnore; 16 | import com.fasterxml.jackson.annotation.JsonInclude; 17 | import com.fasterxml.jackson.annotation.JsonProperty; 18 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 19 | 20 | @JsonInclude(JsonInclude.Include.ALWAYS) 21 | @JsonPropertyOrder({"body"}) 22 | public class GistComment implements Serializable { 23 | 24 | private static final long serialVersionUID = -8825113442917504022L; 25 | 26 | @JsonProperty("body") 27 | private String body; 28 | 29 | @JsonIgnore 30 | private Map additionalProperties = new HashMap(); 31 | 32 | @JsonProperty("body") 33 | public String getBody() { 34 | return body; 35 | } 36 | 37 | @JsonProperty("body") 38 | public void setBody(String body) { 39 | this.body = body; 40 | } 41 | 42 | 43 | @JsonAnyGetter 44 | public Map getAdditionalProperties() { 45 | return this.additionalProperties; 46 | } 47 | 48 | @JsonAnySetter 49 | public void setAdditionalProperty(String name, Object value) { 50 | this.additionalProperties.put(name, value); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/api/UserRestController.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.api; 8 | 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | import org.springframework.http.MediaType; 13 | import org.springframework.security.core.annotation.AuthenticationPrincipal; 14 | import org.springframework.security.core.userdetails.User; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.bind.annotation.RequestMethod; 17 | import org.springframework.web.bind.annotation.RestController; 18 | 19 | import com.mangosolutions.rcloud.rawgist.model.GistIdentity; 20 | import com.mangosolutions.rcloud.rawgist.model.GistResponse; 21 | 22 | @RestController() 23 | @RequestMapping(value = "/user", produces = { 24 | MediaType.APPLICATION_JSON_VALUE, 25 | "application/vnd.github.beta+json", 26 | "application/vnd.github.v3+json" 27 | }) 28 | public class UserRestController { 29 | 30 | @RequestMapping(method = RequestMethod.GET) 31 | public GistIdentity getUser(@AuthenticationPrincipal User activeUser) { 32 | GistIdentity response = new GistIdentity(); 33 | String username = activeUser.getUsername(); 34 | response.setLogin(username); 35 | return response; 36 | } 37 | 38 | @RequestMapping(value = "/{username}/gists", method = RequestMethod.GET) 39 | public List getUsersPublicGists() { 40 | return Collections.emptyList(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/security/CollaborationGrantedAuthorityResolver.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.security; 8 | 9 | import java.util.Collection; 10 | 11 | import org.springframework.security.core.GrantedAuthority; 12 | 13 | import com.mangosolutions.rcloud.rawgist.repository.git.CollaborationDataStore; 14 | import com.mangosolutions.rcloud.sessionkeyauth.UserAuthorityResolver; 15 | 16 | public class CollaborationGrantedAuthorityResolver extends UserAuthorityResolver { 17 | 18 | private CollaborationDataStore collaborationDataStore = new CollaborationDataStore(); 19 | 20 | public CollaborationGrantedAuthorityResolver() { 21 | 22 | } 23 | 24 | public CollaborationGrantedAuthorityResolver(CollaborationDataStore collaborationDataStore) { 25 | this.collaborationDataStore = collaborationDataStore; 26 | } 27 | 28 | @Override 29 | public GrantedAuthority resolve(String username) { 30 | GrantedAuthority authority = super.resolve(username); 31 | if(authority != null) { 32 | String[] aliases = resolveAliases(username); 33 | return new CollaborationGrantedAuthority(aliases); 34 | } 35 | return null; 36 | } 37 | 38 | private String[] resolveAliases(String username) { 39 | Collection aliasList = collaborationDataStore.getCollaborators(username); 40 | return aliasList.toArray(new String[aliasList.size()]); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /rcloud-sessionkey-lib/src/main/java/com/mangosolutions/rcloud/sessionkeyauth/SessionKeyServerAuthenticationDetails.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.sessionkeyauth; 8 | 9 | import java.io.Serializable; 10 | 11 | import org.springframework.util.StringUtils; 12 | 13 | public class SessionKeyServerAuthenticationDetails implements Serializable { 14 | 15 | private static final long serialVersionUID = 6663642339898628671L; 16 | 17 | private String clientId = "default"; 18 | 19 | public SessionKeyServerAuthenticationDetails() { 20 | this("default"); 21 | } 22 | 23 | public SessionKeyServerAuthenticationDetails(String clientId) { 24 | if(!StringUtils.isEmpty(clientId)) { 25 | this.clientId = clientId; 26 | } 27 | } 28 | 29 | public String getClientId() { 30 | return clientId; 31 | } 32 | 33 | @Override 34 | public int hashCode() { 35 | final int prime = 31; 36 | int result = 1; 37 | result = prime * result + ((clientId == null) ? 0 : clientId.hashCode()); 38 | return result; 39 | } 40 | 41 | @Override 42 | public boolean equals(Object obj) { 43 | if (this == obj) 44 | return true; 45 | if (obj == null) 46 | return false; 47 | if (getClass() != obj.getClass()) 48 | return false; 49 | SessionKeyServerAuthenticationDetails other = (SessionKeyServerAuthenticationDetails) obj; 50 | if (clientId == null) { 51 | if (other.clientId != null) 52 | return false; 53 | } else if (!clientId.equals(other.clientId)) 54 | return false; 55 | return true; 56 | } 57 | 58 | @Override 59 | public String toString() { 60 | return "SessionKeyServerAuthenticationDetails [clientId=" + clientId + "]"; 61 | } 62 | 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/api/ControllerUrlResolver.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.api; 8 | 9 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo; 10 | import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn; 11 | 12 | import org.springframework.security.core.userdetails.User; 13 | import org.springframework.stereotype.Component; 14 | 15 | @Component 16 | public class ControllerUrlResolver { 17 | 18 | public String getGistUrl(String gistId, User activeUser) { 19 | String url = null; 20 | if(gistId != null) { 21 | url = linkTo( 22 | methodOn(GistRestController.class) 23 | .getGist(gistId, activeUser)) 24 | .withSelfRel() 25 | .getHref(); 26 | } 27 | return url; 28 | } 29 | 30 | public String getCommentsUrl(String gistId, User activeUser) { 31 | String url = null; 32 | if(gistId != null) { 33 | url = linkTo( 34 | methodOn(GistCommentRestController.class) 35 | .getComments(gistId, activeUser)) 36 | .withSelfRel() 37 | .getHref(); 38 | } 39 | return url; 40 | } 41 | 42 | public String getCommentUrl(String gistId, Long commentId, User activeUser) { 43 | String url = null; 44 | if(gistId != null && commentId != null) { 45 | url = linkTo( 46 | methodOn(GistCommentRestController.class) 47 | .getComment(gistId, commentId, activeUser)) 48 | .withSelfRel() 49 | .getHref(); 50 | } 51 | return url; 52 | } 53 | 54 | public String getForksUrl(String gistId, User activeUser) { 55 | String url = null; 56 | if(gistId != null) { 57 | url = linkTo( 58 | methodOn(GistRestController.class) 59 | .forkGist(gistId, activeUser)) 60 | .withSelfRel() 61 | .getHref(); 62 | } 63 | return url; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/model/FileDefinition.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.model; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | import com.fasterxml.jackson.annotation.JsonIgnore; 13 | import com.fasterxml.jackson.annotation.JsonInclude; 14 | import com.fasterxml.jackson.annotation.JsonProperty; 15 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 16 | 17 | @JsonInclude(JsonInclude.Include.ALWAYS) 18 | @JsonPropertyOrder({ "filename", "type", "language", "content" }) 19 | public class FileDefinition { 20 | 21 | @JsonProperty("filename") 22 | private String filename; 23 | 24 | @JsonProperty("content") 25 | private String content; 26 | 27 | @JsonProperty("language") 28 | private String language; 29 | 30 | @JsonProperty("type") 31 | private String type; 32 | 33 | @JsonIgnore 34 | private Map additionalProperties = new HashMap(); 35 | 36 | public String getLanguage() { 37 | return language; 38 | } 39 | 40 | public void setLanguage(String language) { 41 | this.language = language; 42 | } 43 | 44 | public String getType() { 45 | return type; 46 | } 47 | 48 | public void setType(String type) { 49 | this.type = type; 50 | } 51 | 52 | public String getFilename() { 53 | return filename; 54 | } 55 | 56 | public void setFilename(String filename) { 57 | this.filename = filename; 58 | } 59 | 60 | public String getContent() { 61 | return content; 62 | } 63 | 64 | public void setContent(String content) { 65 | this.content = content; 66 | } 67 | 68 | public Map getAdditionalProperties() { 69 | return additionalProperties; 70 | } 71 | 72 | public void setAdditionalProperties(Map additionalProperties) { 73 | this.additionalProperties = additionalProperties; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/GistRepositoryService.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository; 8 | 9 | import java.util.List; 10 | 11 | import org.springframework.security.core.userdetails.User; 12 | import org.springframework.security.core.userdetails.UserDetails; 13 | 14 | import com.mangosolutions.rcloud.rawgist.model.Fork; 15 | import com.mangosolutions.rcloud.rawgist.model.GistComment; 16 | import com.mangosolutions.rcloud.rawgist.model.GistCommentResponse; 17 | import com.mangosolutions.rcloud.rawgist.model.GistRequest; 18 | import com.mangosolutions.rcloud.rawgist.model.GistResponse; 19 | 20 | public interface GistRepositoryService { 21 | 22 | public List listGists(UserDetails activeUser); 23 | 24 | public GistResponse getGist(String gistId, UserDetails activeUser); 25 | 26 | public GistResponse getGist(String gistId, String commitId, UserDetails activeUser); 27 | 28 | public GistResponse createGist(GistRequest request, UserDetails user); 29 | 30 | public GistResponse editGist(String gistId, GistRequest request, UserDetails activeUser); 31 | 32 | public void deleteGist(String gistId, UserDetails activeUser); 33 | 34 | public List getComments(String gistId, UserDetails activeUser); 35 | 36 | public GistCommentResponse getComment(String gistId, long commentId, UserDetails activeUser); 37 | 38 | public GistCommentResponse createComment(String gistId, GistComment comment, UserDetails activeUser); 39 | 40 | public GistCommentResponse editComment(String gistId, long commentId, GistComment comment, UserDetails activeUser); 41 | 42 | public void deleteComment(String gistId, long commentId, UserDetails activeUser); 43 | 44 | public GistResponse forkGist(String gistId, User activeUser); 45 | 46 | public List getForks(String gistId, User activeUser); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /rcloud-sessionkey-lib/src/test/java/com/mangosolutions/rcloud/sessionkeyauth/GrantedAuthorityFactoryTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.sessionkeyauth; 8 | 9 | import java.util.Collection; 10 | 11 | import static org.junit.Assert.*; 12 | 13 | import org.junit.Test; 14 | import org.springframework.security.core.GrantedAuthority; 15 | 16 | public class GrantedAuthorityFactoryTest { 17 | 18 | 19 | @Test 20 | public void nullUsernameAnonymousAuthority() { 21 | Collection authorities = new GrantedAuthorityFactory().resolve(null); 22 | assertNotNull(authorities); 23 | assertEquals(1, authorities.size()); 24 | authorities.contains(AnonymousUserAuthorityResolver.ANONYMOUS_AUTHORITY); 25 | } 26 | 27 | @Test 28 | public void emptyUsernameAnonymousAuthority() { 29 | Collection authorities = new GrantedAuthorityFactory().resolve(""); 30 | assertNotNull(authorities); 31 | assertEquals(1, authorities.size()); 32 | authorities.contains(AnonymousUserAuthorityResolver.ANONYMOUS_AUTHORITY); 33 | } 34 | 35 | @Test 36 | public void blankUsernameAnonymousAuthority() { 37 | Collection authorities = new GrantedAuthorityFactory().resolve(" "); 38 | assertNotNull(authorities); 39 | assertEquals(1, authorities.size()); 40 | authorities.contains(AnonymousUserAuthorityResolver.ANONYMOUS_AUTHORITY); 41 | } 42 | 43 | @Test 44 | public void usernameUserAuthority() { 45 | Collection authorities = new GrantedAuthorityFactory().resolve("adam"); 46 | assertNotNull(authorities); 47 | assertEquals(2, authorities.size()); 48 | authorities.contains(AnonymousUserAuthorityResolver.ANONYMOUS_AUTHORITY); 49 | authorities.contains(UserAuthorityResolver.USER_AUTHORITY); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************* 7 | server: 8 | port: 17020 9 | 10 | management: 11 | port: 17021 12 | security: 13 | enabled: true 14 | 15 | info: 16 | version: 0.1.0 17 | stage: dev 18 | 19 | spring: 20 | jackson: 21 | serialization: 22 | write_dates_as_timestamps: false 23 | application: 24 | name: rcloud-gist-service 25 | cloud: 26 | config: 27 | enabled: false 28 | 29 | 30 | security: 31 | user: 32 | name: admin 33 | basic: 34 | enabled: false 35 | 36 | gists: 37 | root: ${java.io.tmpdir}/gists/ 38 | lockTimeout: 30 39 | keyservers: 40 | default: 41 | host: 127.0.0.1 42 | port: 4301 43 | realm: rcloud 44 | url: http://{host}:{port}/valid?token={token}&realm={realm} 45 | example: 46 | host: example.com 47 | port: 5678 48 | realm: example 49 | url: http://{host}:{port}/valid?token={token}&realm={realm} 50 | mediatypes: 51 | - application/vnd.github.beta+json 52 | - application/vnd.github.beta 53 | - application/vnd.github.v3+json 54 | - application/vnd.github.v3 55 | route: 56 | redirect: 57 | from: '/login/*' 58 | to: http://example.com 59 | copyparams: true 60 | users: 61 | collaborations: 62 | mock_user: 63 | - mock_collab_user 64 | another_mock_user: 65 | - another_mock_collab_user 66 | 67 | 68 | caches: 69 | - 70 | name: 'sessionkeys' 71 | evictionPolicy: LRU 72 | ttl: 300 73 | - 74 | name: 'gists' 75 | evictionPolicy: LRU 76 | ttl: 300 77 | - 78 | name: 'comments' 79 | evictionPolicy: LRU 80 | ttl: 300 81 | - 82 | name: 'commentstore' 83 | evictionPolicy: LRU 84 | ttl: 300 85 | - 86 | name: 'metadatatore' 87 | evictionPolicy: LRU 88 | ttl: 300 89 | - 90 | name: 'historystore' 91 | evictionPolicy: LRU 92 | ttl: 300 93 | - 94 | name: 'filecontentcache' 95 | evictionPolicy: LRU 96 | ttl: 300 97 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/java/com/mangosolutions/rcloud/gists/filters/SessionTokenParameterToHeaderFilter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.gists.filters; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | import com.google.common.base.Throwables; 16 | import com.netflix.zuul.ZuulFilter; 17 | import com.netflix.zuul.context.RequestContext; 18 | 19 | public final class SessionTokenParameterToHeaderFilter extends ZuulFilter { 20 | 21 | private static final Logger logger = LoggerFactory.getLogger(SessionTokenParameterToHeaderFilter.class); 22 | 23 | private int order = 100; 24 | 25 | private String path = "/"; 26 | 27 | public SessionTokenParameterToHeaderFilter(String path, int order) { 28 | this.order = order; 29 | this.path = path; 30 | } 31 | 32 | @Override 33 | public String filterType() { 34 | return "pre"; 35 | } 36 | 37 | @Override 38 | public int filterOrder() { 39 | return order; 40 | } 41 | 42 | @Override 43 | public boolean shouldFilter() { 44 | return true; 45 | } 46 | 47 | @Override 48 | public Object run() { 49 | try { 50 | rewriteToken(RequestContext.getCurrentContext()); 51 | } catch (final Exception e) { 52 | Throwables.propagate(e); 53 | } 54 | return null; 55 | } 56 | 57 | private void rewriteToken(final RequestContext context) { 58 | if (context.getRequest().getRequestURI().startsWith(this.path)) { 59 | 60 | Map> params = context.getRequestQueryParams(); 61 | Map requestHeaders = context.getZuulRequestHeaders(); 62 | 63 | if (params != null && params.containsKey("access_token")) { 64 | List tokens = params.get("access_token"); 65 | if (!tokens.isEmpty()) { 66 | String token = tokens.get(0); 67 | logger.debug("Setting session key token to " + token); 68 | requestHeaders.put("x-sessionkey-token", token); 69 | } 70 | } else { 71 | logger.debug("No access_token specified"); 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/CacheConfigurationProperties.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist; 8 | 9 | import java.util.List; 10 | 11 | import org.springframework.boot.context.properties.ConfigurationProperties; 12 | 13 | import com.hazelcast.config.EvictionPolicy; 14 | 15 | @ConfigurationProperties() 16 | public class CacheConfigurationProperties { 17 | 18 | private List caches; 19 | 20 | public List getCaches() { 21 | return caches; 22 | } 23 | 24 | public void setCaches(List caches) { 25 | this.caches = caches; 26 | } 27 | 28 | public static class GistCacheConfiguration { 29 | 30 | private String name; 31 | private EvictionPolicy evictionPolicy = EvictionPolicy.LFU; 32 | private int ttl = 300; 33 | private int maxSize = 1000; 34 | private int maxIdleSeconds = 300; 35 | 36 | public String getName() { 37 | return name; 38 | } 39 | 40 | public void setName(String name) { 41 | this.name = name; 42 | } 43 | 44 | public EvictionPolicy getEvictionPolicy() { 45 | return evictionPolicy; 46 | } 47 | 48 | public void setEvictionPolicy(EvictionPolicy evictionPolicy) { 49 | this.evictionPolicy = evictionPolicy; 50 | } 51 | 52 | public int getTtl() { 53 | return ttl; 54 | } 55 | 56 | public void setTtl(int ttl) { 57 | this.ttl = ttl; 58 | } 59 | 60 | public int getMaxSize() { 61 | return maxSize; 62 | } 63 | 64 | public void setMaxSize(int maxSize) { 65 | this.maxSize = maxSize; 66 | } 67 | 68 | public int getMaxIdleSeconds() { 69 | return maxIdleSeconds; 70 | } 71 | 72 | public void setMaxIdleSeconds(int maxIdleSeconds) { 73 | this.maxIdleSeconds = maxIdleSeconds; 74 | } 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/model/GitChangeStatus.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.model; 8 | 9 | import java.io.Serializable; 10 | 11 | import com.fasterxml.jackson.annotation.JsonInclude; 12 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 13 | 14 | @JsonInclude(JsonInclude.Include.ALWAYS) 15 | @JsonPropertyOrder({ 16 | "deletions", 17 | "additions", 18 | "total" 19 | }) 20 | public class GitChangeStatus implements Serializable { 21 | 22 | private static final long serialVersionUID = -1548916401329014408L; 23 | 24 | private int deletions; 25 | 26 | private int additions; 27 | 28 | private int total; 29 | 30 | public int getDeletions() { 31 | return deletions; 32 | } 33 | 34 | public void setDeletions(int deletions) { 35 | this.deletions = deletions; 36 | } 37 | 38 | public int getAdditions() { 39 | return additions; 40 | } 41 | 42 | public void setAdditions(int additions) { 43 | this.additions = additions; 44 | } 45 | 46 | public int getTotal() { 47 | return total; 48 | } 49 | 50 | public void setTotal(int total) { 51 | this.total = total; 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | final int prime = 31; 57 | int result = 1; 58 | result = prime * result + additions; 59 | result = prime * result + deletions; 60 | result = prime * result + total; 61 | return result; 62 | } 63 | 64 | @Override 65 | public boolean equals(Object obj) { 66 | if (this == obj) 67 | return true; 68 | if (obj == null) 69 | return false; 70 | if (getClass() != obj.getClass()) 71 | return false; 72 | GitChangeStatus other = (GitChangeStatus) obj; 73 | if (additions != other.additions) 74 | return false; 75 | if (deletions != other.deletions) 76 | return false; 77 | if (total != other.total) 78 | return false; 79 | return true; 80 | } 81 | 82 | @Override 83 | public String toString() { 84 | return "GitChangeStatus [deletions=" + deletions + ", additions=" + additions + ", total=" + total + "]"; 85 | } 86 | 87 | 88 | } 89 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/java/com/mangosolutions/rcloud/gists/filters/ZuulRequestUrlResolver.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.gists.filters; 8 | 9 | import java.net.MalformedURLException; 10 | import java.net.URL; 11 | import java.util.Map; 12 | 13 | import org.apache.commons.lang3.StringUtils; 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | import com.netflix.zuul.context.RequestContext; 18 | 19 | public class ZuulRequestUrlResolver { 20 | 21 | private static final Logger logger = LoggerFactory.getLogger(ZuulRequestUrlResolver.class); 22 | 23 | public String getProxiedServiceUrl(RequestContext context) { 24 | return context.getRouteHost().toString(); 25 | } 26 | 27 | public String getZuulServiceUrl(RequestContext context) { 28 | Map zuulRequestHeaders = context.getZuulRequestHeaders(); 29 | 30 | String protocol = null; 31 | String host = null; 32 | int port = -1; 33 | String path = ""; 34 | 35 | for (Map.Entry entry : zuulRequestHeaders.entrySet()) { 36 | if ("x-forwarded-host".equals(entry.getKey())) { 37 | host = entry.getValue(); 38 | if (host.contains(":")) { 39 | String[] hp = host.split(":"); 40 | host = hp[0]; 41 | if (port == -1) { 42 | try { 43 | port = Integer.valueOf(hp[1]); 44 | } catch (NumberFormatException e) { 45 | // ignore 46 | } 47 | } 48 | } 49 | } 50 | if ("x-forwarded-proto".equals(entry.getKey())) { 51 | protocol = entry.getValue(); 52 | } 53 | if ("x-forwarded-port".equals(entry.getKey())) { 54 | try { 55 | port = Integer.valueOf(entry.getValue()); 56 | } catch (NumberFormatException e) { 57 | // ignore 58 | } 59 | } 60 | if ("x-forwarded-prefix".equals(entry.getKey())) { 61 | String value = entry.getValue(); 62 | if (StringUtils.isNotBlank(value)) { 63 | path = value; 64 | } 65 | } 66 | } 67 | 68 | try { 69 | URL url = new URL(protocol, host, port, path); 70 | return url.toString(); 71 | } catch (MalformedURLException e) { 72 | logger.warn("Could not convert parameters to a URL protocol: {}, host: {}, port: {}", protocol, host, port); 73 | } 74 | 75 | return null; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************* 7 | server: 8 | port: 13020 9 | 10 | management: 11 | port: 13021 12 | security: 13 | enabled: true 14 | context_path: /manage 15 | 16 | info: 17 | version: 0.1.0 18 | stage: dev 19 | 20 | spring: 21 | jackson: 22 | serialization: 23 | write_dates_as_timestamps: false 24 | application: 25 | name: rcloud-gist-service 26 | cloud: 27 | config: 28 | enabled: false 29 | 30 | security: 31 | user: 32 | name: admin 33 | role: ADMIN 34 | basic: 35 | enabled: false 36 | 37 | gists: 38 | root: /var/rcloud-gist-service/gists/ 39 | lockTimeout: 30 40 | security: default 41 | keyservers: 42 | default: 43 | host: 127.0.0.1 44 | port: 4301 45 | realm: rcloud 46 | url: http://{host}:{port}/valid?token={token}&realm={realm} 47 | access_token_param: access_token 48 | client_id_param: client_id 49 | mediatypes: 50 | - application/vnd.github.beta+json 51 | - application/vnd.github.beta 52 | - application/vnd.github.v3+json 53 | - application/vnd.github.v3 54 | route: 55 | redirect: 56 | from: '/login/*' 57 | to: http://example.com 58 | copyparams: true 59 | users: 60 | collaborations: {} 61 | 62 | 63 | 64 | caches: 65 | - 66 | name: 'sessionkeys' 67 | evictionPolicy: LRU 68 | ttl: 60 69 | maxSize: 100 70 | maxIdleSeconds: 60 71 | - 72 | name: 'gists' 73 | evictionPolicy: LRU 74 | ttl: 300 75 | maxSize: 200 76 | maxIdleSeconds: 300 77 | - 78 | name: 'comments' 79 | evictionPolicy: LRU 80 | ttl: 300 81 | maxSize: 200 82 | maxIdleSeconds: 300 83 | - 84 | name: 'commentstore' 85 | evictionPolicy: LRU 86 | ttl: 300 87 | maxSize: 200 88 | maxIdleSeconds: 300 89 | - 90 | name: 'metadatatore' 91 | evictionPolicy: LRU 92 | ttl: 300 93 | maxSize: 200 94 | maxIdleSeconds: 300 95 | - 96 | name: 'historystore' 97 | evictionPolicy: LRU 98 | ttl: 300 99 | maxSize: 200 100 | maxIdleSeconds: 300 101 | - 102 | name: 'filecontentcache' 103 | evictionPolicy: LRU 104 | ttl: 300 105 | maxSize: 200 106 | maxIdleSeconds: 300 107 | 108 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/java/com/mangosolutions/rcloud/gists/filters/ZuulResponseContent.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.gists.filters; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | 12 | import org.apache.commons.io.IOUtils; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | 16 | import com.netflix.zuul.context.RequestContext; 17 | 18 | /** 19 | * Resolves the content of a response going through Zuul 20 | * 21 | */ 22 | public class ZuulResponseContent { 23 | 24 | private static final Logger logger = LoggerFactory.getLogger(ZuulResponseContent.class); 25 | 26 | private RequestContext context; 27 | 28 | public ZuulResponseContent(RequestContext context) { 29 | this.context = context; 30 | } 31 | 32 | /** 33 | * Get the content from the response. 34 | * @return the content obtained from the response. 35 | */ 36 | public String getContent() { 37 | String content = context.getResponseBody(); 38 | if (content == null) { 39 | content = getBodyFromStream(context); 40 | } 41 | return content; 42 | } 43 | 44 | /** 45 | * Clears the response content 46 | */ 47 | public void clearContent() { 48 | if(context.getResponseDataStream() != null) { 49 | IOUtils.closeQuietly(context.getResponseDataStream()); 50 | } 51 | context.setResponseDataStream(null); 52 | context.setResponseBody(null); 53 | } 54 | 55 | /** 56 | * Sets the content onto the response. 57 | * @param content the content to set 58 | */ 59 | public void setContent(String content) { 60 | this.clearContent(); 61 | context.setResponseBody(content); 62 | } 63 | 64 | private String getBodyFromStream(RequestContext context) { 65 | InputStream bodyStream = context.getResponseDataStream(); 66 | if (bodyStream != null) { 67 | return extractAndReplaceBody(context, bodyStream); 68 | } 69 | return null; 70 | } 71 | 72 | private String extractAndReplaceBody(RequestContext context, InputStream bodyStream) { 73 | String body = null; 74 | try { 75 | body = IOUtils.toString(bodyStream); 76 | InputStream newBodyStream = IOUtils.toInputStream(body, "UTF-8"); 77 | context.setResponseDataStream(newBodyStream); 78 | } catch (IOException e) { 79 | logger.warn("Could not extract body.", e); 80 | } finally { 81 | IOUtils.closeQuietly(bodyStream); 82 | } 83 | return body; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/security/CollaborationGrantedAuthority.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.security; 8 | 9 | import java.util.Arrays; 10 | import java.util.Collection; 11 | import java.util.Collections; 12 | import java.util.HashSet; 13 | import java.util.Set; 14 | 15 | import org.eclipse.jgit.util.StringUtils; 16 | import org.springframework.security.core.GrantedAuthority; 17 | 18 | public class CollaborationGrantedAuthority implements GrantedAuthority { 19 | 20 | private static final long serialVersionUID = -413651046802286010L; 21 | 22 | private static final String COLLABORATOR_ROLE = "COLLABORATOR_ROLE"; 23 | 24 | private Set collaborations = Collections.emptySet(); 25 | 26 | public CollaborationGrantedAuthority() { 27 | this(null); 28 | } 29 | 30 | public CollaborationGrantedAuthority(String[] collaborations) { 31 | if(collaborations != null) { 32 | this.collaborations = new HashSet<>(Arrays.asList(collaborations)); 33 | } 34 | } 35 | 36 | @Override 37 | public String getAuthority() { 38 | return COLLABORATOR_ROLE + ":" + StringUtils.join(collaborations, ","); 39 | } 40 | 41 | public Collection getCollaborations() { 42 | return Collections.unmodifiableSet(collaborations); 43 | } 44 | 45 | @Override 46 | public int hashCode() { 47 | final int prime = 31; 48 | int result = 1; 49 | result = prime * result + ((collaborations == null) ? 0 : collaborations.hashCode()); 50 | return result; 51 | } 52 | 53 | @Override 54 | public boolean equals(Object obj) { 55 | if (this == obj) 56 | return true; 57 | if (obj == null) 58 | return false; 59 | if (getClass() != obj.getClass()) 60 | return false; 61 | CollaborationGrantedAuthority other = (CollaborationGrantedAuthority) obj; 62 | if (collaborations == null) { 63 | if (other.collaborations != null) 64 | return false; 65 | } else if (!collaborations.equals(other.collaborations)) 66 | return false; 67 | return true; 68 | } 69 | 70 | @Override 71 | public String toString() { 72 | return "CollaborationGrantedAuthority [collaborations=" + collaborations + "]"; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/java/com/mangosolutions/rcloud/gists/filters/AcceptContentTypeReWritingFilter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.gists.filters; 8 | 9 | import java.util.Map; 10 | 11 | import org.apache.commons.lang.StringUtils; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | import org.springframework.http.HttpHeaders; 15 | import org.springframework.http.MediaType; 16 | 17 | import com.google.common.base.Throwables; 18 | import com.netflix.zuul.ZuulFilter; 19 | import com.netflix.zuul.context.RequestContext; 20 | 21 | public final class AcceptContentTypeReWritingFilter extends ZuulFilter { 22 | 23 | private static final Logger logger = LoggerFactory.getLogger(AcceptContentTypeReWritingFilter.class); 24 | 25 | private int order = 100; 26 | private String path = "/"; 27 | 28 | 29 | public AcceptContentTypeReWritingFilter(String path, int order) { 30 | this.order = order; 31 | this.path = path; 32 | } 33 | 34 | @Override 35 | public String filterType() { 36 | return "pre"; 37 | } 38 | 39 | @Override 40 | public int filterOrder() { 41 | return order; 42 | } 43 | 44 | @Override 45 | public boolean shouldFilter() { 46 | return true; 47 | } 48 | 49 | @Override 50 | public Object run() { 51 | try { 52 | rewriteHeaders(RequestContext.getCurrentContext()); 53 | } catch (final Exception e) { 54 | Throwables.propagate(e); 55 | } 56 | return null; 57 | } 58 | 59 | private void rewriteHeaders(final RequestContext context) { 60 | if(context.getRequest().getRequestURI().startsWith(this.path)) { 61 | Map requestHeaders = context.getZuulRequestHeaders(); 62 | replaceHeader(requestHeaders, HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE); 63 | replaceHeader(requestHeaders, HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_UTF8_VALUE); 64 | } 65 | } 66 | 67 | private void replaceHeader(Map requestHeaders, String headerName, String headerValue) { 68 | String originalValue = requestHeaders.get(headerName); 69 | if(StringUtils.isNotBlank(originalValue)) { 70 | logger.debug("Request header {} has value {}", headerName, originalValue); 71 | requestHeaders.remove(headerName); 72 | requestHeaders.put("X-Original-" + headerName, originalValue); 73 | } 74 | logger.debug("Replacing header {} with value {}", headerName, headerValue); 75 | requestHeaders.put(headerName, headerValue); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/test/java/com/mangosolutions/rcloud/gists/filters/ZuulResponseContentTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.gists.filters; 8 | 9 | import java.io.IOException; 10 | 11 | import org.apache.commons.io.IOUtils; 12 | import org.junit.Assert; 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | 16 | import com.netflix.zuul.context.RequestContext; 17 | 18 | 19 | public class ZuulResponseContentTest { 20 | 21 | private RequestContext context = null; 22 | 23 | 24 | @Before 25 | public void setup() { 26 | context = new RequestContext(); 27 | } 28 | 29 | @Test 30 | public void testGetContentFromText() { 31 | context.setResponseBody("I am some test text"); 32 | ZuulResponseContent content = new ZuulResponseContent(context); 33 | Assert.assertEquals("I am some test text", content.getContent()); 34 | } 35 | 36 | @Test 37 | public void testGetContentFromStream() { 38 | context.setResponseDataStream(IOUtils.toInputStream("I am some test text")); 39 | ZuulResponseContent content = new ZuulResponseContent(context); 40 | Assert.assertEquals("I am some test text", content.getContent()); 41 | } 42 | 43 | @Test 44 | public void testSetContent() throws IOException { 45 | ZuulResponseContent content = new ZuulResponseContent(context); 46 | content.setContent("I am some test text"); 47 | Assert.assertNull(context.getResponseDataStream()); 48 | Assert.assertEquals("I am some test text", context.getResponseBody()); 49 | } 50 | 51 | @Test 52 | public void testClearContentWithNullTextAndStream() { 53 | context.setResponseBody(null); 54 | context.setResponseDataStream(null); 55 | ZuulResponseContent content = new ZuulResponseContent(context); 56 | content.clearContent(); 57 | Assert.assertNull(content.getContent()); 58 | } 59 | 60 | @Test 61 | public void testClearContentWithStream() { 62 | context.setResponseBody(null); 63 | context.setResponseDataStream(IOUtils.toInputStream("I am some test text")); 64 | ZuulResponseContent content = new ZuulResponseContent(context); 65 | content.clearContent(); 66 | Assert.assertNull(content.getContent()); 67 | } 68 | 69 | @Test 70 | public void testClearContentWithText() { 71 | context.setResponseBody("I am some test text"); 72 | context.setResponseDataStream(null); 73 | ZuulResponseContent content = new ZuulResponseContent(context); 74 | content.clearContent(); 75 | Assert.assertNull(content.getContent()); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /rcloud-sessionkey-lib/src/main/java/com/mangosolutions/rcloud/sessionkeyauth/SessionKeyServerResponse.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.sessionkeyauth; 8 | 9 | import java.io.Serializable; 10 | 11 | public class SessionKeyServerResponse implements Serializable { 12 | 13 | private static final long serialVersionUID = 5075823537826850513L; 14 | 15 | private SessionKeyServerResult result = SessionKeyServerResult.NO; 16 | 17 | private String name = null; 18 | 19 | private String source = null; 20 | 21 | public SessionKeyServerResult getResult() { 22 | return result; 23 | } 24 | 25 | public void setResult(SessionKeyServerResult result) { 26 | this.result = result; 27 | } 28 | 29 | public String getName() { 30 | return name; 31 | } 32 | 33 | public void setName(String name) { 34 | this.name = name; 35 | } 36 | 37 | public String getSource() { 38 | return source; 39 | } 40 | 41 | public void setSource(String source) { 42 | this.source = source; 43 | } 44 | 45 | @Override 46 | public int hashCode() { 47 | final int prime = 31; 48 | int result = 1; 49 | result = prime * result + ((name == null) ? 0 : name.hashCode()); 50 | result = prime * result + ((this.result == null) ? 0 : this.result.hashCode()); 51 | result = prime * result + ((source == null) ? 0 : source.hashCode()); 52 | return result; 53 | } 54 | 55 | @Override 56 | public boolean equals(Object obj) { 57 | if (this == obj) 58 | return true; 59 | if (obj == null) 60 | return false; 61 | if (getClass() != obj.getClass()) 62 | return false; 63 | SessionKeyServerResponse other = (SessionKeyServerResponse) obj; 64 | if (name == null) { 65 | if (other.name != null) 66 | return false; 67 | } else if (!name.equals(other.name)) 68 | return false; 69 | if (result != other.result) 70 | return false; 71 | if (source == null) { 72 | if (other.source != null) 73 | return false; 74 | } else if (!source.equals(other.source)) 75 | return false; 76 | return true; 77 | } 78 | 79 | @Override 80 | public String toString() { 81 | return "SessionKeyServerResponse [result=" + result + ", name=" + name + ", source=" + source + "]"; 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/pkg/home/service.conf: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************/ 7 | MAX_MEM=512m 8 | MIN_MEM=64m 9 | 10 | JAVA_OPTS="${JAVA_OPTS} -Xms${MIN_MEM} -Xmx${MAX_MEM}" 11 | 12 | # Increase maximum perm size for web base applications to 4x the default amount 13 | # http://wiki.apache.org/tomcat/FAQ/Memoryhttp://wiki.apache.org/tomcat/FAQ/Memory 14 | JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256m" 15 | 16 | # Reset the default stack size for threads to a lower value (by 1/10th original) 17 | # By default this can be anywhere between 512k -> 1024k depending on x32 or x64 18 | # bit Java version. 19 | # http://www.springsource.com/files/uploads/tomcat/tomcatx-large-scale-deployments.pdf 20 | # http://www.oracle.com/technetwork/java/hotspotfaq-138619.html 21 | JAVA_OPTS="${JAVA_OPTS} -Xss228k" 22 | 23 | # Oracle Java as default, uses the serial garbage collector on the 24 | # Full Tenured heap. The Young space is collected in parallel, but the 25 | # Tenured is not. This means that at a time of load if a full collection 26 | # event occurs, since the event is a 'stop-the-world' serial event then 27 | # all application threads other than the garbage collector thread are 28 | # taken off the CPU. This can have severe consequences if requests continue 29 | # to accrue during these 'outage' periods. (specifically webservices, webapps) 30 | # [Also enables adaptive sizing automatically] 31 | JAVA_OPTS="${JAVA_OPTS} -XX:+UseParallelGC" 32 | 33 | # This is interpreted as a hint to the garbage collector that pause times 34 | # of milliseconds or less are desired. The garbage collector will 35 | # adjust the Java heap size and other garbage collection related parameters 36 | # in an attempt to keep garbage collection pauses shorter than milliseconds. 37 | # http://java.sun.com/docs/hotspot/gc5.0/ergo5.html 38 | JAVA_OPTS="${JAVA_OPTS} -XX:MaxGCPauseMillis=1500" 39 | 40 | # A hint to the virtual machine that it.s desirable that not more than: 41 | # 1 / (1 + GCTimeRation) of the application execution time be spent in 42 | # the garbage collector. 43 | # http://themindstorms.wordpress.com/2009/01/21/advanced-jvm-tuning-for-low-pause/ 44 | JAVA_OPTS="${JAVA_OPTS} -XX:GCTimeRatio=9" 45 | 46 | # The hotspot server JVM has specific code-path optimizations 47 | # which yield an approximate 10% gain over the client version. 48 | JAVA_OPTS="${JAVA_OPTS} -server" 49 | 50 | # Disable remote (distributed) garbage collection by Java clients 51 | # and remove ability for applications to call explicit GC collection 52 | JAVA_OPTS="${JAVA_OPTS} -XX:+DisableExplicitGC" 53 | 54 | # LOG file is not in default location 55 | LOG_FOLDER=/var/log/rcloud-gist-service 56 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/test/java/com/mangosolutions/rcloud/gists/filters/HeaderUrlRewritingFilterTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.gists.filters; 8 | 9 | import java.net.MalformedURLException; 10 | import java.net.URL; 11 | import java.util.List; 12 | 13 | import org.junit.Assert; 14 | import org.junit.Before; 15 | import org.junit.Test; 16 | 17 | import com.netflix.util.Pair; 18 | import com.netflix.zuul.context.RequestContext; 19 | 20 | public class HeaderUrlRewritingFilterTest { 21 | 22 | 23 | @Before 24 | public void setupHeaders() throws MalformedURLException { 25 | RequestContext context = RequestContext.getCurrentContext(); 26 | //add link header 27 | context.addZuulResponseHeader("Link", "; rel=\"next\", ; rel=\"last\""); 28 | //add location header 29 | context.addZuulResponseHeader("Location", "https://api.github.com"); 30 | //add another header 31 | context.addZuulResponseHeader("Content-Type", "application/json"); 32 | 33 | context.addZuulResponseHeader("Blacklist-Header", "https://api.github.com"); 34 | 35 | context.addZuulRequestHeader("x-forwarded-host", "localhost:8080"); 36 | context.addZuulRequestHeader("x-forwarded-proto", "http"); 37 | context.addZuulRequestHeader("x-forwarded-port", "8080"); 38 | context.setRouteHost(new URL("https://api.github.com")); 39 | } 40 | 41 | @Test 42 | public void filterHeaders() { 43 | RequestContext context = RequestContext.getCurrentContext(); 44 | Assert.assertNotNull(context); 45 | HeaderUrlRewritingFilter filter = new HeaderUrlRewritingFilter(1); 46 | filter.run(); 47 | List> headers = context.getZuulResponseHeaders(); 48 | for(Pair header: headers) { 49 | if(header.first().startsWith("Blacklist")) { 50 | Assert.assertTrue("expected " + header.second() + " to contain https://api.github.com" , header.second().contains("https://api.github.com")); 51 | } else if(filter.getWhitelist().contains(header.first())) { 52 | Assert.assertTrue("expected " + header.second() + " to contain http://localhost:8080", header.second().contains("http://localhost:8080")); 53 | Assert.assertFalse("expected " + header.second() + " to not contain https://api.github.com", header.second().contains("https://api.github.com")); 54 | } else { 55 | Assert.assertFalse("expected " + header.second() + " to not contain https://api.github.com", header.second().contains("https://api.github.com")); 56 | } 57 | } 58 | 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/model/GistRequest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.model; 8 | 9 | import java.io.Serializable; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 14 | import com.fasterxml.jackson.annotation.JsonAnySetter; 15 | import com.fasterxml.jackson.annotation.JsonIgnore; 16 | import com.fasterxml.jackson.annotation.JsonInclude; 17 | import com.fasterxml.jackson.annotation.JsonProperty; 18 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 19 | 20 | @JsonInclude(JsonInclude.Include.ALWAYS) 21 | @JsonPropertyOrder({ "owner", "description", "public", "files" }) 22 | public class GistRequest implements Serializable { 23 | 24 | private final static long serialVersionUID = -7352290872081419828L; 25 | 26 | @JsonProperty("description") 27 | private String description; 28 | 29 | @JsonProperty("public") 30 | private Boolean _public; 31 | 32 | @JsonProperty("owner") 33 | private String owner; 34 | 35 | @JsonProperty("files") 36 | private Map files; 37 | 38 | @JsonIgnore 39 | private Map additionalProperties = new HashMap(); 40 | 41 | @JsonProperty("owner") 42 | public String getOwner() { 43 | return owner; 44 | } 45 | 46 | @JsonProperty("owner") 47 | public void setOwner(String owner) { 48 | this.owner = owner; 49 | } 50 | 51 | @JsonProperty("description") 52 | public String getDescription() { 53 | return description; 54 | } 55 | 56 | @JsonProperty("description") 57 | public void setDescription(String description) { 58 | this.description = description; 59 | } 60 | 61 | @JsonProperty("public") 62 | public Boolean getPublic() { 63 | return _public; 64 | } 65 | 66 | @JsonProperty("public") 67 | public void setPublic(Boolean _public) { 68 | this._public = _public; 69 | } 70 | 71 | @JsonProperty("files") 72 | public Map getFiles() { 73 | return files; 74 | } 75 | 76 | @JsonProperty("files") 77 | public void setFiles(Map files) { 78 | this.files = files; 79 | } 80 | 81 | @JsonAnyGetter 82 | public Map getAdditionalProperties() { 83 | return this.additionalProperties; 84 | } 85 | 86 | @JsonAnySetter 87 | public void setAdditionalProperty(String name, Object value) { 88 | this.additionalProperties.put(name, value); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/pkg/home/service.conf: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************/ 7 | MAX_MEM=512m 8 | MIN_MEM=64m 9 | 10 | JAVA_OPTS="${JAVA_OPTS} -Xms${MIN_MEM} -Xmx${MAX_MEM}" 11 | 12 | # Increase maximum perm size for web base applications to 4x the default amount 13 | # http://wiki.apache.org/tomcat/FAQ/Memoryhttp://wiki.apache.org/tomcat/FAQ/Memory 14 | JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256m" 15 | 16 | # Reset the default stack size for threads to a lower value (by 1/10th original) 17 | # By default this can be anywhere between 512k -> 1024k depending on x32 or x64 18 | # bit Java version. 19 | # http://www.springsource.com/files/uploads/tomcat/tomcatx-large-scale-deployments.pdf 20 | # http://www.oracle.com/technetwork/java/hotspotfaq-138619.html 21 | JAVA_OPTS="${JAVA_OPTS} -Xss228k" 22 | 23 | # Oracle Java as default, uses the serial garbage collector on the 24 | # Full Tenured heap. The Young space is collected in parallel, but the 25 | # Tenured is not. This means that at a time of load if a full collection 26 | # event occurs, since the event is a 'stop-the-world' serial event then 27 | # all application threads other than the garbage collector thread are 28 | # taken off the CPU. This can have severe consequences if requests continue 29 | # to accrue during these 'outage' periods. (specifically webservices, webapps) 30 | # [Also enables adaptive sizing automatically] 31 | JAVA_OPTS="${JAVA_OPTS} -XX:+UseParallelGC" 32 | 33 | # This is interpreted as a hint to the garbage collector that pause times 34 | # of milliseconds or less are desired. The garbage collector will 35 | # adjust the Java heap size and other garbage collection related parameters 36 | # in an attempt to keep garbage collection pauses shorter than milliseconds. 37 | # http://java.sun.com/docs/hotspot/gc5.0/ergo5.html 38 | JAVA_OPTS="${JAVA_OPTS} -XX:MaxGCPauseMillis=1500" 39 | 40 | # A hint to the virtual machine that it.s desirable that not more than: 41 | # 1 / (1 + GCTimeRation) of the application execution time be spent in 42 | # the garbage collector. 43 | # http://themindstorms.wordpress.com/2009/01/21/advanced-jvm-tuning-for-low-pause/ 44 | JAVA_OPTS="${JAVA_OPTS} -XX:GCTimeRatio=9" 45 | 46 | # The hotspot server JVM has specific code-path optimizations 47 | # which yield an approximate 10% gain over the client version. 48 | JAVA_OPTS="${JAVA_OPTS} -server" 49 | 50 | # Disable remote (distributed) garbage collection by Java clients 51 | # and remove ability for applications to call explicit GC collection 52 | JAVA_OPTS="${JAVA_OPTS} -XX:+DisableExplicitGC" 53 | 54 | # LOG file is not in default location 55 | LOG_FOLDER=/var/log/rcloud-gistproxy-service 56 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/pkg/home/application.yml: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************/ 7 | ################################################################################ 8 | # Application port. Change the value below to change the port this service 9 | # is listening on. 10 | ################################################################################ 11 | server: 12 | port: 13010 13 | 14 | ################################################################################ 15 | # Management port. Change the value below to change the port the management 16 | # services are listening on. 17 | ################################################################################ 18 | management: 19 | port: 13011 20 | 21 | ################################################################################ 22 | # Logging configuration: 23 | # config: The logback configuration file for logging. 24 | # file: The log file to write the log out to. 25 | ################################################################################ 26 | logging: 27 | config: logback.xml 28 | file: /var/log/${spring.application.name}/${spring.application.name}-file.log 29 | 30 | ################################################################################ 31 | # GitHub proxy settings. 32 | ################################################################################ 33 | github: 34 | api: 35 | url: https://api.github.com 36 | ################################################################################ 37 | # RCLoud proxy settings 38 | ################################################################################ 39 | rcloud: 40 | gists: 41 | url: http://localhost:13020 42 | 43 | ################################################################################ 44 | # Security information for administrative access. 45 | # Default user is 'admin' default password is generated on startup and printed 46 | # out in the log file. To override these settings uncomment the lines below 47 | # and specify your own password. 48 | ################################################################################ 49 | #security: 50 | # user: 51 | # name: admin 52 | # password: secret 53 | 54 | ################################################################################ 55 | # Application profiles that change the behaviour. Default is the `rcloudgist` 56 | # profile that sets up the proxy to route gist requests to the 57 | # rcloud-gist-service, uncomment the following to change the proxying to proxy 58 | # every request only to github. 59 | ################################################################################ 60 | #spring: 61 | # profiles: 62 | # active: github 63 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/model/GistIdentity.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.model; 8 | 9 | import java.io.Serializable; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 13 | import com.fasterxml.jackson.annotation.JsonAnySetter; 14 | import com.fasterxml.jackson.annotation.JsonIgnore; 15 | import com.fasterxml.jackson.annotation.JsonInclude; 16 | import com.fasterxml.jackson.annotation.JsonProperty; 17 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 18 | 19 | @JsonInclude(JsonInclude.Include.ALWAYS) 20 | @JsonPropertyOrder({ 21 | "login" 22 | }) 23 | public class GistIdentity implements Serializable 24 | { 25 | 26 | @JsonProperty("login") 27 | private String login; 28 | @JsonIgnore 29 | private Map additionalProperties = new HashMap(); 30 | private final static long serialVersionUID = 938605199482828189L; 31 | 32 | @JsonProperty("login") 33 | public String getLogin() { 34 | return login; 35 | } 36 | 37 | @JsonProperty("login") 38 | public void setLogin(String login) { 39 | this.login = login; 40 | } 41 | 42 | @JsonAnyGetter 43 | public Map getAdditionalProperties() { 44 | return this.additionalProperties; 45 | } 46 | 47 | @JsonAnySetter 48 | public void setAdditionalProperty(String name, Object value) { 49 | this.additionalProperties.put(name, value); 50 | } 51 | 52 | @Override 53 | public int hashCode() { 54 | final int prime = 31; 55 | int result = 1; 56 | result = prime * result + ((additionalProperties == null) ? 0 : additionalProperties.hashCode()); 57 | result = prime * result + ((login == null) ? 0 : login.hashCode()); 58 | return result; 59 | } 60 | 61 | @Override 62 | public boolean equals(Object obj) { 63 | if (this == obj) 64 | return true; 65 | if (obj == null) 66 | return false; 67 | if (getClass() != obj.getClass()) 68 | return false; 69 | GistIdentity other = (GistIdentity) obj; 70 | if (additionalProperties == null) { 71 | if (other.additionalProperties != null) 72 | return false; 73 | } else if (!additionalProperties.equals(other.additionalProperties)) 74 | return false; 75 | if (login == null) { 76 | if (other.login != null) 77 | return false; 78 | } else if (!login.equals(other.login)) 79 | return false; 80 | return true; 81 | } 82 | 83 | @Override 84 | public String toString() { 85 | return "GistIdentity [login=" + login + ", additionalProperties=" + additionalProperties + "]"; 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/GistMetadataStore.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import java.io.File; 10 | import java.io.IOException; 11 | 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.cache.annotation.CachePut; 16 | import org.springframework.cache.annotation.Cacheable; 17 | import org.springframework.stereotype.Component; 18 | 19 | import com.fasterxml.jackson.databind.ObjectMapper; 20 | import com.mangosolutions.rcloud.rawgist.repository.GistError; 21 | import com.mangosolutions.rcloud.rawgist.repository.GistErrorCode; 22 | import com.mangosolutions.rcloud.rawgist.repository.GistRepositoryError; 23 | 24 | @Component 25 | public class GistMetadataStore implements MetadataStore { 26 | 27 | private static final Logger logger = LoggerFactory.getLogger(GistMetadataStore.class); 28 | 29 | @Autowired 30 | private ObjectMapper objectMapper; 31 | 32 | public GistMetadataStore() { 33 | this.objectMapper = new ObjectMapper(); 34 | } 35 | 36 | @Autowired 37 | public GistMetadataStore(ObjectMapper objectMapper) { 38 | this.objectMapper = objectMapper; 39 | } 40 | 41 | public ObjectMapper getObjectMapper() { 42 | return objectMapper; 43 | } 44 | 45 | public void setObjectMapper(ObjectMapper objectMapper) { 46 | this.objectMapper = objectMapper; 47 | } 48 | 49 | 50 | @Override 51 | @Cacheable(value = "metadatastore", key = "#store.getAbsolutePath()") 52 | public GistMetadata load(File store) { 53 | GistMetadata metadata = null; 54 | if(store.exists()) { 55 | try { 56 | metadata = objectMapper.readValue(store, GistMetadata.class); 57 | } catch (IOException e) { 58 | GistError error = new GistError(GistErrorCode.ERR_METADATA_NOT_READABLE, "Could not read metadata for this gist"); 59 | logger.error(error.getFormattedMessage() + " with path {}", store); 60 | throw new GistRepositoryError(error, e); 61 | } 62 | } else { 63 | metadata = new GistMetadata(); 64 | } 65 | return metadata; 66 | } 67 | 68 | @Override 69 | @CachePut(cacheNames = "metadatastore", key = "#store.getAbsolutePath()") 70 | public GistMetadata save(File store, GistMetadata metadata) { 71 | try { 72 | objectMapper.writeValue(store, metadata); 73 | } catch (IOException e) { 74 | GistError error = new GistError(GistErrorCode.ERR_METADATA_NOT_WRITEABLE, "Could not update metadata for gist {}", metadata.getId()); 75 | logger.error(error.getFormattedMessage() + " with path {}", store); 76 | throw new GistRepositoryError(error, e); 77 | } 78 | return metadata; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/GistServiceProperties.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import org.springframework.boot.context.properties.ConfigurationProperties; 13 | import org.springframework.boot.context.properties.NestedConfigurationProperty; 14 | 15 | @ConfigurationProperties(prefix = "gists") 16 | public class GistServiceProperties { 17 | 18 | public static final String STRICT_SECURITY_MANAGER = "strict"; 19 | public static final String PERMISSIVE_SECURITY_MANAGER = "permissive"; 20 | 21 | @NestedConfigurationProperty 22 | private GistUsersProperties users = new GistUsersProperties(); 23 | 24 | private String security = "default"; 25 | 26 | private String root; 27 | 28 | private String cache = "gists"; 29 | 30 | private int lockTimeout = 30; 31 | 32 | private String sessionKeyServerUrl = null; 33 | 34 | private String sessionKeyServerRealm = "rcloud"; 35 | 36 | private List mediatypes = new ArrayList<>(); 37 | 38 | 39 | public String getSessionKeyServerRealm() { 40 | return sessionKeyServerRealm; 41 | } 42 | 43 | public void setSessionKeyServerRealm(String sessionKeyServerRealm) { 44 | this.sessionKeyServerRealm = sessionKeyServerRealm; 45 | } 46 | 47 | public int getLockTimeout() { 48 | return lockTimeout; 49 | } 50 | 51 | public void setLockTimeout(int lockTimeout) { 52 | this.lockTimeout = lockTimeout; 53 | } 54 | 55 | public String getRoot() { 56 | return root; 57 | } 58 | 59 | public void setRoot(String root) { 60 | this.root = root; 61 | } 62 | 63 | public String getCache() { 64 | return cache; 65 | } 66 | 67 | public void setCache(String cacheName) { 68 | this.cache = cacheName; 69 | } 70 | 71 | public String getSessionKeyServerUrl() { 72 | return sessionKeyServerUrl; 73 | } 74 | 75 | public void setSessionKeyServerUrl(String sessionKeyServerUrl) { 76 | this.sessionKeyServerUrl = sessionKeyServerUrl; 77 | } 78 | 79 | public List getMediatypes() { 80 | return mediatypes; 81 | } 82 | 83 | public void setMediatypes(List mediatypes) { 84 | this.mediatypes = mediatypes; 85 | } 86 | 87 | public String getSecurity() { 88 | return security; 89 | } 90 | 91 | public void setSecurity(String securityManager) { 92 | this.security = securityManager; 93 | } 94 | 95 | public GistUsersProperties getUsers() { 96 | return users; 97 | } 98 | 99 | public void setUsers(GistUsersProperties users) { 100 | this.users = users; 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/test/java/com/mangosolutions/rcloud/rawgist/GrantedAuthorityFactoryTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | import static org.junit.Assert.assertNotNull; 11 | 12 | import java.util.Arrays; 13 | import java.util.Collection; 14 | 15 | import org.junit.Before; 16 | import org.junit.Test; 17 | import org.springframework.security.core.GrantedAuthority; 18 | 19 | import com.mangosolutions.rcloud.rawgist.repository.security.CollaborationGrantedAuthority; 20 | import com.mangosolutions.rcloud.rawgist.repository.security.CollaborationGrantedAuthorityResolver; 21 | import com.mangosolutions.rcloud.sessionkeyauth.AnonymousUserAuthorityResolver; 22 | import com.mangosolutions.rcloud.sessionkeyauth.AuthorityResolver; 23 | import com.mangosolutions.rcloud.sessionkeyauth.GrantedAuthorityFactory; 24 | import com.mangosolutions.rcloud.sessionkeyauth.UserAuthorityResolver; 25 | 26 | public class GrantedAuthorityFactoryTest { 27 | 28 | GrantedAuthorityFactory factory = new GrantedAuthorityFactory(); 29 | 30 | @Before 31 | public void setup() { 32 | Collection authorityResolvers = Arrays.asList(new AnonymousUserAuthorityResolver(), 33 | new UserAuthorityResolver(), new CollaborationGrantedAuthorityResolver()); 34 | factory.setAuthorityResolvers(authorityResolvers); 35 | } 36 | 37 | @Test 38 | public void nullUsernameAnonymousAuthority() { 39 | Collection authorities = factory.resolve(null); 40 | assertNotNull(authorities); 41 | assertEquals(1, authorities.size()); 42 | authorities.contains(AnonymousUserAuthorityResolver.ANONYMOUS_AUTHORITY); 43 | } 44 | 45 | @Test 46 | public void emptyUsernameAnonymousAuthority() { 47 | Collection authorities = factory.resolve(""); 48 | assertNotNull(authorities); 49 | assertEquals(1, authorities.size()); 50 | authorities.contains(AnonymousUserAuthorityResolver.ANONYMOUS_AUTHORITY); 51 | } 52 | 53 | @Test 54 | public void blankUsernameAnonymousAuthority() { 55 | Collection authorities = factory.resolve(" "); 56 | assertNotNull(authorities); 57 | assertEquals(1, authorities.size()); 58 | authorities.contains(AnonymousUserAuthorityResolver.ANONYMOUS_AUTHORITY); 59 | } 60 | 61 | @Test 62 | public void usernameUserAuthority() { 63 | Collection authorities = factory.resolve("adam"); 64 | assertNotNull(authorities); 65 | assertEquals(3, authorities.size()); 66 | authorities.contains(AnonymousUserAuthorityResolver.ANONYMOUS_AUTHORITY); 67 | authorities.contains(UserAuthorityResolver.USER_AUTHORITY); 68 | authorities.contains(new CollaborationGrantedAuthority()); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/build.gradle: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | 8 | project.description = "RCloud Gist service providing gist access api." 9 | 10 | dependencies { 11 | compile 'org.springframework.boot:spring-boot-starter' 12 | compile 'org.springframework.boot:spring-boot-starter-actuator' 13 | compile 'org.springframework.boot:spring-boot-starter-security' 14 | compile 'org.springframework.boot:spring-boot-starter-web' 15 | compile 'org.springframework.cloud:spring-cloud-starter' 16 | compile 'org.springframework.cloud:spring-cloud-starter-zuul' 17 | compile 'com.eclipsesource.minimal-json:minimal-json:0.9.4' 18 | 19 | testCompile 'junit:junit:4.11' 20 | testCompile 'org.mockito:mockito-all:1.10.8' 21 | testCompile 'org.springframework.boot:spring-boot-starter-test' 22 | 23 | } 24 | 25 | 26 | ext.pkg = [:] 27 | pkg.name = archivesBaseName 28 | pkg.installPath = '/opt/' + pkg.name 29 | pkg.jarName = archivesBaseName + '-' + project.version + '.jar' 30 | pkg.jarPath = pkg.installPath + '/' + pkg.jarName 31 | pkg.initPath = '/etc/init.d/' + archivesBaseName 32 | pkg.description = project.description 33 | pkg.summary = "RCloud Gist Proxy Service" 34 | pkg.vendor = "Mango Solutions Ltd." 35 | pkg.url = projectUrl 36 | pkg.buildId = new Date().format('yyyyMMddHHmmss') 37 | pkg.version = project.version.replaceAll("-", ".") 38 | pkg.user = 'rcloudgistservice' 39 | pkg.group = pkg.user 40 | 41 | ospackage { 42 | packageName = pkg.name 43 | version = pkg.version 44 | release = pkg.buildId 45 | os = LINUX 46 | user = pkg.user 47 | group = pkg.group 48 | summary = pkg.summary 49 | vendor = pkg.vendor 50 | packageDescription = pkg.description 51 | url = pkg.url 52 | type = BINARY 53 | 54 | //create user and group 55 | preInstall "/usr/sbin/useradd -c \"$pkg.summary\" -r -d $pkg.installPath $pkg.user 2>/dev/null || :" 56 | 57 | //create log directory 58 | preInstall "mkdir -p /var/log/$pkg.name && chown $pkg.user:root /var/log/$pkg.name" 59 | 60 | into(pkg.installPath) 61 | 62 | from(jar.outputs.files) { 63 | fileMode 0770 64 | } 65 | 66 | from('src/main/pkg/home') { 67 | fileType CONFIG | NOREPLACE 68 | filter (org.apache.tools.ant.filters.ReplaceTokens, tokens: pkg ) 69 | rename { String fileName -> 70 | if(fileName.equals("service.conf")) { 71 | fileName.replace('service', project.name + "-" + project.version) 72 | } else if(fileName.equals("systemd.service")) { 73 | fileName.replace('systemd', pkg.name) 74 | } else { 75 | fileName 76 | } 77 | } 78 | fileMode 0660 79 | } 80 | //systemv symlink 81 | link(pkg.initPath, pkg.jarPath) 82 | //The following link is for systemd based systems, at the moment the above systemv symlink will suffice 83 | //link("/etc/systemd/system/" + pkg.name + ".service", pkg.installPath + "/" + pkg.name + ".service") 84 | } 85 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/GistCommentStore.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.cache.annotation.CachePut; 18 | import org.springframework.cache.annotation.Cacheable; 19 | import org.springframework.stereotype.Component; 20 | 21 | import com.fasterxml.jackson.core.type.TypeReference; 22 | import com.fasterxml.jackson.databind.ObjectMapper; 23 | import com.mangosolutions.rcloud.rawgist.model.GistCommentResponse; 24 | import com.mangosolutions.rcloud.rawgist.repository.GistError; 25 | import com.mangosolutions.rcloud.rawgist.repository.GistErrorCode; 26 | import com.mangosolutions.rcloud.rawgist.repository.GistRepositoryError; 27 | 28 | @Component 29 | public class GistCommentStore implements CommentStore { 30 | 31 | private static final Logger logger = LoggerFactory.getLogger(GistCommentStore.class); 32 | 33 | @Autowired 34 | private ObjectMapper objectMapper; 35 | 36 | public GistCommentStore() { 37 | this.objectMapper = new ObjectMapper(); 38 | } 39 | 40 | @Autowired 41 | public GistCommentStore(ObjectMapper objectMapper) { 42 | this.objectMapper = objectMapper; 43 | } 44 | 45 | public ObjectMapper getObjectMapper() { 46 | return objectMapper; 47 | } 48 | 49 | public void setObjectMapper(ObjectMapper objectMapper) { 50 | this.objectMapper = objectMapper; 51 | } 52 | 53 | @Override 54 | @Cacheable(value = "commentstore", key = "#store.getAbsolutePath()") 55 | public List load(File store) { 56 | List comments = new ArrayList<>(); 57 | if (store.exists()) { 58 | try { 59 | comments = objectMapper.readValue(store, new TypeReference>() { 60 | }); 61 | } catch (IOException e) { 62 | GistError error = new GistError(GistErrorCode.ERR_COMMENTS_NOT_READABLE, "Could not read comments"); 63 | logger.error(error.getFormattedMessage() + " with path {}", store); 64 | throw new GistRepositoryError(error, e); 65 | } 66 | } 67 | return comments == null? new ArrayList(): comments; 68 | } 69 | 70 | @Override 71 | @CachePut(cacheNames = "commentstore", key = "#store.getAbsolutePath()") 72 | public List save(File store, List comments) { 73 | if(comments != null) { 74 | try { 75 | objectMapper.writeValue(store, comments); 76 | } catch (IOException e) { 77 | GistError error = new GistError(GistErrorCode.ERR_COMMENTS_NOT_WRITEABLE, "Could not save comments"); 78 | logger.error(error.getFormattedMessage() + " with path {}", store); 79 | throw new GistRepositoryError(error, e); 80 | } 81 | } 82 | return comments; 83 | } 84 | 85 | 86 | 87 | } 88 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/RequestParameterAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | 11 | import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; 12 | import org.springframework.security.web.authentication.preauth.PreAuthenticatedCredentialsNotFoundException; 13 | import org.springframework.util.Assert; 14 | 15 | public class RequestParameterAuthenticationFilter extends AbstractPreAuthenticatedProcessingFilter { 16 | 17 | private String principalRequestParameter = "access_token"; 18 | private String credentialsRequestParameter; 19 | private boolean exceptionIfParameterMissing = true; 20 | 21 | /** 22 | * Read and returns the header named by {@code principalRequestParameter} from the 23 | * request. 24 | * 25 | * @throws PreAuthenticatedCredentialsNotFoundException if the header is missing and 26 | * {@code exceptionIfHeaderMissing} is set to {@code true}. 27 | */ 28 | @Override 29 | protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) { 30 | String principal = request.getParameter(principalRequestParameter); 31 | 32 | if (principal == null && exceptionIfParameterMissing) { 33 | throw new PreAuthenticatedCredentialsNotFoundException(principalRequestParameter 34 | + " parameter not found in request."); 35 | } else { 36 | principal = principal == null? "": principal; 37 | } 38 | 39 | return principal; 40 | } 41 | 42 | /** 43 | * Credentials aren't usually applicable, but if a {@code credentialsRequestParameter} is 44 | * set, this will be read and used as the credentials value. Otherwise a dummy value 45 | * will be used. 46 | */ 47 | @Override 48 | protected Object getPreAuthenticatedCredentials(HttpServletRequest request) { 49 | if (credentialsRequestParameter != null) { 50 | return request.getParameter(credentialsRequestParameter); 51 | } 52 | 53 | return "N/A"; 54 | } 55 | 56 | public void setPrincipalRequestParameter(String principalRequestParameter) { 57 | Assert.hasText(principalRequestParameter, 58 | "principalRequestHeader must not be empty or null"); 59 | this.principalRequestParameter = principalRequestParameter; 60 | } 61 | 62 | public void setCredentialsRequestParameter(String credentialsRequestParameter) { 63 | Assert.hasText(credentialsRequestParameter, 64 | "credentialsRequestHeader must not be empty or null"); 65 | this.credentialsRequestParameter = credentialsRequestParameter; 66 | } 67 | 68 | /** 69 | * Defines whether an exception should be raised if the principal paramater is missing. 70 | * Defaults to {@code true}. 71 | * 72 | * @param exceptionIfParameterMissing set to {@code false} to override the default 73 | * behaviour and allow the request to proceed if no header is found. 74 | */ 75 | public void setExceptionIfParameterMissing(boolean exceptionIfParameterMissing) { 76 | this.exceptionIfParameterMissing = exceptionIfParameterMissing; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/model/GistCommentResponse.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.model; 8 | 9 | import java.io.Serializable; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | import org.joda.time.DateTime; 14 | 15 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 16 | import com.fasterxml.jackson.annotation.JsonAnySetter; 17 | import com.fasterxml.jackson.annotation.JsonIgnore; 18 | import com.fasterxml.jackson.annotation.JsonInclude; 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 21 | 22 | @JsonInclude(JsonInclude.Include.ALWAYS) 23 | @JsonPropertyOrder({ "url", "id", "user", "body", "created_at", "updated_at" }) 24 | public class GistCommentResponse implements Serializable { 25 | 26 | @JsonProperty("id") 27 | private Long id; 28 | 29 | @JsonProperty("url") 30 | private String url; 31 | 32 | @JsonProperty("body") 33 | private String body; 34 | 35 | @JsonProperty("user") 36 | private GistIdentity user; 37 | 38 | @JsonProperty("created_at") 39 | private DateTime createdAt; 40 | 41 | @JsonProperty("updated_at") 42 | private DateTime updatedAt; 43 | 44 | @JsonIgnore 45 | private Map additionalProperties = new HashMap(); 46 | 47 | private final static long serialVersionUID = 5239803736959473806L; 48 | 49 | @JsonProperty("id") 50 | public Long getId() { 51 | return id; 52 | } 53 | 54 | @JsonProperty("id") 55 | public void setId(Long id) { 56 | this.id = id; 57 | } 58 | 59 | public GistIdentity getUser() { 60 | return user; 61 | } 62 | 63 | public void setUser(GistIdentity user) { 64 | this.user = user; 65 | } 66 | 67 | @JsonProperty("url") 68 | public String getUrl() { 69 | return url; 70 | } 71 | 72 | @JsonProperty("url") 73 | public void setUrl(String url) { 74 | this.url = url; 75 | } 76 | 77 | @JsonProperty("body") 78 | public String getBody() { 79 | return body; 80 | } 81 | 82 | @JsonProperty("body") 83 | public void setBody(String body) { 84 | this.body = body; 85 | } 86 | 87 | @JsonProperty("created_at") 88 | public DateTime getCreatedAt() { 89 | return createdAt; 90 | } 91 | 92 | @JsonProperty("created_at") 93 | public void setCreatedAt(DateTime createdAt) { 94 | this.createdAt = createdAt; 95 | } 96 | 97 | @JsonProperty("updated_at") 98 | public DateTime getUpdatedAt() { 99 | return updatedAt; 100 | } 101 | 102 | @JsonProperty("updated_at") 103 | public void setUpdatedAt(DateTime updatedAt) { 104 | this.updatedAt = updatedAt; 105 | } 106 | 107 | @JsonAnyGetter 108 | public Map getAdditionalProperties() { 109 | return this.additionalProperties; 110 | } 111 | 112 | @JsonAnySetter 113 | public void setAdditionalProperty(String name, Object value) { 114 | this.additionalProperties.put(name, value); 115 | } 116 | 117 | public void addAdditionalProperties(Map properties) { 118 | this.additionalProperties.putAll(properties); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/security/SimpleGistSecurityManager.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.security; 8 | 9 | import java.util.Arrays; 10 | import java.util.Collection; 11 | import java.util.Collections; 12 | import java.util.HashSet; 13 | import java.util.Set; 14 | 15 | import org.springframework.security.core.userdetails.UserDetails; 16 | 17 | import com.mangosolutions.rcloud.rawgist.repository.GistRepository; 18 | import com.mangosolutions.rcloud.rawgist.repository.GistSecurityManager; 19 | import com.mangosolutions.rcloud.rawgist.repository.git.GistMetadata; 20 | 21 | public class SimpleGistSecurityManager implements GistSecurityManager { 22 | 23 | private static final Set READ_RIGHTS = new HashSet<>( 24 | Arrays.asList(GistAccessRight.READ, GistAccessRight.WRITE)); 25 | private static final Set WRITE_RIGHTS = new HashSet<>(Arrays.asList(GistAccessRight.WRITE)); 26 | 27 | @Override 28 | public boolean canRead(GistRepository repository, UserDetails userDetails) { 29 | return READ_RIGHTS.contains(this.getAccessRight(repository, userDetails)); 30 | } 31 | 32 | @Override 33 | public boolean canWrite(GistRepository repository, UserDetails userDetails) { 34 | return WRITE_RIGHTS.contains(this.getAccessRight(repository, userDetails)); 35 | } 36 | 37 | @Override 38 | public boolean isOwner(GistRepository repository, UserDetails userDetails) { 39 | return GistRole.OWNER.equals(this.getRole(repository, userDetails)); 40 | } 41 | 42 | @Override 43 | public GistRole getRole(GistRepository repository, UserDetails userDetails) { 44 | return this.isOwner(this.getMetaData(repository), userDetails) ? GistRole.OWNER : GistRole.COLLABORATOR; 45 | } 46 | 47 | @Override 48 | public GistAccessRight getAccessRight(GistRepository repository, UserDetails userDetails) { 49 | GistMetadata metadata = getMetaData(repository); 50 | 51 | if (this.canWrite(metadata, userDetails)) { 52 | return GistAccessRight.WRITE; 53 | } 54 | if (this.canRead(metadata, userDetails)) { 55 | return GistAccessRight.READ; 56 | } 57 | return GistAccessRight.NONE; 58 | } 59 | 60 | private boolean canRead(GistMetadata metadata, UserDetails userDetails) { 61 | return true; 62 | } 63 | 64 | private boolean canWrite(GistMetadata metadata, UserDetails userDetails) { 65 | return this.isOwner(metadata, userDetails); 66 | } 67 | 68 | private GistMetadata getMetaData(GistRepository repository) { 69 | return repository.getMetadata(); 70 | } 71 | 72 | private boolean isOwner(GistMetadata metadata, UserDetails userDetails) { 73 | return userDetails.getUsername().equals(metadata.getOwner()); 74 | } 75 | 76 | @Override 77 | public boolean canCreate(UserDetails userDetails) { 78 | return true; 79 | } 80 | 81 | @Override 82 | public boolean canCreateAs(UserDetails userDetails, String otherUser) { 83 | return false; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/InitRepositoryLayoutOperation.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.util.concurrent.Callable; 12 | 13 | import org.ajoberstar.grgit.exception.GrgitException; 14 | import org.ajoberstar.grgit.operation.InitOp; 15 | import org.apache.commons.io.FileUtils; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | import com.mangosolutions.rcloud.rawgist.repository.GistError; 20 | import com.mangosolutions.rcloud.rawgist.repository.GistErrorCode; 21 | import com.mangosolutions.rcloud.rawgist.repository.GistRepositoryError; 22 | 23 | public class InitRepositoryLayoutOperation implements Callable { 24 | 25 | private static final Logger logger = LoggerFactory.getLogger(InitRepositoryLayoutOperation.class); 26 | 27 | private File repositoryRoot; 28 | 29 | public InitRepositoryLayoutOperation(File repositoryRoot) { 30 | this.repositoryRoot = repositoryRoot; 31 | } 32 | 33 | public File getRepositoryRoot() { 34 | return repositoryRoot; 35 | } 36 | 37 | public void setRepositoryRoot(File repositoryRoot) { 38 | this.repositoryRoot = repositoryRoot; 39 | } 40 | 41 | @Override 42 | public RepositoryLayout call() { 43 | RepositoryLayout layout = new RepositoryLayout(repositoryRoot); 44 | //ensure the comments folder exists 45 | createRootFolder(layout); 46 | createCommentsFolder(layout); 47 | createGistFolder(layout); 48 | createWorkingFolder(layout); 49 | initGistRepo(layout); 50 | return layout; 51 | } 52 | 53 | private void initGistRepo(RepositoryLayout layout) { 54 | File bareFolder = layout.getBareFolder(); 55 | if(bareFolder.list().length == 0) { 56 | try { 57 | InitOp initOp = new InitOp(); 58 | initOp.setDir(bareFolder); 59 | initOp.setBare(true); 60 | initOp.call(); 61 | } catch (GrgitException e) { 62 | GistError error = new GistError(GistErrorCode.FATAL_GIST_INITIALISATION, "Could not create gist storage location for gist"); 63 | logger.error(error.getFormattedMessage() + " with folder path {}", bareFolder); 64 | throw new GistRepositoryError(error, e); 65 | } 66 | } 67 | } 68 | 69 | private void createCommentsFolder(RepositoryLayout layout) { 70 | mkdir(layout.getCommentsFolder()); 71 | } 72 | 73 | private void createGistFolder(RepositoryLayout layout) { 74 | mkdir(layout.getBareFolder()); 75 | } 76 | 77 | private void createWorkingFolder(RepositoryLayout layout) { 78 | mkdir(layout.getWorkingFolder()); 79 | } 80 | 81 | private void createRootFolder(RepositoryLayout layout) { 82 | mkdir(layout.getRootFolder()); 83 | } 84 | 85 | private void mkdir(File dir) { 86 | if (!dir.exists()) { 87 | try { 88 | FileUtils.forceMkdir(dir); 89 | } catch (IOException e) { 90 | GistError error = new GistError(GistErrorCode.FATAL_GIST_INITIALISATION, "Could not create gist storage location for gist"); 91 | logger.error(error.getFormattedMessage() + " with folder path {}", dir); 92 | throw new GistRepositoryError(error, e); 93 | } 94 | } 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/SessionKeyServerProperties.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | import org.springframework.boot.context.properties.ConfigurationProperties; 13 | import org.springframework.cloud.context.config.annotation.RefreshScope; 14 | 15 | import com.mangosolutions.rcloud.sessionkeyauth.KeyServerConfiguration; 16 | 17 | @ConfigurationProperties(prefix = "gists") 18 | @RefreshScope 19 | public class SessionKeyServerProperties { 20 | 21 | private static final String DEFAULT_ACCESS_TOKEN_NAME = "access_token"; 22 | 23 | private static final String DEFAULT_CLIENT_ID_NAME = "client_id"; 24 | 25 | private Map keyservers = new HashMap(); 26 | 27 | private String accessTokenParam = DEFAULT_ACCESS_TOKEN_NAME; 28 | private String clientIdParam = DEFAULT_CLIENT_ID_NAME; 29 | 30 | public String getAccessTokenParam() { 31 | return accessTokenParam; 32 | } 33 | 34 | public Map getKeyservers() { 35 | return keyservers; 36 | } 37 | 38 | public void setKeyservers(Map keyservers) { 39 | this.keyservers = keyservers; 40 | } 41 | 42 | public void setAccessTokenParam(String accessTokenParam) { 43 | this.accessTokenParam = accessTokenParam; 44 | } 45 | 46 | public String getClientIdParam() { 47 | return clientIdParam; 48 | } 49 | 50 | public void setClientIdParam(String clientIdParam) { 51 | this.clientIdParam = clientIdParam; 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | final int prime = 31; 57 | int result = 1; 58 | result = prime * result + ((accessTokenParam == null) ? 0 : accessTokenParam.hashCode()); 59 | result = prime * result + ((clientIdParam == null) ? 0 : clientIdParam.hashCode()); 60 | result = prime * result + ((keyservers == null) ? 0 : keyservers.hashCode()); 61 | return result; 62 | } 63 | 64 | @Override 65 | public boolean equals(Object obj) { 66 | if (this == obj) 67 | return true; 68 | if (obj == null) 69 | return false; 70 | if (getClass() != obj.getClass()) 71 | return false; 72 | SessionKeyServerProperties other = (SessionKeyServerProperties) obj; 73 | if (accessTokenParam == null) { 74 | if (other.accessTokenParam != null) 75 | return false; 76 | } else if (!accessTokenParam.equals(other.accessTokenParam)) 77 | return false; 78 | if (clientIdParam == null) { 79 | if (other.clientIdParam != null) 80 | return false; 81 | } else if (!clientIdParam.equals(other.clientIdParam)) 82 | return false; 83 | if (keyservers == null) { 84 | if (other.keyservers != null) 85 | return false; 86 | } else if (!keyservers.equals(other.keyservers)) 87 | return false; 88 | return true; 89 | } 90 | 91 | @Override 92 | public String toString() { 93 | return "SessionKeyServerProperties [keyservers=" + keyservers + ", accessTokenParam=" + accessTokenParam 94 | + ", clientIdParam=" + clientIdParam + "]"; 95 | } 96 | 97 | 98 | 99 | } 100 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/ContentNegotiationConfiguration.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Arrays; 11 | import java.util.Collection; 12 | import java.util.LinkedHashSet; 13 | import java.util.List; 14 | import java.util.Set; 15 | 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 18 | import org.springframework.context.annotation.Configuration; 19 | import org.springframework.http.MediaType; 20 | import org.springframework.http.converter.HttpMessageConverter; 21 | import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter; 22 | import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; 23 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 24 | 25 | @Configuration 26 | @EnableConfigurationProperties(GistServiceProperties.class) 27 | public class ContentNegotiationConfiguration extends WebMvcConfigurerAdapter { 28 | 29 | private static final List DEFAULT_GITHUB_MEDIA_TYPES = Arrays.asList( 30 | MediaType.parseMediaType("application/vnd.github.beta+json"), 31 | MediaType.parseMediaType("application/vnd.github.beta"), 32 | MediaType.parseMediaType("application/vnd.github.v3+json"), 33 | MediaType.parseMediaType("application/vnd.github.v3") 34 | ); 35 | 36 | @Autowired 37 | private GistServiceProperties serviceProperties; 38 | 39 | @Override 40 | public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { 41 | configurer.ignoreAcceptHeader(true); 42 | configurer.defaultContentType(MediaType.APPLICATION_JSON_UTF8); 43 | } 44 | 45 | @Override 46 | public void extendMessageConverters(List> converters) { 47 | super.extendMessageConverters(converters); 48 | for (HttpMessageConverter converter : converters) { 49 | if (isJsonConverter(converter)) { 50 | updateMediaTypes((AbstractJackson2HttpMessageConverter) converter); 51 | } 52 | } 53 | } 54 | 55 | private void updateMediaTypes(AbstractJackson2HttpMessageConverter converter) { 56 | Collection gistMediaTypes = getMediaTypes(converter); 57 | List mediaTypes = new ArrayList<>(gistMediaTypes); 58 | converter.setSupportedMediaTypes(mediaTypes); 59 | } 60 | 61 | private Collection getMediaTypes(AbstractJackson2HttpMessageConverter converter) { 62 | Set mediaTypes = new LinkedHashSet<>(converter.getSupportedMediaTypes()); 63 | for(String mediaType: serviceProperties.getMediatypes()) { 64 | mediaTypes.add(MediaType.parseMediaType(mediaType)); 65 | } 66 | mediaTypes.addAll(DEFAULT_GITHUB_MEDIA_TYPES); 67 | return mediaTypes; 68 | } 69 | 70 | private boolean isJsonConverter(HttpMessageConverter converter) { 71 | if(AbstractJackson2HttpMessageConverter.class.isAssignableFrom(converter.getClass())) { 72 | for (MediaType mediaType : converter.getSupportedMediaTypes()) { 73 | if (mediaType.equals(MediaType.APPLICATION_JSON)) { 74 | return true; 75 | } 76 | } 77 | } 78 | return false; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/model/Fork.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.model; 8 | 9 | import java.io.Serializable; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | import org.joda.time.DateTime; 14 | 15 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 16 | import com.fasterxml.jackson.annotation.JsonAnySetter; 17 | import com.fasterxml.jackson.annotation.JsonIgnore; 18 | import com.fasterxml.jackson.annotation.JsonInclude; 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 21 | 22 | @JsonInclude(JsonInclude.Include.NON_NULL) 23 | @JsonPropertyOrder({ "user", "url", "id", "created_at", "updated_at" }) 24 | public class Fork implements Serializable 25 | { 26 | 27 | /** 28 | * 29 | */ 30 | private static final long serialVersionUID = 1L; 31 | 32 | @JsonProperty("url") 33 | private String url; 34 | 35 | @JsonProperty("id") 36 | private String id; 37 | 38 | @JsonIgnore 39 | private Map additionalProperties = new HashMap(); 40 | 41 | @JsonProperty("url") 42 | public String getUrl() { 43 | return url; 44 | } 45 | 46 | @JsonProperty("url") 47 | public void setUrl(String url) { 48 | this.url = url; 49 | } 50 | 51 | @JsonProperty("id") 52 | public String getId() { 53 | return id; 54 | } 55 | 56 | @JsonProperty("id") 57 | public void setId(String id) { 58 | this.id = id; 59 | } 60 | 61 | @JsonAnyGetter 62 | public Map getAdditionalProperties() { 63 | return this.additionalProperties; 64 | } 65 | 66 | @JsonAnySetter 67 | public void setAdditionalProperty(String name, Object value) { 68 | this.additionalProperties.put(name, value); 69 | } 70 | 71 | @Override 72 | public int hashCode() { 73 | final int prime = 31; 74 | int result = 1; 75 | result = prime * result + ((additionalProperties == null) ? 0 : additionalProperties.hashCode()); 76 | result = prime * result + ((id == null) ? 0 : id.hashCode()); 77 | result = prime * result + ((url == null) ? 0 : url.hashCode()); 78 | return result; 79 | } 80 | 81 | @Override 82 | public boolean equals(Object obj) { 83 | if (this == obj) 84 | return true; 85 | if (obj == null) 86 | return false; 87 | if (getClass() != obj.getClass()) 88 | return false; 89 | Fork other = (Fork) obj; 90 | if (additionalProperties == null) { 91 | if (other.additionalProperties != null) 92 | return false; 93 | } else if (!additionalProperties.equals(other.additionalProperties)) 94 | return false; 95 | if (id == null) { 96 | if (other.id != null) 97 | return false; 98 | } else if (!id.equals(other.id)) 99 | return false; 100 | if (url == null) { 101 | if (other.url != null) 102 | return false; 103 | } else if (!url.equals(other.url)) 104 | return false; 105 | return true; 106 | } 107 | 108 | @Override 109 | public String toString() { 110 | return "Fork [url=" + url + ", id=" + id + ", additionalProperties=" + additionalProperties + "]"; 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /rcloud-sessionkey-lib/src/main/java/com/mangosolutions/rcloud/sessionkeyauth/KeyServerConfiguration.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.sessionkeyauth; 8 | 9 | public class KeyServerConfiguration { 10 | 11 | private static final String DEFAULT_REALM_VALUE = "rcloud"; 12 | 13 | private static final String DEFAULT_URL_VALUE = "http://{host}:{port}/valid?token={token}&realm={realm}"; 14 | 15 | private static final String DEFAULT_HOST_VALUE = "127.0.0.1"; 16 | 17 | private static final Integer DEFAULT_PORT_VALUE = 4301; 18 | 19 | private String host = DEFAULT_HOST_VALUE; 20 | private Integer port = DEFAULT_PORT_VALUE; 21 | private String realm = DEFAULT_REALM_VALUE; 22 | private String url = DEFAULT_URL_VALUE; 23 | private boolean active = true; 24 | 25 | 26 | public String getHost() { 27 | return host; 28 | } 29 | 30 | public void setHost(String host) { 31 | this.host = host; 32 | } 33 | 34 | public Integer getPort() { 35 | return port; 36 | } 37 | 38 | public void setPort(Integer port) { 39 | this.port = port; 40 | } 41 | 42 | public String getRealm() { 43 | return realm; 44 | } 45 | 46 | public void setRealm(String realm) { 47 | this.realm = realm; 48 | } 49 | 50 | public String getUrl() { 51 | return url; 52 | } 53 | 54 | public void setUrl(String url) { 55 | this.url = url; 56 | } 57 | 58 | 59 | public boolean isActive() { 60 | return active; 61 | } 62 | 63 | public void setActive(boolean active) { 64 | this.active = active; 65 | } 66 | 67 | @Override 68 | public int hashCode() { 69 | final int prime = 31; 70 | int result = 1; 71 | result = prime * result + (active ? 1231 : 1237); 72 | result = prime * result + ((host == null) ? 0 : host.hashCode()); 73 | result = prime * result + ((port == null) ? 0 : port.hashCode()); 74 | result = prime * result + ((realm == null) ? 0 : realm.hashCode()); 75 | result = prime * result + ((url == null) ? 0 : url.hashCode()); 76 | return result; 77 | } 78 | 79 | @Override 80 | public boolean equals(Object obj) { 81 | if (this == obj) 82 | return true; 83 | if (obj == null) 84 | return false; 85 | if (getClass() != obj.getClass()) 86 | return false; 87 | KeyServerConfiguration other = (KeyServerConfiguration) obj; 88 | if (active != other.active) 89 | return false; 90 | if (host == null) { 91 | if (other.host != null) 92 | return false; 93 | } else if (!host.equals(other.host)) 94 | return false; 95 | if (port == null) { 96 | if (other.port != null) 97 | return false; 98 | } else if (!port.equals(other.port)) 99 | return false; 100 | if (realm == null) { 101 | if (other.realm != null) 102 | return false; 103 | } else if (!realm.equals(other.realm)) 104 | return false; 105 | if (url == null) { 106 | if (other.url != null) 107 | return false; 108 | } else if (!url.equals(other.url)) 109 | return false; 110 | return true; 111 | } 112 | 113 | @Override 114 | public String toString() { 115 | return "KeyServerConfiguration [host=" + host + ", port=" + port + ", realm=" + realm + ", url=" + url 116 | + ", active=" + active + "]"; 117 | } 118 | 119 | 120 | } -------------------------------------------------------------------------------- /rcloud-gist-service/src/test/java/com/mangosolutions/rcloud/rawgist/api/UserRestControllerTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.api; 8 | 9 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 10 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 11 | 12 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; 13 | import static org.hamcrest.CoreMatchers.is; 14 | 15 | 16 | import org.junit.Before; 17 | import org.junit.Test; 18 | import org.junit.runner.RunWith; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.boot.test.context.SpringBootTest; 21 | import org.springframework.http.MediaType; 22 | import org.springframework.security.test.context.support.WithMockUser; 23 | import org.springframework.test.annotation.DirtiesContext; 24 | import org.springframework.test.annotation.DirtiesContext.ClassMode; 25 | import org.springframework.test.context.ActiveProfiles; 26 | import org.springframework.test.context.junit4.SpringRunner; 27 | import org.springframework.test.context.web.WebAppConfiguration; 28 | import org.springframework.test.web.servlet.MockMvc; 29 | import org.springframework.test.web.servlet.ResultActions; 30 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; 31 | import org.springframework.web.context.WebApplicationContext; 32 | 33 | import com.mangosolutions.rcloud.rawgist.Application; 34 | 35 | @RunWith(SpringRunner.class) 36 | @SpringBootTest(classes = Application.class) 37 | @DirtiesContext(classMode = ClassMode.AFTER_CLASS) 38 | @WebAppConfiguration 39 | @ActiveProfiles({"test", "default"}) 40 | public class UserRestControllerTest { 41 | 42 | public static MediaType GITHUB_BETA_MEDIA_TYPE = MediaType.parseMediaType("application/vnd.github.beta+json"); 43 | public static MediaType GITHUB_V3_MEDIA_TYPE = MediaType.parseMediaType("application/vnd.github.v3+json"); 44 | 45 | private MockMvc mvc; 46 | 47 | @Autowired 48 | private WebApplicationContext webApplicationContext; 49 | 50 | @Before 51 | public void setup() throws Exception { 52 | this.mvc = MockMvcBuilders.webAppContextSetup(this.webApplicationContext).build(); 53 | } 54 | 55 | @Test 56 | @WithMockUser("mock_user") 57 | public void testGetUserWithApplicationJsonMediaType() throws Exception { 58 | ResultActions resultActions = mvc.perform(get("/user") 59 | .accept(MediaType.APPLICATION_JSON_UTF8)) 60 | .andExpect(status().isOk()) 61 | .andExpect(jsonPath("$.login", is("mock_user"))); 62 | } 63 | 64 | @Test 65 | @WithMockUser("mock_user") 66 | public void testGetUserWithGithubBetaMediaType() throws Exception { 67 | ResultActions resultActions = mvc.perform(get("/user") 68 | .accept(GITHUB_BETA_MEDIA_TYPE)) 69 | .andExpect(status().isOk()) 70 | .andExpect(jsonPath("$.login", is("mock_user"))); 71 | } 72 | 73 | @Test 74 | @WithMockUser("mock_user") 75 | public void testGetUserWithGithubV3MediaType() throws Exception { 76 | ResultActions resultActions = mvc.perform(get("/user") 77 | .accept(GITHUB_V3_MEDIA_TYPE)) 78 | .andExpect(status().isOk()) 79 | .andExpect(jsonPath("$.login", is("mock_user"))); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/test/java/com/mangosolutions/rcloud/rawgist/api/GistTestHelper.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.api; 8 | 9 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; 10 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; 11 | 12 | import java.io.File; 13 | import java.io.IOException; 14 | import java.util.Arrays; 15 | import java.util.Collection; 16 | import java.util.Collections; 17 | import java.util.HashMap; 18 | import java.util.Map; 19 | import java.util.Map.Entry; 20 | 21 | import org.apache.commons.io.FileUtils; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.http.MediaType; 24 | import org.springframework.security.core.GrantedAuthority; 25 | import org.springframework.security.core.userdetails.User; 26 | import org.springframework.security.core.userdetails.UserDetails; 27 | import org.springframework.stereotype.Component; 28 | import org.springframework.test.web.servlet.MockMvc; 29 | import org.springframework.test.web.servlet.MvcResult; 30 | 31 | import com.hazelcast.config.Config; 32 | import com.hazelcast.config.MapConfig; 33 | import com.hazelcast.core.HazelcastInstance; 34 | import com.hazelcast.core.IMap; 35 | import com.mangosolutions.rcloud.rawgist.model.FileDefinition; 36 | import com.mangosolutions.rcloud.rawgist.model.GistRequest; 37 | import com.mangosolutions.rcloud.rawgist.model.GistResponse; 38 | import com.mangosolutions.rcloud.rawgist.repository.GistRepositoryService; 39 | import com.mangosolutions.rcloud.sessionkeyauth.UserAuthorityResolver; 40 | 41 | @Component 42 | public class GistTestHelper { 43 | 44 | @Autowired 45 | private HazelcastInstance hazelcastInstance; 46 | 47 | @Autowired 48 | private GistRepositoryService service; 49 | 50 | public void emptyHazelcast() { 51 | Config config = hazelcastInstance.getConfig(); 52 | Map mapConfigs = config.getMapConfigs(); 53 | for(Entry entry: mapConfigs.entrySet()) { 54 | IMap map = hazelcastInstance.getMap(entry.getKey()); 55 | map.evictAll(); 56 | } 57 | } 58 | 59 | public void clearGistRepository() throws IOException { 60 | String tmpdir = System.getProperty("java.io.tmpdir"); 61 | File gistFolder = new File(tmpdir + "/gists"); 62 | FileUtils.forceDelete(gistFolder); 63 | FileUtils.forceMkdir(gistFolder); 64 | FileUtils.forceMkdir(new File(gistFolder, ".recycle")); 65 | } 66 | 67 | public String createGist(String user, String description, String fileName, String fileContent) throws Exception { 68 | GistRequest request = new GistRequest(); 69 | request.setDescription(description); 70 | request.setPublic(false); 71 | 72 | Map files = new HashMap<>(); 73 | FileDefinition def = new FileDefinition(); 74 | def.setContent(fileContent); 75 | files.put(fileName, def); 76 | request.setFiles(files); 77 | Collection authorities = Arrays.asList(UserAuthorityResolver.USER_AUTHORITY); 78 | UserDetails userDetails = new User(user, "gist_user_pwd", authorities); 79 | GistResponse response = this.service.createGist(request, userDetails); 80 | return response.getId(); 81 | } 82 | 83 | public void warmupWebService(MockMvc mvc, String gistId) throws Exception { 84 | for(int i = 0; i < 10; i++) { 85 | MvcResult result = mvc 86 | .perform( 87 | get("/gists/" + gistId) 88 | .accept(MediaType.APPLICATION_JSON_UTF8) 89 | .contentType(MediaType.APPLICATION_JSON_UTF8) 90 | ) 91 | .andExpect(status().isOk()) 92 | .andReturn(); 93 | } 94 | 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/model/GistHistory.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.model; 8 | 9 | import java.io.Serializable; 10 | 11 | import org.joda.time.DateTime; 12 | 13 | import com.fasterxml.jackson.annotation.JsonInclude; 14 | import com.fasterxml.jackson.annotation.JsonProperty; 15 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 16 | 17 | @JsonInclude(JsonInclude.Include.ALWAYS) 18 | @JsonPropertyOrder({ "url", "version", "user", "change_status", "committed_at" }) 19 | public class GistHistory implements Serializable { 20 | 21 | private static final long serialVersionUID = 7346102204021167017L; 22 | 23 | private String url; 24 | private String version; 25 | private GistIdentity user; 26 | private GitChangeStatus changeStatus; 27 | 28 | @JsonProperty("committed_at") 29 | private DateTime committedAt; 30 | 31 | public String getUrl() { 32 | return url; 33 | } 34 | 35 | public void setUrl(String url) { 36 | this.url = url; 37 | } 38 | 39 | public String getVersion() { 40 | return version; 41 | } 42 | 43 | public void setVersion(String version) { 44 | this.version = version; 45 | } 46 | 47 | public GistIdentity getUser() { 48 | return user; 49 | } 50 | 51 | public void setUser(GistIdentity user) { 52 | this.user = user; 53 | } 54 | 55 | public GitChangeStatus getChangeStatus() { 56 | return changeStatus; 57 | } 58 | 59 | public void setChangeStatus(GitChangeStatus changeStatus) { 60 | this.changeStatus = changeStatus; 61 | } 62 | 63 | @JsonProperty("committed_at") 64 | public DateTime getCommittedAt() { 65 | return committedAt; 66 | } 67 | 68 | @JsonProperty("committed_at") 69 | public void setCommittedAt(DateTime committedAt) { 70 | this.committedAt = committedAt; 71 | } 72 | 73 | @Override 74 | public int hashCode() { 75 | final int prime = 31; 76 | int result = 1; 77 | result = prime * result + ((changeStatus == null) ? 0 : changeStatus.hashCode()); 78 | result = prime * result + ((committedAt == null) ? 0 : committedAt.hashCode()); 79 | result = prime * result + ((url == null) ? 0 : url.hashCode()); 80 | result = prime * result + ((user == null) ? 0 : user.hashCode()); 81 | result = prime * result + ((version == null) ? 0 : version.hashCode()); 82 | return result; 83 | } 84 | 85 | @Override 86 | public boolean equals(Object obj) { 87 | if (this == obj) 88 | return true; 89 | if (obj == null) 90 | return false; 91 | if (getClass() != obj.getClass()) 92 | return false; 93 | GistHistory other = (GistHistory) obj; 94 | if (changeStatus == null) { 95 | if (other.changeStatus != null) 96 | return false; 97 | } else if (!changeStatus.equals(other.changeStatus)) 98 | return false; 99 | if (committedAt == null) { 100 | if (other.committedAt != null) 101 | return false; 102 | } else if (!committedAt.equals(other.committedAt)) 103 | return false; 104 | if (url == null) { 105 | if (other.url != null) 106 | return false; 107 | } else if (!url.equals(other.url)) 108 | return false; 109 | if (user == null) { 110 | if (other.user != null) 111 | return false; 112 | } else if (!user.equals(other.user)) 113 | return false; 114 | if (version == null) { 115 | if (other.version != null) 116 | return false; 117 | } else if (!version.equals(other.version)) 118 | return false; 119 | return true; 120 | } 121 | 122 | @Override 123 | public String toString() { 124 | return "GistHistory [url=" + url + ", version=" + version + ", user=" + user + ", changeStatus=" + changeStatus 125 | + ", committedAt=" + committedAt + "]"; 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/ManagementSecurityConfiguration.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist; 8 | 9 | import java.lang.reflect.Field; 10 | import java.util.LinkedHashSet; 11 | import java.util.Set; 12 | 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | import org.springframework.beans.factory.annotation.Autowired; 16 | import org.springframework.boot.actuate.autoconfigure.ManagementServerProperties; 17 | import org.springframework.boot.autoconfigure.security.SecurityProperties; 18 | import org.springframework.boot.autoconfigure.security.SecurityProperties.User; 19 | import org.springframework.context.annotation.Configuration; 20 | import org.springframework.core.annotation.Order; 21 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 22 | import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer; 23 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 24 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 25 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 26 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 27 | import org.springframework.util.ReflectionUtils; 28 | 29 | @Configuration 30 | @EnableWebSecurity 31 | @EnableGlobalMethodSecurity(prePostEnabled = true) 32 | @Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER) 33 | public class ManagementSecurityConfiguration extends WebSecurityConfigurerAdapter { 34 | 35 | @Autowired 36 | private ManagementServerProperties managementProperties; 37 | 38 | @Autowired 39 | private SecurityProperties securityProperties; 40 | 41 | @Override 42 | protected void configure(HttpSecurity http) throws Exception { 43 | http 44 | .antMatcher("/" + managementProperties.getContextPath() + "/**") 45 | .csrf() 46 | .disable() 47 | .authorizeRequests() 48 | .anyRequest() 49 | .hasRole("ADMIN") 50 | .and().httpBasic(); 51 | } 52 | 53 | @Autowired 54 | public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 55 | auth.apply(new DefaultInMemoryUserDetailsManagerConfigurer( 56 | this.securityProperties)); 57 | } 58 | 59 | private static class DefaultInMemoryUserDetailsManagerConfigurer 60 | extends InMemoryUserDetailsManagerConfigurer { 61 | 62 | private final SecurityProperties securityProperties; 63 | 64 | private static final Logger logger = LoggerFactory.getLogger(DefaultInMemoryUserDetailsManagerConfigurer.class); 65 | 66 | DefaultInMemoryUserDetailsManagerConfigurer(SecurityProperties securityProperties) { 67 | this.securityProperties = securityProperties; 68 | } 69 | 70 | @Override 71 | public void configure(AuthenticationManagerBuilder auth) throws Exception { 72 | User user = this.securityProperties.getUser(); 73 | if (user.isDefaultPassword()) { 74 | logger.info("\n\nUsing default security password: " + user.getPassword() + "\n"); 75 | } 76 | Set roles = new LinkedHashSet(user.getRole()); 77 | withUser(user.getName()).password(user.getPassword()).roles(roles.toArray(new String[roles.size()])); 78 | setField(auth, "defaultUserDetailsService", getUserDetailsService()); 79 | super.configure(auth); 80 | } 81 | 82 | private void setField(Object target, String name, Object value) { 83 | try { 84 | Field field = ReflectionUtils.findField(target.getClass(), name); 85 | ReflectionUtils.makeAccessible(field); 86 | ReflectionUtils.setField(field, target, value); 87 | } catch (Exception ex) { 88 | logger.info("Could not set " + name); 89 | } 90 | } 91 | 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /rcloud-gist-service/build.gradle: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | 8 | project.description = "RCloud Gist service implementation on a git repository." 9 | 10 | dependencies { 11 | compile 'org.springframework.boot:spring-boot-starter' 12 | compile 'org.springframework.boot:spring-boot-starter-actuator' 13 | compile 'org.springframework.boot:spring-boot-starter-security' 14 | compile 'org.springframework.boot:spring-boot-starter-web' 15 | compile 'org.springframework.boot:spring-boot-starter-cache' 16 | compile 'org.springframework.cloud:spring-cloud-starter' 17 | compile 'org.springframework.hateoas:spring-hateoas' 18 | compile 'commons-io:commons-io' 19 | compile 'org.codehaus.groovy:groovy-all' 20 | compile 'com.hazelcast:hazelcast' 21 | compile 'com.hazelcast:hazelcast-spring' 22 | 23 | compile 'joda-time:joda-time' 24 | compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda' 25 | compile 'org.apache.commons:commons-collections4:4.1' 26 | compile 'org.ajoberstar:grgit:1.7.2' 27 | compile 'org.eclipse.jgit:org.eclipse.jgit:4.3.1.201605051710-r' 28 | compile 'com.google.guava:guava:20.0' 29 | compile project(':rcloud-sessionkey-lib') 30 | 31 | testCompile 'junit:junit' 32 | // testCompile 'org.mockito:mockito-all:1.10.8' 33 | testCompile 'org.springframework.boot:spring-boot-starter-test' 34 | testCompile 'org.springframework.security:spring-security-test' 35 | testCompile 'org.apache.commons:commons-math3:3.6.1' 36 | 37 | 38 | } 39 | 40 | 41 | ext.pkg = [:] 42 | pkg.name = archivesBaseName 43 | pkg.installPath = '/opt/' + pkg.name 44 | pkg.jarName = archivesBaseName + '-' + project.version + '.jar' 45 | pkg.jarPath = pkg.installPath + '/' + pkg.jarName 46 | pkg.initPath = '/etc/init.d/' + archivesBaseName 47 | pkg.description = project.description 48 | pkg.summary = "RCloud Raw Gist Service" 49 | pkg.vendor = "Mango Solutions Ltd." 50 | pkg.url = projectUrl 51 | pkg.buildId = new Date().format('yyyyMMddHHmmss') 52 | pkg.version = project.version.replaceAll("-", ".") 53 | pkg.user = 'rcloudgistservice' 54 | pkg.group = pkg.user 55 | 56 | ospackage { 57 | packageName = pkg.name 58 | version = pkg.version 59 | release = pkg.buildId 60 | os = LINUX 61 | user = pkg.user 62 | group = pkg.group 63 | summary = pkg.summary 64 | vendor = pkg.vendor 65 | packageDescription = pkg.description 66 | url = pkg.url 67 | type = BINARY 68 | 69 | //create user and group 70 | preInstall "/usr/sbin/useradd -c \"$pkg.summary\" -r -d $pkg.installPath $pkg.user 2>/dev/null || :" 71 | 72 | //create log directory 73 | preInstall "mkdir -p /var/log/$pkg.name && chown $pkg.user:root /var/log/$pkg.name" 74 | preInstall "mkdir -p /var/$pkg.name && chown $pkg.user:root /var/$pkg.name" 75 | 76 | 77 | 78 | into(pkg.installPath) 79 | 80 | from(jar.outputs.files) { 81 | fileMode 0770 82 | } 83 | 84 | from('src/main/pkg/home') { 85 | fileType CONFIG | NOREPLACE 86 | filter (org.apache.tools.ant.filters.ReplaceTokens, tokens: pkg ) 87 | rename { String fileName -> 88 | if(fileName.equals("service.conf")) { 89 | fileName.replace('service', pkg.name + "-" + project.version) 90 | } else if(fileName.equals("systemd.service")) { 91 | fileName.replace('systemd', pkg.name) 92 | } else { 93 | fileName 94 | } 95 | } 96 | fileMode 0660 97 | } 98 | //systemv symlink 99 | link(pkg.initPath, pkg.jarPath) 100 | //The following link is for systemd based systems, at the moment the above systemv symlink will suffice 101 | //link("/etc/systemd/system/" + pkg.name + ".service", pkg.installPath + "/" + pkg.name + ".service") 102 | } 103 | 104 | assemble.dependsOn distRpm 105 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/GistMetadata.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import java.io.Serializable; 10 | import java.util.ArrayList; 11 | import java.util.HashMap; 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | import org.joda.time.DateTime; 16 | 17 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 18 | import com.fasterxml.jackson.annotation.JsonAnySetter; 19 | import com.fasterxml.jackson.annotation.JsonInclude; 20 | import com.fasterxml.jackson.annotation.JsonProperty; 21 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 22 | import com.mangosolutions.rcloud.rawgist.model.Fork; 23 | 24 | @JsonInclude(JsonInclude.Include.NON_NULL) 25 | @JsonPropertyOrder({ "id", "owner", "description", "public", "created_at", "updated_at", "fork_of", "forks"}) 26 | public class GistMetadata implements Serializable { 27 | 28 | private final static long serialVersionUID = -7352290872081419828L; 29 | 30 | @JsonProperty("id") 31 | private String id; 32 | 33 | @JsonProperty("owner") 34 | private String owner; 35 | 36 | @JsonProperty("description") 37 | private String description; 38 | 39 | @JsonProperty("public") 40 | private boolean _public = true; 41 | 42 | @JsonProperty("created_at") 43 | private DateTime createdAt; 44 | 45 | @JsonProperty("updated_at") 46 | private DateTime updatedAt; 47 | 48 | @JsonProperty("fork_of") 49 | private Fork forkOf = null; 50 | 51 | @JsonProperty("forks") 52 | private List forks = new ArrayList<>(); 53 | 54 | private Map additionalProperties = new HashMap(); 55 | 56 | public String getId() { 57 | return id; 58 | } 59 | 60 | public void setId(String id) { 61 | this.id = id; 62 | } 63 | 64 | public String getOwner() { 65 | return owner; 66 | } 67 | 68 | public void setOwner(String owner) { 69 | this.owner = owner; 70 | } 71 | 72 | 73 | @JsonProperty("description") 74 | public String getDescription() { 75 | return description; 76 | } 77 | 78 | @JsonProperty("description") 79 | public void setDescription(String description) { 80 | this.description = description; 81 | } 82 | 83 | @JsonProperty("public") 84 | public boolean isPublic() { 85 | return _public; 86 | } 87 | 88 | @JsonProperty("public") 89 | public void setPublic(boolean _public) { 90 | this._public = _public; 91 | } 92 | 93 | @JsonProperty("created_at") 94 | public DateTime getCreatedAt() { 95 | return createdAt; 96 | } 97 | 98 | @JsonProperty("created_at") 99 | public void setCreatedAt(DateTime createdAt) { 100 | this.createdAt = createdAt; 101 | } 102 | 103 | @JsonProperty("updated_at") 104 | public DateTime getUpdatedAt() { 105 | return updatedAt; 106 | } 107 | 108 | @JsonProperty("updated_at") 109 | public void setUpdatedAt(DateTime updatedAt) { 110 | this.updatedAt = updatedAt; 111 | } 112 | 113 | @JsonProperty("forks") 114 | public List getForks() { 115 | return forks; 116 | } 117 | 118 | @JsonProperty("forks") 119 | public void setForks(List forks) { 120 | this.forks = forks; 121 | } 122 | 123 | @JsonAnyGetter 124 | public Map getAdditionalProperties() { 125 | return this.additionalProperties; 126 | } 127 | 128 | @JsonAnySetter 129 | public void setAdditionalProperty(String name, Object value) { 130 | this.additionalProperties.put(name, value); 131 | } 132 | 133 | public void addOrUpdateFork(Fork fork) { 134 | 135 | for(int i = 0; i < this.forks.size(); i++) { 136 | Fork existingFork = this.forks.get(i); 137 | if(existingFork.getId().equals(fork.getId())) { 138 | this.forks.set(i, fork); 139 | return; 140 | } 141 | } 142 | this.forks.add(fork); 143 | } 144 | 145 | @JsonProperty("fork_of") 146 | public void setForkOf(Fork fork) { 147 | this.forkOf = fork; 148 | } 149 | 150 | @JsonProperty("fork_of") 151 | public Fork getForkOf() { 152 | return this.forkOf; 153 | } 154 | 155 | } 156 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/test/java/com/mangosolutions/rcloud/gists/filters/JsonContentUrlRewritingFilterTest.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.gists.filters; 8 | 9 | import java.net.MalformedURLException; 10 | import java.net.URL; 11 | 12 | import org.junit.Assert; 13 | import org.junit.Before; 14 | import org.junit.Test; 15 | import org.springframework.http.MediaType; 16 | 17 | import com.netflix.zuul.context.RequestContext; 18 | 19 | public class JsonContentUrlRewritingFilterTest { 20 | 21 | private static final String REMOTE_URL = "https://api.github.com"; 22 | private static final String LOCAL_URL = "http://localhost:8080"; 23 | 24 | @Before 25 | public void setup() throws MalformedURLException { 26 | setup(MediaType.APPLICATION_JSON_UTF8_VALUE); 27 | } 28 | 29 | public void setup(String contentType) throws MalformedURLException { 30 | RequestContext context = RequestContext.getCurrentContext(); 31 | context.getZuulResponseHeaders().clear(); 32 | context.addZuulRequestHeader("x-forwarded-host", "localhost:8080"); 33 | context.addZuulRequestHeader("x-forwarded-proto", "http"); 34 | context.addZuulRequestHeader("x-forwarded-port", "8080"); 35 | context.addZuulResponseHeader("Content-Type", contentType); 36 | context.setRouteHost(new URL("https://api.github.com")); 37 | } 38 | 39 | public void setContent(String content) { 40 | RequestContext.getCurrentContext().setResponseBody(content); 41 | } 42 | 43 | @Test 44 | public void testShouldFilterJsonContent() { 45 | Assert.assertTrue(new JsonContentUrlRewritingFilter(1).shouldFilter()); 46 | } 47 | 48 | @Test 49 | public void testShouldNotFilterXmlContent() throws MalformedURLException { 50 | setup(MediaType.APPLICATION_XML_VALUE); 51 | Assert.assertFalse(new JsonContentUrlRewritingFilter(1).shouldFilter()); 52 | } 53 | 54 | @Test 55 | public void testShouldFilterJsonExtensionContent() throws MalformedURLException { 56 | setup("application/hal+json"); 57 | Assert.assertTrue(new JsonContentUrlRewritingFilter(1).shouldFilter()); 58 | } 59 | 60 | @Test 61 | public void replaceUrlInJsonArray() throws MalformedURLException { 62 | String jsonArray = "[ \"https://api.github.com\" ]"; 63 | setContent(jsonArray); 64 | JsonContentUrlRewritingFilter filter = new JsonContentUrlRewritingFilter(1); 65 | filter.run(); 66 | String responseBody = RequestContext.getCurrentContext().getResponseBody(); 67 | Assert.assertFalse(responseBody.contains(REMOTE_URL)); 68 | Assert.assertTrue(responseBody.contains(LOCAL_URL)); 69 | } 70 | 71 | @Test 72 | public void replaceUrlInJsonObject() { 73 | String jsonArray = "{ \"url\": \"https://api.github.com\" }"; 74 | setContent(jsonArray); 75 | JsonContentUrlRewritingFilter filter = new JsonContentUrlRewritingFilter(1); 76 | filter.run(); 77 | String responseBody = RequestContext.getCurrentContext().getResponseBody(); 78 | Assert.assertFalse(responseBody.contains(REMOTE_URL)); 79 | Assert.assertTrue(responseBody.contains(LOCAL_URL)); 80 | } 81 | 82 | @Test 83 | public void replaceUrlInNestedJsonObject() { 84 | String jsonArray = "{ \"obj\": { \"url\": \"https://api.github.com\" } }"; 85 | setContent(jsonArray); 86 | JsonContentUrlRewritingFilter filter = new JsonContentUrlRewritingFilter(1); 87 | filter.run(); 88 | String responseBody = RequestContext.getCurrentContext().getResponseBody(); 89 | Assert.assertFalse(responseBody.contains(REMOTE_URL)); 90 | Assert.assertTrue(responseBody.contains(LOCAL_URL)); 91 | } 92 | 93 | @Test 94 | public void replaceUrlInSpecificJsonObject() { 95 | String jsonArray = "{ \"obj\": { \"url\": \"https://api.github.com\", \"noUrl\": \"I am not a url\" } }"; 96 | setContent(jsonArray); 97 | JsonContentUrlRewritingFilter filter = new JsonContentUrlRewritingFilter(1); 98 | filter.run(); 99 | String responseBody = RequestContext.getCurrentContext().getResponseBody(); 100 | Assert.assertFalse(responseBody.contains(REMOTE_URL)); 101 | Assert.assertTrue(responseBody.contains(LOCAL_URL)); 102 | Assert.assertTrue(responseBody.contains("I am not a url")); 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/README.md: -------------------------------------------------------------------------------- 1 | # RCloud Gist Proxy Service 2 | A Java based service to proxy and route requests between RCloud and the gist 3 | backend. By default this is setup to route requests to `/gists` to the 4 | rcloud-gist-service and all others to GitHub. 5 | 6 | ## Building 7 | The code uses the Gradle build system and includes the gradle wrapper in the root 8 | of the project. The only requirement for building is a Java JDK version 7 or greater 9 | and an internet connection, all dependencies will be downloaded for the build. 10 | 11 | To build the software run the following command which runs the tests and generates 12 | the artifacts. 13 | 14 | `./gradlew build` 15 | 16 | ### Outputs 17 | The build generates 3 artifacts 18 | 1. An executable jar file created here: `./rcloud-gistproxy-service/build/libs` 19 | 2. An rpm install file created here: `./rcloud-gistproxy-service/build/distributions` 20 | 3. An deb install file created here: `./rcloud-gistproxy-service/build/distributions` 21 | 22 | ## Installation 23 | 24 | The redhat and debian install archives will install the application to 25 | `/opt/rcloud-gistproxy-service` and create an entry in the `/etc/init.d/` folder 26 | which can be used to start and stop the service. 27 | 28 | ### User and Groups 29 | The installation creates a user and group for the service called `rcloudgistservice` which the service runs as. 30 | 31 | ### Debian based systems 32 | To install the service on debian based systems the following command can be used, you will need to use the correct name for the deb file for the version you are installing. 33 | 34 | `sudo dpkg -i ./rcloud-gistproxy-service_0.1.0-20170126123855_all.deb` 35 | 36 | ## Default ports 37 | The service uses two ports, one for the gist api and the other for the service management functionality, these can be controlled in configuration. The management port is secured using basic auth. 38 | 39 | ## Service Configuration 40 | 41 | Configuration is held within the `/opt/rcloud-gistproxy-service/application.yml` file. 42 | The following parameters are configurable: 43 | 44 | | Property | Description | Default | 45 | |----------|-------------|---------| 46 | | `github.api.url` | The URL to the root of the GitHub installation that this should use | `https://api.github.com` | 47 | | `service.port` | The port that the gist api is accessible over | `13010` | 48 | | `management.port` | The port that the service management api is accessible over | `13011` | 49 | | `security.user.name` | The username that is required for basic auth access to the management port | `admin` | 50 | | `security.user.password` | The username that is required for basic auth access to the management port | If not specified the password is generated at service startup and can be identified in the `/var/log/rcloud-gistproxy-service/rcloud-gistproxy-service-file.log` file. The following command can be used to find the password. `cat /var/log/rcloud-gistproxy-service/rcloud-gistproxy-service-file.log | grep "Using default security"`. More information can be found on the [spring boot documentation.](http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-monitoring.html) | 51 | 52 | ### JVM Configuration 53 | The startup parameters for the JVM are stored in the conf file in the installation directory, this must have the same name as the jar file. 54 | 55 | 56 | ## RCloud Configuration 57 | To configure RCloud edit the `rcloud.conf` and change the `api.github.url` value to the URL of this service if running with the defaults then this would be `http://localhost:13010` e.g. : 58 | 59 | `github.api.url: http://localhost:13010` 60 | 61 | ## Starting and stopping the service 62 | 63 | An System V startup script is installed as part of the installation, thissupports the following commands: 64 | 65 | | Command | Example | 66 | |---------|-------------------------------------------| 67 | | start | `service rcloud-gistproxy-service start` | 68 | | stop | `service rcloud-gistproxy-service stop` | 69 | | status | `service rcloud-gistproxy-service status` | 70 | 71 | ## Logging 72 | The service uses [Logback](https://logback.qos.ch/), this is controlled by the 73 | configuration file in the installation directory `/opt/rcloud-gistproxy-service/logback.xml`, this configuration file can be updated and the changes will be reloaded to alter the log output. The service writes log files to `/var/log/rcloud-gistproxy-service/` access to this folder is restricted to `root` group and the `rcloudgistservice` user/group. 74 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/pkg/home/application.yml: -------------------------------------------------------------------------------- 1 | #******************************************************************************* 2 | # Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | # 4 | # SPDX-License-Identifier: MIT 5 | # 6 | #******************************************************************************* 7 | 8 | ################################################################################ 9 | # Application port. Change the value below to change the port this service 10 | # is listening on. 11 | ################################################################################ 12 | #server: 13 | # port: 13020 14 | 15 | ################################################################################ 16 | # Management port. Change the value below to change the port the management 17 | # services are listening on. This is protected by BASIC authentication details 18 | # in the security section below. 19 | ################################################################################ 20 | #management: 21 | # port: 13021 22 | 23 | ################################################################################ 24 | # Security information settings administrative access to endpoints. 25 | # Default user is 'admin' default password is generated on startup and printed 26 | # out in the log file. To override these settings uncomment the lines below 27 | # and specify your own password. 28 | # 29 | # The administrative endpoints are documented: 30 | # https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html 31 | ################################################################################ 32 | #security: 33 | # user: 34 | # name: admin 35 | # role: ADMIN 36 | # password: secret 37 | 38 | ################################################################################ 39 | # Gist Repository configuration: 40 | # root: 41 | # Folder location for storing the gists. This needs to be writable by the 42 | # rcloudgistservice user/group. 43 | # lockTimeout: 44 | # Timeout to acquire read/write locks on a gist to prevent concurrent 45 | # modification. This value is in seconds. 46 | # keyservers: 47 | # The configuration block for the Session Key Servers. The immediate child 48 | # of this is the client_id name for the key server as is received in the 49 | # request from rcloud. A value of 'default' indicates that this is to 50 | # be used if no matching client_id is specified for a key service 51 | # configuration. 52 | # keyservers.active: 53 | # Whether this configuration for the keyserver is active, default is true. 54 | # keyservers.host: 55 | # The host machine running the Session Key Server 56 | # keyservers.port: 57 | # The port of the Session Key Server 58 | # keyservers.url: 59 | # The URL template for the session key server. 60 | # route.redirect: 61 | # A static route that when hit will return a redirect to the client 62 | # route.redirect.from: 63 | # The relative URL that this service uses to issue the redirect from. 64 | # route.redirect.to: 65 | # The URL to redirect to 66 | # route.redirect.copyparams: 67 | # Whether to copy the parameters from the request into the redirection URL. 68 | # defaults to 'true' if not specified 69 | # users.collaborations: 70 | # YAML map syntax mapping gist owners with other users who can access and 71 | # manipulate their gists 72 | ################################################################################ 73 | #gists: 74 | # root: /var/rcloud-gist-service/gists/ 75 | # lockTimeout: 30 76 | # keyservers: 77 | # default: 78 | # host: 127.0.0.1 79 | # port: 4301 80 | # realm: rcloud 81 | # url: http://{host}:{port}/valid?token={token}&realm={realm} 82 | # route: 83 | # redirect: 84 | # from: '/login/*' 85 | # to: 'http://example.com' 86 | # copyparams: true 87 | # users: 88 | # collaborations: 89 | # james: 90 | # - steve 91 | # - angela 92 | # grace: 93 | # - david 94 | # - hannah 95 | # - evan 96 | 97 | 98 | 99 | ################################################################################ 100 | # Logging configuration: 101 | # config: The logback configuration file for logging. 102 | # file: The log file to write the log out to. 103 | ################################################################################ 104 | logging: 105 | config: logback.xml 106 | file: /var/log/${spring.application.name}/${spring.application.name}-file.log 107 | -------------------------------------------------------------------------------- /rcloud-gistproxy-service/src/main/java/com/mangosolutions/rcloud/gists/filters/HeaderUrlRewritingFilter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.gists.filters; 8 | 9 | import static com.google.common.base.Preconditions.checkNotNull; 10 | import static com.google.common.collect.Collections2.filter; 11 | 12 | import java.util.Collection; 13 | 14 | import org.apache.commons.lang3.StringUtils; 15 | import org.slf4j.Logger; 16 | import org.slf4j.LoggerFactory; 17 | 18 | import com.google.common.base.Objects; 19 | import com.google.common.base.Predicate; 20 | import com.google.common.base.Throwables; 21 | import com.google.common.collect.ImmutableSet; 22 | import com.netflix.util.Pair; 23 | import com.netflix.zuul.ZuulFilter; 24 | import com.netflix.zuul.context.RequestContext; 25 | 26 | public final class HeaderUrlRewritingFilter extends ZuulFilter { 27 | 28 | private static final Logger log = LoggerFactory.getLogger(HeaderUrlRewritingFilter.class); 29 | 30 | public static final ImmutableSet DEFAULT_WHITELIST = ImmutableSet.of("Link", "Location"); 31 | 32 | private final ImmutableSet whitelist = DEFAULT_WHITELIST; 33 | 34 | private int order = 100; 35 | 36 | 37 | public HeaderUrlRewritingFilter(int order) { 38 | this.order = order; 39 | } 40 | 41 | @Override 42 | public String filterType() { 43 | return "post"; 44 | } 45 | 46 | @Override 47 | public int filterOrder() { 48 | return order; 49 | } 50 | 51 | @Override 52 | public boolean shouldFilter() { 53 | return containsHeaders(RequestContext.getCurrentContext()); 54 | } 55 | 56 | private static boolean containsHeaders(final RequestContext context) { 57 | assert context != null; 58 | return !context.getZuulResponseHeaders().isEmpty(); 59 | } 60 | 61 | @Override 62 | public Object run() { 63 | try { 64 | rewriteHeaders(RequestContext.getCurrentContext(), this.whitelist); 65 | } catch (final Exception e) { 66 | Throwables.propagate(e); 67 | } 68 | return null; 69 | } 70 | 71 | public ImmutableSet getWhitelist() { 72 | return this.whitelist; 73 | } 74 | 75 | private static void rewriteHeaders(final RequestContext context, final Collection whitelist) { 76 | assert context != null; 77 | ZuulRequestUrlResolver resolver = new ZuulRequestUrlResolver(); 78 | String zuulUrl = resolver.getZuulServiceUrl(context); 79 | String targetUrl = resolver.getProxiedServiceUrl(context); 80 | if(StringUtils.isNotBlank(zuulUrl) & StringUtils.isNotBlank(targetUrl)) { 81 | filterHeaders(context, whitelist, zuulUrl, targetUrl); 82 | } 83 | } 84 | 85 | private static void filterHeaders(final RequestContext context, final Collection whitelist, 86 | String originUrl, String targetUrl) { 87 | for (final Pair header : context.getZuulResponseHeaders()) { 88 | if (caseInsensitiveContains(whitelist, header.first())) { 89 | header.setSecond(header.second().replace(targetUrl, originUrl)); 90 | log.debug("Rewrote header: {} to {}", header.first(), header.second() ); 91 | } 92 | } 93 | } 94 | 95 | 96 | 97 | private static boolean caseInsensitiveContains(final Collection collection, final String value) { 98 | return !filter(collection, new CaseInsensitiveEqualityPredicate(value)).isEmpty(); 99 | } 100 | 101 | private static class CaseInsensitiveEqualityPredicate implements Predicate { 102 | 103 | private final String referenceValue; 104 | 105 | public CaseInsensitiveEqualityPredicate(final String referenceValue) { 106 | this.referenceValue = checkNotNull(referenceValue); 107 | } 108 | 109 | @Override 110 | public boolean apply(final String input) { 111 | return this.referenceValue.equalsIgnoreCase(input); 112 | } 113 | 114 | @Override 115 | public boolean equals(final Object obj) { 116 | if (obj == this) { 117 | return true; 118 | } 119 | if (obj instanceof CaseInsensitiveEqualityPredicate) { 120 | final @SuppressWarnings("unchecked") CaseInsensitiveEqualityPredicate that = (CaseInsensitiveEqualityPredicate) obj; 121 | return Objects.equal(this.referenceValue, that.referenceValue); 122 | } 123 | return false; 124 | } 125 | 126 | @Override 127 | public int hashCode() { 128 | return Objects.hashCode(this.referenceValue); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /rcloud-gist-service/README.md: -------------------------------------------------------------------------------- 1 | # Implementation of the RCloud Gist Service. 2 | A Java based service to provide GitHub gist functionality to RCloud. 3 | 4 | ## Building 5 | The code uses the Gradle build system and includes the gradle wrapper in the root 6 | of the project. The only requirement for building is a Java JDK version 7 or greater 7 | and an internet connection, all dependencies will be downloaded for the build. 8 | 9 | To build the software run the following command which runs the tests and generates 10 | the artifacts. 11 | 12 | `./gradlew build` 13 | 14 | ### Outputs 15 | The build generates 3 artifacts 16 | 1. An executable jar file created here: `./rcloud-rawgist-service/build/libs` 17 | 2. An rpm install file created here: `./rcloud-rawgist-service/build/distributions` 18 | 3. An deb install file created here: `./rcloud-rawgist-service/build/distributions` 19 | 20 | ## Installation 21 | 22 | The redhat and debian install archives will install the application to 23 | `/opt/rcloud-gist-service` and create an entry in the `/etc/init.d/` folder 24 | which can be used to start and stop the service. 25 | 26 | ### User and Groups 27 | The installation creates a user and group for the service called `rcloudgistservice` which the service runs as. 28 | 29 | ### Debian based systems 30 | To install the service on debian based systems the following command can be used, you will need to use the correct name for the deb file for the version you are installing. 31 | 32 | `sudo dpkg -i ./rcloud-rawgist-service_0.1.0-20170126123855_all.deb` 33 | 34 | ## Default ports 35 | The service uses two ports, one for the gist api and the other for the service management functionality, these can be controlled in configuration. The management port is secured using basic auth. 36 | * 13020 application port 37 | * 13021 management port 38 | 39 | ## Service Configuration 40 | 41 | Configuration is held within the `/opt/rcloud-gist-service/application.yml` file. 42 | The following parameters are configurable: 43 | 44 | | Property | Description | Default | 45 | |----------|-------------|---------| 46 | | `service.port` | The port that the gist api is accessible over | `13020` | 47 | | `management.port` | The port that the service management api is accessible over | `13021` | 48 | | `security.user.name` | The username that is required for basic auth access to the management port | `admin` | 49 | | `security.user.password` | The username that is required for basic auth access to the management port | If not specified the password is generated at service startup and can be identified in the `/var/log/rcloud-rawgist-service/rcloud-rawgist-service-file.log` file. The following command can be used to find the password. `cat /var/log/rcloud-rawgist-service/rcloud-rawgist-service-file.log | grep "Using default security"`. More information can be found on the [spring boot documentation.](http://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-monitoring.html) | 50 | | `gists.root` | The location that the gist repositories are stored | `/var/rcloud-gist-service/gists/` | 51 | | `gists.lockTimeout` | The timeout to acquire a lock on the gist to prevent concurrent modification | `30` | 52 | | `gists.keyserver.host` | The host for the session key server | `127.0.0.1` | 53 | | `gists.keyserver.port` | The port for the session key server | `4301` | 54 | | `gists.keyserver.realm` | The realm for the session key server | `rcloud` | 55 | | `gists.keyserver.url` | The URL template for the session key server | `http://127.0.0.1:4301/valid?token={token}&realm={realm}` | 56 | 57 | ### JVM Configuration 58 | The startup parameters for the JVM are stored in the conf file in the installation directory, this must have the same name as the jar file. 59 | 60 | 61 | ## Starting and stopping the service 62 | 63 | An System V startup script is installed as part of the installation, this supports the following commands: 64 | 65 | | Command | Example | 66 | |---------|--------------------------------------| 67 | | start | `service rcloud-gist-service start` | 68 | | stop | `service rcloud-gist-service stop` | 69 | | status | `service rcloud-gist-service status` | 70 | | restart | `service rcloud-gist-service restart`| 71 | 72 | ## Logging 73 | The service uses [Logback](https://logback.qos.ch/), this is controlled by the 74 | configuration file in the installation directory `/opt/rcloud-gist-service/logback.xml`, this configuration file can be updated and the changes will be reloaded to alter the log output. The service writes log files to `/var/log/rcloud-gist-service/` access to this folder is restricted to the `root` user and the `rcloudgistservice` user/group. 75 | 76 | ## TODO 77 | * Switch to using the git repository for looking things up rather than the file system. 78 | * Performance tests 79 | * Caching 80 | * Documentation 81 | -------------------------------------------------------------------------------- /rcloud-gist-service/src/main/java/com/mangosolutions/rcloud/rawgist/repository/git/BareRmCommand.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright (c) 2017 AT&T Intellectual Property, [http://www.att.com] 3 | * 4 | * SPDX-License-Identifier: MIT 5 | * 6 | *******************************************************************************/ 7 | package com.mangosolutions.rcloud.rawgist.repository.git; 8 | 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.util.Collection; 12 | import java.util.LinkedHashSet; 13 | 14 | import org.eclipse.jgit.api.GitCommand; 15 | import org.eclipse.jgit.api.errors.GitAPIException; 16 | import org.eclipse.jgit.api.errors.JGitInternalException; 17 | import org.eclipse.jgit.api.errors.NoFilepatternException; 18 | import org.eclipse.jgit.dircache.DirCache; 19 | import org.eclipse.jgit.dircache.DirCacheBuildIterator; 20 | import org.eclipse.jgit.dircache.DirCacheBuilder; 21 | import org.eclipse.jgit.internal.JGitText; 22 | import org.eclipse.jgit.lib.Constants; 23 | import org.eclipse.jgit.lib.FileMode; 24 | import org.eclipse.jgit.lib.Repository; 25 | import org.eclipse.jgit.treewalk.TreeWalk; 26 | import org.eclipse.jgit.treewalk.filter.PathFilterGroup; 27 | 28 | /** 29 | * Removes files from the bare git repository. This is based 30 | * upon the JGit RmCommand. 31 | */ 32 | public class BareRmCommand extends GitCommand { 33 | 34 | /** 35 | * patterns of files that should be removed from the repository. 36 | */ 37 | private Collection filepatterns; 38 | 39 | /** 40 | * The index file to update with the changes. 41 | */ 42 | private DirCache index; 43 | 44 | /** Only remove files from index, not from working directory */ 45 | private boolean cached = true; 46 | 47 | /** 48 | * Creates the command to perform the operation on the repository 49 | * @param repo the repository to operate on. 50 | * @param index the index file to change. 51 | */ 52 | public BareRmCommand(Repository repo, DirCache index) { 53 | super(repo); 54 | filepatterns = new LinkedHashSet(); 55 | this.index = index; 56 | } 57 | 58 | /** 59 | * Adds file patterns to be processed. 60 | * @param filepattern 61 | * repository-relative path of file to remove (with 62 | * / as separator) 63 | * @return {@code this} 64 | */ 65 | public BareRmCommand addFilepattern(String filepattern) { 66 | checkCallable(); 67 | filepatterns.add(filepattern); 68 | return this; 69 | } 70 | 71 | /** 72 | * Only remove the specified files from the index. 73 | * 74 | * @param cached 75 | * true if files should only be removed from index, false if 76 | * files should also be deleted from the working directory 77 | * @return {@code this} 78 | * @since 2.2 79 | */ 80 | public BareRmCommand setCached(boolean cached) { 81 | checkCallable(); 82 | this.cached = cached; 83 | return this; 84 | } 85 | 86 | /** 87 | * Executes the {@code Rm} command. Each instance of this class should only 88 | * be used for one invocation of the command. Don't call this method twice 89 | * on an instance. 90 | * 91 | * @return the DirCache after Rm 92 | */ 93 | public DirCache call() throws GitAPIException, 94 | NoFilepatternException { 95 | 96 | if (filepatterns.isEmpty()) { 97 | throw new NoFilepatternException(JGitText.get().atLeastOnePatternIsRequired); 98 | } 99 | checkCallable(); 100 | 101 | try (final TreeWalk tw = new TreeWalk(repo)) { 102 | index.lock(); 103 | DirCacheBuilder builder = index.builder(); 104 | tw.reset(); // drop the first empty tree, which we do not need here 105 | tw.setRecursive(true); 106 | tw.setFilter(PathFilterGroup.createFromStrings(filepatterns)); 107 | tw.addTree(new DirCacheBuildIterator(builder)); 108 | 109 | while (tw.next()) { 110 | if (!cached) { 111 | final FileMode mode = tw.getFileMode(0); 112 | if (mode.getObjectType() == Constants.OBJ_BLOB) { 113 | final File path = new File(repo.getWorkTree(), 114 | tw.getPathString()); 115 | // Deleting a blob is simply a matter of removing 116 | // the file or symlink named by the tree entry. 117 | delete(path); 118 | } 119 | } 120 | } 121 | builder.commit(); 122 | setCallable(false); 123 | } catch (IOException e) { 124 | throw new JGitInternalException( 125 | JGitText.get().exceptionCaughtDuringExecutionOfRmCommand, e); 126 | } finally { 127 | if (index != null) { 128 | index.unlock(); 129 | } 130 | } 131 | 132 | return index; 133 | } 134 | 135 | private void delete(File p) { 136 | while (p != null && !p.equals(repo.getWorkTree()) && p.delete()) { 137 | p = p.getParentFile(); 138 | } 139 | } 140 | 141 | } 142 | --------------------------------------------------------------------------------